마이크로 태스크 큐와 태스크 큐의 작업은 우선순위에 차이가 있다. * **마이크로 태스크 큐** * 우선순위가 **높다.** * 한번의 이벤트 루프 사이클에 큐를 다 비운다. * **태스크 큐** * 우선순위가 낮다 * 한번의 이벤트 루프 사이클에 하나의 작업만 수행한다. 마이크로 태스크 큐는 한번의 루프 사이클에 큐를 다 비우므로, 다르게 말하면 **마이크로 태스크 큐가 비워지기 전까지는 계속해서 마이크로 태스크 큐의 작업들이 실행되고 다른 곳의 작업들은 실행되지 않는다.** 현재 이벤트 루프에서 처리 중인 마이크로 태스크 작업 중간에 새로 추가된 마이크로 태스크가 있다면, **새로 추가된 마이크로 태스크는 현재 처리 중인 마이크로 태스크 큐의 뒤에 추가되고 현재 루프 사이클 내에서 이어서 처리된다.** 태스크의 경우에는 마이크로 태스크 작업이 모두 끝난 다음 루프 사이클마다 하나씩 처리된다. **마이크로 태스크의 경우에는 한번의 루프 사이클에서 큐를 모두 비우지만**, **태스크의 경우에는 한 번의 루프 사이클에서 하나의 태스크만 처리한다**는 차이점이 있다. *** 마이크로 태스크 작업 중간에 계속해서 마이크로 태스크가 추가되는 아래 코드의 실행 결과를 보면 마이크로 태스크가 모두 실행된 이후에야 태스크가 실행된다. ```javascript Promise.resolve().then(() => { console.log('🔴 마이크로1'); Promise.resolve().then(() => { console.log('🔴 마이크로1-1'); Promise.resolve().then(() => console.log('🔴 마이크로1-1-1')); }); }); Promise.resolve().then(() => console.log('🔴 마이크로2')); setTimeout(() => console.log('🔵 태스크: 첫번째'), 0); setTimeout(() => console.log('🔵 태스크: 두번째'), 0); ``` ![[e472bf9e-5bab-453d-a595-a9ec48cee94a.png]] *** 복잡한 비동기 작업이 섞인 경우도 살펴보자. ```javascript console.log('🟡 동기: 1'); setTimeout(() => { console.log('🔵 태스크1: setTimeout'); Promise.resolve().then(() => console.log('🔴 태스크1 안의 마이크로태스크')); }, 0); Promise.resolve().then(() => { console.log('🔴 마이크로1'); setTimeout(() => console.log('🔵 마이크로1 안의 태스크'), 0); }); queueMicrotask(() => console.log('🔴 마이크로2: queueMicrotask')); setTimeout(() => console.log('🔵 태스크2: setTimeout'), 0); console.log('🟡 동기: 2'); ``` ![[fe4e2cdc-3b56-4218-b865-a09557c55618.png]] a. 초기 동기 코드 실행 1. `console.log('🟡 동기: 1')` → **Call Stack**에서 즉시 실행 2. `setTimeout(태스크1)` → Web API로 이동, 완료 후 **Task Queue**에 콜백 추가 3. `Promise.resolve().then(마이크로 1)` → **Microtask Queue**에 콜백 추가 4. `queueMicrotask(마이크로 2)` → **Microtask Queue**에 콜백 추가 5. `setTimeout(태스크2)` → Web API로 이동, 완료 후 **Task Queue**에 콜백 추가 6. `console.log('동기: 2')` → **Call Stack**에서 즉시 실행 b. 첫번째 마이크로태스크 큐 실행 7. **Event Loop가 Call Stack이 비어있음을 확인** 8. Microtask Queue 확인 ⇒ **\[마이크로 1, 마이크로 2]** 9. **마이크로 1** → Call Stack에서 실행\ `setTimeout(마이크로1 안의 태스크, 0)` → Web API로 이동, 완료 후 **Task Queue**에 콜백 추가 10. **마이크로 2** 실행 → Call Stack에서 실행 c. 첫번째 태스크 실행 12. **Event Loop가 Microtask Queue가 비어있음을 확인** 13. **Task Queue**에서 **태스크 1** 가져옴 → → Call Stack에서 실행\ `Promise.resolve().then(태스크1 안의 마이크로태스크)` → **Microtask Queue**에 콜백 추가 d. 두번째 마이크로태스크 큐 실행 12. **Event Loop가 Call Stack이 비어있음을 확인** 13. Microtask Queue 확인 ⇒ **\[태스크1 안의 마이크로태스크]** 14. **태스크1 안의 마이크로태스크** → Call Stack에서 실행 e. 남은 태스크 실행 12. **Event Loop가 Microtask Queue가 비어있음을 확인** 13. **Task Queue**에서 **태스크 2** 가져옴 → Call Stack에서 실행 14. **Event Loop가 Microtask Queue가 비어있음을 확인** 15. **Task Queue**에서 **마이크로1 안의 태스크** 가져옴 → Call Stack에서 실행