- Event loop의 작동 원리에 대해서 이해한다.
정말 꼭 배워보고 싶었던 Event loop
!! 좋은 동영상도 보고, 자료도 많이 읽어봤지만 이렇게 블로깅을 하는 것은 처음이다. 내가 어떻게 생각하고 있는지 한 번 정리해보려고 한다.
위의 사진은 자바스크립트 엔진의 구조이다. (그 중에서도 V8엔진이다.) 그럼 각각 무슨 역할을 하는지 알아보자.
Memory Heap은 메모리 할당이 일어나는 곳이다.
Call Stack은 실행 될 코드를 한 줄 단위로 할당 한다.
Web APIs는 비동기 처리를 담당한다.
Callback Queue(안에 Task Queue, Event Queue등이 있음)는 비동기 처리가 끝난 후 실행해야 할 콜백 함수를 차례대로 할당한다.
Event Loop는 Queue에 할당된 함수를 순서에 맞춰 Call Stack에 할당해준다.
그럼 이제 각자의 역할을 알았으니 작동 원리를 살펴 보자.
console.log("시작");
setTimeout(() => {
console.log("중간");
}, 1000);
console.log("끝");
위의 코드는 어떤 순서로 실행이 될까?
먼저 호출 스택(콜 스택)에는 항상 코드들을 가지고 있는 anonymous(main)
가 들어간다. 이후에 첫번째로 찍히는 콘솔 ‘시작’이 찍힌다.
호출 스택이기 때문에 ‘시작’은 바로 호출이 되고, 그 다음 콘솔 ‘중간’이 온다. 하지만 비동기 함수이기 때문에 호출하지 않고 Web APIs
로 넘어간다.
(setTimeout의 두번째 인자가 1000이 아니라 0이여도 넘어간다.)
여기서가 중요하다! 콜백 큐(테스크 큐)에 있는 익명 함수는 항상 대기하고 있다가 호출 스택이 비워지면(전역 컨텍스트 anonymous(main)
의 실행이 종료되면) 그 때 함수를 하나씩 호출 스택으로 밀어 올린다.
그리고 마지막으로 콘솔 ‘중간’을 호출하면서 순서는 시작-끝-중간
순으로 출력한다.
그 다음 코드는 어떤 순으로 출력할까?
console.log("시작");
setTimeout(() => {
console.log("중간");
}, 0);
Promise.resolve().then(() => {
console.log("프로미스");
});
console.log("끝");
프로미스와 setTimeout의 순서는 현재 코드로는 판단할 수 없지만 setTimeout 먼저 실행된다고 가정한다. 그리고 setTimeout-프로미스 순으로 콜백 큐에 함수가 쌓일 예정이다.
그러면 호출 스택의 콘솔들이 다 호출 된 이후에는 예상대로 setTimeout이 호출 스택에 올라가고 프로미스가 그 다음으로 올라갈 것이라고 생각했다. 하지만 콜백 큐(테스크 큐)에는 우선순위가 존재했다..!!
사실 내가 알고 있는 콜백 큐안에는 3가지로 이루어져 있었다. 이 3가지에서 우선 순위가 있고 이 우선 순위대로 호출 스택에 쌓인다.
가장 먼저 프로미스는 Microtask Queue
에 속한다. 그리고 setTimeout은 Task Queue
에 쌓인다. 그렇기 때문에 콜백 큐에 setTimeout이 먼저 쌓여 있어도, 결국엔 프로미스먼저 호출을 한다는 뜻이다.
그래서 호출 순서는 시작-끝-프로미스-중간
순으로 출력한다.
참고 자료