03.24.2024
0. Background
요즘 코딩 컨텐츠 검수 아르바이트를 하는 중인데 그 곳에서 알게된 개발자님이 컨텐츠 중 한 문제를 보내주셔서 풀어본 문제를 정리해보려 한다.
1. 코드
function a() {
console.log('a1');
b();
console.log('a2');
}
function b() {
console.log('b1');
c();
console.log('b2');
}
async function c() {
console.log('c1');
setTimeout(() => console.log('setTimeout'), 0);
await d();
console.log('c2');
}
function d() {
return new Promise(resolve => {
console.log('d1');
resolve();
console.log('d2');
}).then(() => console.log('then!'));
}
a();
2. 정답
a1
b1
c1
d1
d2
b2
a2
then!
c2
setTimeout
3. 마이크로 태스크와 매크로 태스크
3-1. 마이크로 태스크(Micro Task)
- 현재 수행 중인 작업이 끝난 뒤에 이어서 실행될 작업(콜백)을 말한다.
- FIFO의 구조이다.
- 콜스택이 비어있을 때 실행된다. -> 메인 코드가 다 끝나야 실행이 된다.
- then(), catch(), finally()
3-2. 매크로 태스크(Macro Task)
- 콜스택의 작업이 끝난 후에 실행되는 작업을 말한다.
- 콜스택의 작업이 끝나지 않을 때는 실행되지 않는다.
- 마이크로 태스크보다 우선순위가 낮다.
- setTimeout(), setInterval(), setImmediate(), 그 외 I/O 연산
3-3. 차이점과 공통점
- 콜스택에 있는 작업이 완료된 후에 실행되는 비동기 작업이다.
- 자바스크립트 메인 스레드 밖에서 실행되어야 할 내용을 담고 있는 경우가 많다.
3-4. 우선순위
콜스택 > 마이크로 태스크 > 매크로 태스크
4. 풀이
- a()가 콜스택에 푸쉬됨, a1 출력
- b()가 콜스택에 푸쉬됨, b1 출력
- c()가 콜스택에 푸쉬됨, c1출력
- setTimeout이 매크로 태스크에 추가됨
- d()가 콜스택에 푸쉬됨, d1 출력
- resolve()가 실행됨, 마이크로 태스크에 then()이 추가됨, 마이크로 태스크에 c()함수의 await 뒷부분이 추가됨
- d2가 출력됨, 프라미스가 반환되며 콜스택에서 d()가 삭제됨
- await은 Promise가 반환될 때 까지 c()의 실행 컨텍스트가 일시정지 상태로 들어가도록 함. c()를 콜스택에서 제거하진 않지만 콜스택은 c()을 실질적으로 제거된 상태로 간주함.
- b2가 출력됨, 콜스택에서 b()가 삭제됨
- a2가 출력됨, 콜스택에서 a()가 삭제됨
- 콜스택이 모두 비었으므로 then!이 출력됨, 마이크로 태스크에서 then()이 삭제됨
- 마이크로 태스크에 예약되었던 c2가 출력됨, 콜스택에서 c()가 삭제됨
- setTimeout이 출력됨, 매크로 태스크에서 setTimeout이 삭제됨
5. 마치며
굉장히 어려운 문제였는데 너무 흥미로워 한 번 제대로 이해해보고 싶어 정리해보았다.
마이크로 태스크, 매크로 태스크를 이해하는데 도움이 되었고 더불어 await-async에 대한 개념도 잡을 수 있었던 좋은 문제였던 것 같다.
'FE > javascript' 카테고리의 다른 글
| [JS] Array.prototype.sort()의 허점 (0) | 2024.06.20 |
|---|---|
| [JS] Swap in JavaScript (0) | 2024.01.04 |
| [Web] Lazy Loading이란 (0) | 2023.08.08 |
| JavaScript spread 와 rest (0) | 2021.02.09 |
| JavaScript 단축 평가 논리 계산법, 비구조화 할당 (0) | 2021.02.05 |