Stack이 비어있을 때 Microtask Queue를 먼저 확인하고 그 안의 작업을 모두 처리합니다. 이후 Macrotask Queue에서 하나의 작업을 꺼내 Stack으로 올려 실행합니다. 이 순서를 런타임 동안 계속 반복하기 때문에 이벤트루프라고 칭합니다.
일반적인 비동기 작업이 들어가는 큐입니다. 대표적인 예로는 setTimeout, setInterval, setImmediate(Node.js)와 같은 타이머 함수나, 브라우저의 I/O 작업이 있습니다.
우선순위가 높은 비동기 작업을 위한 큐입니다. Promise.then, catch, finally, MutationObserver, queueMicrotask 등이 해당되며, Macrotask Queue보다 우선순위가 높습니다.
console.log('A');
new Promise((resolve) => {
console.log('B');
resolve('C');
}).then((value) => console.log(value));
setTimeout(() => console.log('D'), 0);
Promise.resolve('E').then((res) => {
console.log('F');
setTimeout(console.log, 0, res);
});
console.log('G');
동작 과정을 보기 전에 먼저 풀어보세요!
console.log('A') 는 동기 코드이기 때문에 Call Stack에 쌓인 후 바로 실행 됩니다.(resolve) ⇒ { … }) 함수가 Call Stack에 쌓이고 해당 함수는 동기 코드이기 때문에 바로 실행됩니다. console.log('B') 는 바로 실행 됩니다.resolve('C') 는 Promise 비동기 코드로, 마이크로 태스크큐에 추가됩니다.setTimeout(() => console.log('D'), 0); 이 매크로 태스크큐에 추가됩니다.Promise.resolve('E') 가 마이크로 태스크큐에 추가됩니다.console.log('G') 는 동기 코드이기 때문에 Call Stack에 쌓인 후 바로 실행 됩니다.
resolve('C') 의 콜백인 (value) => console.log(value) 를 Call Stack에 추가하고, C를 출력합니다.Promise.resolve('E') 의 콜백이 Call Stack에서 실행됩니다.console.log('F') 가 실행되어 F가 출력됩니다.setTimeout(console.log, 0, res); 가 실행되어 console.log('E') 가 매크로 태스크큐에 등록됩니다.
setTimeout(console.log, 0, res) 의 콜백인 console.log('E'); 가 추가되고 E가 출력됩니다.A - B - G - C - F - D - E 순으로 모든 코드가 출력됩니다.본 코드의 동작 과정은 https://www.jsv9000.app 에서 스텝별로 자세히 확인해 볼 수 있습니다.