이벤트 루프의 동작을 정리하고,
비동기 코드의 동작 순서를 정리합니다.
🌸 잘못 이해하고 있는 내용이 있다면 알려주세요. 감사합니다 🌸
목차
- ko.javascript.info/event-loop 본문 예시 코드
- 코드의 실행 순서
- 콜스택의 상태
- 이벤트 루프와 마이크로 태스크 큐, 매크로 태스크 큐
자바스크립트 튜토리얼 [이벤트 루프] 카테고리 이해하기
- '특정 태스크'란?
- 렌더링 시점
- 반복문 내의 DOM 조작은 렌더링과 관련이 있는 걸까?
들어가기 전에, 기억해야 할 내용입니다.
- 콜스택이 비어야 태스크 큐의 작업이 콜스택으로 이동합니다.
- 태스크 큐의 종류
(1) 마이크로 태스크 큐 (빨리 처리되는 후속 작업. then, resolve 등)
(2) 매크로 태스크 큐 (setTimeout 등)
1. ko.javascript.info/event-loop 본문 예시 코드
https://ko.javascript.info/event-loop
setTimeout(() => alert("timeout"));
Promise.resolve()
.then(() => alert("promise"));
alert("code");
2. 코드의 실행 결과 (순서 확인)
"code"
"promise"
"timeout"
3. 콜스택의 상태
여기서 드는 의문
setTimeout이 호출되고, 콜백인 () => alert("timeout")이 매크로 태스크큐에 들어간 그 시점!!!
딱 콜 스택이 비어있는 상태라고 가정하면, 바로 실행되어야 하지 않는건가?
왜? 콜스택은 현재 비어있는 상태 아닌가?
setTimeout의 딜레이 시간이 4ms 있기 때문에 실행되지 않는건가?
이벤트 루프의 개념을 다시 살펴봅니다.
동기적으로 실행해야 할 작업이 남아있다면, 이벤트 루프는 실행되지 않습니다.
따라서, alert까지 모두 실행된 이후. 즉, 동기적으로 실행되는 코드가 없을 때 까지 태스크큐의 작업들은 실행되지 않았기 때문에 "timeout"이 먼저 출력되지 않았던 것이었어요.
4. 이벤트 루프와 마이크로 태스크 큐, 매크로 태스크 큐
"code"까지 실행된 이후 왜 "timeout"이 아니라, "promise"일까?
이벤트 루프는 마이크로 태스크 큐와 매크로 태스크 큐 중에 마이크로 태스크 큐에 있는 작업들을 더 먼저 콜스택으로 이동하여 실행합니다.
이벤트 루프는 더 빠르게 후속 처리될 수 있는 작업들을 먼저 실행합니다.
자바스크립트 튜토리얼 [이벤트 루프] 카테고리에 나온 개념 이해하기
1. '특정 태스크'란?
엔진이 특정 태스크를 처리하는 동안엔 렌더링이 절대 일어나지 않습니다. 태스크를 처리하는 데 걸리는 시간이 길지 않으면 이는 전혀 문제가 되지 않습니다. 처리가 끝나는 대로 DOM 변경을 화면에 반영하면 되기 때문입니다. (https://ko.javascript.info/event-loop#ref-684)
여기서 말하는 특정 태스크란 어떤 내용일까? 콜스택에 들어간 한 단위? 블록 단위? for문? 함수 호출?
특정 태스크란,
JavaScript 엔진이 콜 스택에서 처리하는 모든 작업을 의미합니다.
JavaScript 엔진은 콜 스택이 비어 있을 때만 브라우저에게 화면을 다시 그릴 기회를 줍니다.
즉, 콜 스택이 비어 있지 않으면 브라우저는 화면을 다시 그릴 수 없습니다.
그리고 특정 태스크가 처리되었다는 말의 의미는, 동기적으로 실행되는 모든 작업이 완료되었다는 것을 의미합니다.
2. 렌더링 시점
https://ko.javascript.info/event-loop#ref-686
다음은, 위의 예시 코드를 변형한 코드입니다.
궁금했던 점: 실제로 'start'가 렌더링되는 시점이 언제일까? (1) for루프 이전? (2) 함수 종료 후?
<div id="start"></div>
<div id="progress"></div>
<div id="end"></div>
<script>
function count() {
start.innerHTML = 'start'
for (let i = 0; i < 1e6; i++) {
i++;
progress.innerHTML = i;
}
end.innerHTML = 'end'
}
count();
</script>
실행 결과, 렌더링 시점은 (2) 함수 종료 후 였습니다.
자바스크립트는 단일 스레드로 실행되기 때문에,
콜스택의 작업과 렌더링 작업은 동시에 진행되지 않아서 이런 결과가 도출되었습니다.
그리고 이러한 이유로, 1부터 1e6까지 innerHTML로 작성하더라도, 변화되는 과정 1, 2, 3, ... 이 보이지 않고, 사용자는 마지막 결과만 보게 됩니다. 999999
따라서, 숫자가 변화하는 과정을 사용자가 보려면(프로그래스바), 콜스택의 작업이 완료된 이후에 렌더링 작업을 하면 됩니다. 그래서 예시처럼, 비동기 로직인 setTimeout을 사용해서 콜스택을 비우고, 렌더링을 해줄 수 있습니다.
3. 반복문 내의 DOM 조작 은 렌더링과 관련이 있는 걸까?
반복문 내에서 DOM을 직접 조작하지 않아야 하는데, 왜일까?
렌더링이 가장 마지막에 일어나기 때문에 반복문 내에서 DOM 을 조작하더라도, 렌더링은 한번만 일어나는것 외에 더 추가적인 작업이 무엇일까?
DOM이 변경될 때마다, reflow와 repaint 작업이 예약되는 과정이 있는데, 해당 연산에 드는 비용과 관련된 것 같아서 자세한 내용은 따로 알아봐야 할 것 같습니다.
'Front-End > JavaScript' 카테고리의 다른 글
좋은 코드, 나쁜 코드 프로그래머의 코드 개선법 (0) | 2024.02.17 |
---|---|
fetch axios header proxy Proxy URL CORS까지 (1) | 2023.12.11 |
fetch (0) | 2023.10.31 |
31장 RegExp (모던 자바스크립트 Deep Dive) (0) | 2023.06.08 |
35장 스프레드 문법 36장 디스트럭처링 할당 (모던 자바스크립트 Deep Dive) (0) | 2023.06.05 |