Event Loop는 브라우저에 존재하는 여러 Queue들에 우선순위를 부여해 어떤 task를 먼저 수행할지 결정한다. 그런데 아래의 그림을 보면 태스크 큐 외에도 다른 큐들이 있다. 그래서 이에 대해서도 정리해보려고 한다.
우리가 기존에 알고 있던 Task Queue 는 뒤에서 설명한 Microtask Queue 와 구별하기 위해 Macrotask Queue 라고도 부른다.
Task Queue 는 Web API 가 수행한 비동기 함수를 넘겨받아 Event Loop 가 해당 함수를 Call Stack 에 넘겨줄 때까지 비동기 함수들을 쌓아놓는 곳이다.
이 큐는 setTimeout(), setInterval(), setImmediate()와 같은 task를 넘겨받는다.
Microtask Queue는 Promise나 async/await, process.nextTick, Object.observe, MutationObserver과 같은 비동기 호출을 넘겨받는다. Microtask의 우선순위는 일반 task(또는 Macrotask)보다 더 높다.
아래 예시처럼, Promise 로 비동기 호출을 하면 해당 작업은 Microtask Queue 에 쌓이게 되는데, Microtask 는 setTimeout 과 같은 일반 Task 보다 높은 우선순위를 가지고 있어서, Promise 함수의 내용이 setTimeout 함수의 내용보다 더 먼저 출력되는 것을 확인할 수 있다.
여기를 클릭하면 아래 코드의 동작 과정을 애니메이션으로 확인할 수 있다.
// 1. 실행
console.log('script start')
// 2. task queue로 전달
setTimeout(function() {
// 8. task 실행
console.log('setTimeout')
}, 0)
// 3. microtask queue로 전달
Promise.resolve()
.then(function() {
// 5. microtask 실행
console.log('promise1')
// 6. microtask queue로 전달
})
.then(function() {
// 7. microtask 실행
console.log('promise2')
})
// 4. 실행
console.log('script end')
Promise가 Microtask Queue로 전달되는 과정
async/await이 Microtask Queue로 전달되는 과정
ㄴ myFunc 함수 안의 두번째 줄이 실행되었을 때, one 함수는 콜 스택에서 pop되어 promise를 반환한다. → promise가 반환되었을 때 마주하는 것은 await 키워드인데, 이 경우 async 함수의 실행은 미뤄진다. → async 함수의 나머지 부분들을 실행하는 것은 Microtask Queue로 넘겨진다.
Animation Frames는 requestAnimationFrame과 같이 브라우저 렌더링과 관련된 task를 넘겨받는 Queue이다. 우선 순위는 Microtask보다는 낮고, (Macro)Task보다는 높다.
// 1. 실행
console.log("script start");
// 2. task queue로 전달
setTimeout(function () {
// 10. task 실행
console.log("setTimeout");
}, 0);
//3. microtask queue로 전달
Promise.resolve()
.then(function () {
// 6. microtask 실행
console.log("promise1");
}) // 7. microtask queue로 전달
.then(function () {
// 8. microtask 실행
console.log("promise2");
});
//4. AnimationFrame으로 전달
requestAnimationFrame(function () {
//9. animation frame 실행
console.log("animation");
});
//5. 실행
console.log("script end");
✔️ 이벤트 루프가 비동기 작업을 처리하는 우선순위
Microtask Queue > Animation Frames > Task Queue
이벤트 루프는 Microtask Queue나 Animation Frames를 방문할 때는, 큐 안에 있는 모든 작업들을 수행하지만, Task Queue를 방문할 때는 한 번에 하나의 작업만 call stack으로 전달하고 다른 Queue를 순회한다.