Q3. 만약 아래 코드처럼 Promise.then이 자기 자신을 계속 재귀 호출하는 무한 루프가 돈다면, 브라우저 화면(UI)은 어떻게 될까요? (사용자가 버튼을 클릭하거나 스크롤을 할 수 있을까요? 아니면 멈출까요?)
function loop() {
Promise.resolve().then(loop); // 무한히 마이크로태스크를 추가함
}
loop();
예상 결과: 브라우저 화면(UI)은 완전히 멈춥니다 (Freezing). 사용자의 클릭이나 스크롤에도 전혀 반응하지 않게 됩니다.
콜스택에 loop() 들어가고 실행됨.
자바스크립트 엔진이 loop() 함수를 Microtask Queue에 담습니다.
콜스택은 비었기 때문에 이벤트 루프에 의해 Microtask Queue에 있는 태스크를 스택에 적재합니다.
이 과정을 무한히 반복하게 되면
Microtask Queue는 비어 있을 수가 없습니다. 그러면 그 아래 순위인 사용자가 버튼을 클릭하거나 스크롤을 하는 Task Queue에 접근도 못하고, 렌더링 단계로 진입하지 못하기 때문에 화면이 그대로 멈춰버리게 됩니다.
Q4. 반대로 setTimeout을 사용해서 무한 재귀 호출을 한다면 어떻게 될까요? (setTimeout 안에 setTimeout을 계속 넣는 경우)
function loop() {
setTimeout(loop, 0); // 무한히 태스크를 추가함
}
loop();
예상 결과: 화면이 아예 멈추지는(Freezing) 않지만, 심각한 버벅임(Lag)이 발생하며 CPU 팬 소음이 커지고 배터리 소모가 급증합니다.
개념적으로 setTimeout은 태스크 큐(Macrotask Queue)를 사용합니다. 태스크 큐의 작업은 이벤트 루프가 한 바퀴 돌 때마다 하나씩 꺼내져 실행됩니다. 즉, 다음 재귀 호출이 실행되기 전에 '렌더링을 할 수 있는 틈(Opportunity)'과 '사용자 입력을 처리할 수 있는 틈'이 존재합니다.
실적으로 무한 루프는 CPU에 막대한 부하를 주지만, 모던 브라우저는 이를 방지하기 위한 안전장치를 가지고 있습니다.
HTML Living Standard 스펙에 따르면, 타이머 중첩(Nesting)이 5회 이상 깊어지면 브라우저는 강제로 **최소 4ms 이상의 지연 시간(Clamping)**을 추가합니다.
- setTimeout(..., 0)이라고 작성해도 실제로는 4ms마다 실행됩니다.
- 이 4ms라는 짧은 시간 동안 CPU는 숨을 돌리고, 브라우저는 렌더링을 수행하고, 유저 입력을 받아낼 수 있습니다.


반면 Promise는 자바스크립트 엔진(V8 등)이 직접 관리하는 Native 객체이며 마이크로태스크 큐를 사용합니다. 브라우저의 스케줄링(4ms 제한 등) 개입 없이 엔진 레벨에서 즉시 처리되므로, 큐가 비워질 때까지 나노초 단위로 몰아치며 UI 스레드를 완전히 점유(Blocking)해버립니다.
출처)
https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timer-initialization-steps
'CS 질문' 카테고리의 다른 글
| [Deep Dive CS- Q7, Q8, Q9] setTimeout, await/async, promise 에서의 에러 처리 (0) | 2025.12.15 |
|---|---|
| [Deep Dive CS- Q5,Q6] Iframe과 Event Loop (0) | 2025.12.15 |
| [Deep Dive CS- Q2] - 실행결과 (0) | 2025.12.15 |
| [Deep Dive CS- Q1] Javascript Run-to-completion, Event Loop (0) | 2025.12.15 |
| Deep Dive CS 질문 리스트 1 (0) | 2025.12.15 |