Web/[JS] Common

Micro Task vs Macro Task

ihl 2021. 8. 3. 18:09

Browser Event Loop

  JavaScript로 비동기 작업을 JS 런타임에서 처리 후 연결된 콜백 함수를 JS 엔진의 콜스택으로 적절한 타이밍에 적재시키기 위한 장치가 Event Loop이다. 이벤트 루프에 의해 JS 엔진의 콜스택에 적재되기 전 콜백함수가 대기하고 있는 곳을 Callback Queue 혹은 Task Queue라고 한다. 태스크 큐는 2가지 종류의 우선순위 큐로 구성되어있으며, 두 개의 큐 간에도 우선순위가 존재한다.

 

setTimeout(() => {
    console.log('A');
}, 0);

Promise.resolve()
.then(() => {
    console.log('B');
})
.then(function() {
    console.log('C');
});

console.log('D');

  위 코드의 출력결과는 무엇일까? 만약 태스크 큐가 하나고, 선입선출이라면 setTimeout과 Promise 모두 실행되자마자 끝나므로 콜백함수들이 순서대로 태스크 큐에 담기게 되어 D > A > B > C 순서대로 출력될 것이다. 그러나 코드를 실제 실행해보면 D > B > C > A 순으로 출력된다. 즉, Promise 의 then 안에 있는 함수가 좀 더 우선 순위가 높은 것이다.

 

 

1. Task

Macro Task Queue: setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI Rendering
Micro Task Queue: process.nextTick, Promise, Object.observe, MutationObserver

  Task의 종류는 Macro Task와 Micro Task 2가지이다. 각 테스크에 담길 콜백함수는 어떤 비동기 함수의 콜백함수인가에 따라 달라진다. 예를 들어 setTImeout의 콜백함수는 Macro Task Queue(Task Queue라고도 한다.)에 담긴다. 반면 Promise의 콜백함수는 Micro Task Queue에 담긴다. 그리고 Macro Task Queue 보다 Micro Task Queue의 우선순위가 높다. 따라서 위 코드에서 Promise의 콜백함수가 먼저 실행된 것이다.

 

 

2. New Event Loop Process

1. Macro Task Queue에서 가장 오래된 작업 하나를 실행한다.
2. Micro Task Queue에 있는 모든 작업을 실행한다.
3. 1단계로 이동한다.

  Event Loop는 위와 같은 단계로 수행된다. 그런데 위 순서대로라면 setTimeout이 먼저 실행되는 것이 아닐까? 사실 Task Queue는 콜백 함수만 담기는 공간은 아니다. 콜백 함수가 아닌 Script 태그 내의 모든 JS 코드도 Macro Task에 포함되기 때문이다. 즉, 동기 작업이 모두 실행된 후 먼저 Micro Task Queue에 포함된 콜백 작업을 수행하고, Macro Task Queue에 포함된 콜백 작업을 실행하는 것이다.

 

 

Task Queue and Call Stack

  코드의 작업들은 위와 같이 Task Queue에 담기게 된다. 이 중 JS 코드 내의 동기 작업은 Run Script에 포함된다. 이제 코드를 하나씩 실행해보자.

 

Step 1

  우선 Macro Task Queue에 있는 가장 오래된 작업 하나를 실행한다. 따라서 Console에 D가 찍힌다.

 

Step2-1
Step2-2

  그 후 Engine의 Stack이 비어있다면 이벤트 루프에 의해 콜백함수가 실행될 차례이다. Micro Task Queue에 있는 모든 작업을 실행한다.

 

Step 3

  이제 Macro Task Queue에 있는 setTimeout의 콜백함수가 실행된다.

 


이벤트루프 테스크큐 과정: https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

event loop: https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context

macro/micro: https://baeharam.netlify.app/posts/javascript/JS-Task%EC%99%80-Microtask%EC%9D%98-%EB%8F%99%EC%9E%91%EB%B0%A9%EC%8B%9D

event loop: https://meetup.toast.com/posts/89

event loop: https://javascript.info/event-loop