마이크로 태스크 큐와 태스크 큐의 작업은 우선순위에 차이가 있다.
* **마이크로 태스크 큐**
* 우선순위가 **높다.**
* 한번의 이벤트 루프 사이클에 큐를 다 비운다.
* **태스크 큐**
* 우선순위가 낮다
* 한번의 이벤트 루프 사이클에 하나의 작업만 수행한다.
마이크로 태스크 큐는 한번의 루프 사이클에 큐를 다 비우므로, 다르게 말하면 **마이크로 태스크 큐가 비워지기 전까지는 계속해서 마이크로 태스크 큐의 작업들이 실행되고 다른 곳의 작업들은 실행되지 않는다.**
현재 이벤트 루프에서 처리 중인 마이크로 태스크 작업 중간에 새로 추가된 마이크로 태스크가 있다면, **새로 추가된 마이크로 태스크는 현재 처리 중인 마이크로 태스크 큐의 뒤에 추가되고 현재 루프 사이클 내에서 이어서 처리된다.**
태스크의 경우에는 마이크로 태스크 작업이 모두 끝난 다음 루프 사이클마다 하나씩 처리된다.
**마이크로 태스크의 경우에는 한번의 루프 사이클에서 큐를 모두 비우지만**, **태스크의 경우에는 한 번의 루프 사이클에서 하나의 태스크만 처리한다**는 차이점이 있다.
***
마이크로 태스크 작업 중간에 계속해서 마이크로 태스크가 추가되는 아래 코드의 실행 결과를 보면 마이크로 태스크가 모두 실행된 이후에야 태스크가 실행된다.
```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에서 실행