자바스크립트는 코드를 실행할때 Stack
에 함수를 쌓고 연계된 다른 함수가 있으면 그 함수도 Stack
에 쌓는 식으로 코드를 실행하다가 쌓는 역순으로 스택에서 빼내며 결과를 반환해 나간다.
이때 setTimeout
같은 Web API는 Stack
이 아닌 Web API(s)로 빼내 설정한 타이머를 돌린다.
그리고 지정된 시간이 되면 이 타이머의 콜백 함수를 바로 Stack
에 쌓아 실행시키는 것이 아닌 Task Queue
라는 곳에 보냈다가 Stack이 빌때, Event Loop
를 통해 Stack으로 이동하고 해당 콜백 함수가 실행된다.
여기서 이 이벤트 루프는 단순히 Task Queue
에 있는 것들을 Stack
이 비었을때 Stack
으로 보낼뿐인 아주 간단한 작업을 하는 기능인데 이 이벤트 루프가 실행되는 조건인 Stack이 비었을때 Task Queue에서 Stack으로 이동시켜 실행한다는 점 때문에 원하지 않는 결과가 발생할 수 있다.
예를 들어
const logging = () => {
console.log('a');
setTimeout(()=>{
console.log('b');
}, 0);
console.log('c');
}
logging(); // 'a', 'c', 'b' 순으로 로그가 남는다.
위와 같은 상황에서 바로 콘솔로그 사이에 있는 setTimeout
에서 설정한 시간이 0밀리초니까 abc
순서대로 로그가 남을 것 같지만 전술한 것 처럼 setTimeout
은 웹API에서 Task Queue
로 보내는 시간만 정해주고 이벤트 루프가 Stack
으로 보내 실행시키는 역할을 하므로 로그는 acb
순으로 남는다.
또 다른 경우로 setTimeout
의 두번재 인자로 1000밀리초를 주었을때, 어떠한 경우에도 1초 후에 콜백 함수가 실행이 되어야 할 것 같지만 재귀나 데이터를 받아온다던가 하는 것의 이유로 콜스택이 비워지지 않는다면 1초는 무슨 해당 함수가 종료되지 않는 한 콜백함수는 실행되지 않을 것이다.
여기까지 왔으면 이벤트 루프를 막지말라는 뜻이 무엇인지 알 수 있을 것이다.
조금만 더 나아가서 브라우저는 16.6밀리초, 1초에 60번씩 repainting
하는데, 이 repainting
은 이벤트 루프를 통해서 실행된다.
다만 Web API와 차이는 repainting
이 Queue에 있다면 이벤트 루프는 Task Queue에 대기중인 콜백 함수가 있더라도 이 repainting
을 가장 먼저 Stack
으로 보내 실행시킨다.
덕분에 Task Queue
가 범람하든 말든 렌더는 정상적으로 이루어지지만 문제는 Stack에서 어떤 놈이 버티고 있을때이다.
Stack
이 비워져야 이벤트 루프가 작동을 할텐데 이 조건이 충족되지 않으니 렌더를 못하게 되고 결과적으로 브라우저 화면이 멈추게 되는 것이다.
고로 누군가에게 이벤트 루프를 막지 말라는 조언을 들었다면 지금 콜 스택에 누가 자리잡고 안비켜주는지 확인 하라는 뜻과 비슷하게 생각하면 될 듯 하다.