해결된 질문
작성
·
186
1
안녕하세요 훌륭한 강의 덕분에 Svelte를 잘 학습하고 있습니다. '반응성 구문' 학습 도중 잘 이해가 가지 않는 부분이 있어 질문을 남깁니다.
먼저 반응성 구문은 tick을 적용하지 않는다면, 화면이 한 번 갱신되고 난 후에 실행이 된다고 이해했습니다.
그런데, 선생님께서 보여주신 예제에서는 tick()을 적용하지 않은 상태에서도 화면 상의 double 값이 0 => 2로 변화하였습니다. 이에 의문이 남아 아래의 코드와 같은 실험을 해보았습니다. Assign 버튼을 클릭하였을 때 제가 예상한 작동 순서는 다음과 같습니다.
0. assign 함수 실행
1. count ++
2. console.log(double) => 콘솔 상에 0 출력, 아직 화면이 갱신되지 않았으니 반응성 구문 실행 x
3. assign 함수 종료
4. 화면 갱신
5. 화면이 갱신되었으니, count값에 의존하고 있는 반응성 구문 실행
-- 여기서부터 반응성 구문--
6. count가 1로 증가한 상태로 화면이 갱신되었으니 'id = count'인 태그는 1 출력
7. double에는 아직 새로운 값이 할당되지 않았으니 'id = double'인 태그는 0 출력
8. 'double = count * 2' 문장 실행 : double = 2
9. 문자열 'double' 출력
하지만 제 예상과는 다르게 'double = count * 2' 문장이 실행되기도 전에,
let double_ = document.getElementById("double");
console.log(double_);
으로 인한 결과 값이 <h2 id="double">2</h2>로 출력되었습니다.
즉, double이라는 변수가 2로 변경되기도 전에 화면 상의 double은 2로 렌더링 되었습니다.
위와 같은 현상의 원인이 무엇인지 궁금합니다. (소스코드는 아래에 텍스트로 남기겠습니다. )
다시 한 번 양질의 강의에 감사의 말씀 드립니다.
코드
<script>
import { tick } from "svelte";
let count = 0;
let double = 0;
$: {
let count_ = document.getElementById("count");
let double_ = document.getElementById("double");
console.log(count_);
console.log(double_);
double = count * 2;
console.log("double!");
}
async function assign() {
count++;
console.log(double);
}
</script>
<button on:click={assign}> Assign</button>
<h2 id="count">{count}</h2>
<h2 id="double">{double}</h2>
답변 2
2
0
이준석 님 안녕하세요.
현상에 대해 간단하게 설명드리면,
Svelte는 반응형 데이터(count, double)의 최적화 실행을 위해 처리할 로직을 모아서 한 번에 실행합니다.
따라서 이해하신 코드의 흐름대로 처리되지 않습니다.
특히 count_, double_ 변수는 단순히 DOM 요소를 참조하는 것이기에, 이미 바뀐 결과가 출력되는 것이죠.(이것은 Svelte가 아닌 JavaScript DOM의 특징입니다)
그래서 실행 흐름을 작성하자면 다음과 같습니다.
1. assign 함수 실행
2. count++
3. console.log(double)
4. assign 함수 종료
5. 반응성 구문($:) 실행 시작
6. console.log(count_) => <h2 id="count">0</h2>
7. console.log(double_) => <h2 id="double">0</h2>
8. 반응성 구문($:) 실행 완료
9. 화면 갱신
위 흐름의 6번과 7번에서는 분명 요소는 0을 가집니다.
화면 갱신은 가장 마지막에 일어나기 때문인데요.
콘솔에는 <h2 id="count">1</h2>과 <h2 id="double">2</h2>가 출력되는 것은 위에서 말씀드린 것처럼 단순히 해당 요소를 참조만 하고 있기 때문에 최종 결과만 보이는 것입니다.
그래서 console.log(count_)가 아닌 console.log(count_.textContent)와 같이 출력하면 0이 나옵니다.
반응성 구문을 다음과 같이 작성해서 테스트해 보세요.
$: {
let count_ = document.getElementById("count");
let double_ = document.getElementById("double");
if (count_ && double_) {
console.log(count_.textContent);
console.log(double_.textContent);
}
double = count * 2;
console.log("double!");
}
결국 질문하신 것처럼 원하는 순서대로 실행하려면 다음과 같이 작성할 수 있습니다.
<script>
import { tick } from "svelte";
let count = 0;
let double = 0;
$: {
updateDouble(count);
}
async function updateDouble() {
await tick()
let count_ = document.getElementById("count");
let double_ = document.getElementById("double");
if (count_ && double_) {
console.log(count_.textContent);
console.log(double_.textContent);
}.
double = count * 2;
console.log("double!");
}
async function assign() {
count++;
console.log(double);
}
</script>
위 내용 확인해 보시고 혹시 이해가 되지 않으시면 다시 질문 남겨주세요~
좋은 하루 보내세요~😉