const response = fetch('https://jsonplaceholder.typicode.com/todos/1');
// const data = response.json();
console.log('0', response);
const response2 = fetch('https://jsonplaceholder.typicode.com/todos/1');
const data2 = response2;
console.log('2', data2);
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((json) => console.log('3', json));
(async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const data = await response;
console.log('1', data);
})()
코드 실행 흐름 분석:
- 첫 번째 fetch 호출 (로그 '0')
- fetch 함수는 비동기 함수이며 즉시 Promise 객체를 반환함.
- 따라서 console.log('0', response);가 즉시 실행되며, Promise<pending> 상태의 response가 출력됨.
- 네트워크 요청은 백그라운드에서 진행됨.
- 두 번째 fetch 호출 (로그 '2')
- 마찬가지로 즉시 실행되며, Promise<pending> 상태가 출력됨.
- 세 번째 fetch 호출 (로그 '3')
- fetch가 호출되고, .then 체이닝이 등록됨.
- 네트워크 요청이 완료되면 응답을 JSON으로 변환 후 console.log('3', json);이 실행됨.
- 이 과정은 이벤트 루프에 의해 비동기적으로 처리되므로 이후 코드 실행 후에 로그가 출력됨.
- async/await 비동기 호출 (로그 '1')
- 이 함수는 즉시 실행되지 않고, 비동기 함수의 실행 컨텍스트가 이벤트 루프에 의해 예약됨.
- await는 네트워크 응답을 기다리므로 블로킹되지 않으며, 나머지 동기 코드를 먼저 실행시킴.
- 네트워크 요청이 끝난 후 console.log('1', data);가 실행됨.
왜 console.log('1')이 console.log('3')보다 먼저 출력될까?
- await는 호출된 위치에서 해당 비동기 작업이 완료될 때까지 기다리지만, Promise.then 체인은 이벤트 루프의 마이크로태스크 큐에서 처리됨.
- await는 내부적으로 마이크로태스크로 동작하므로, Promise 체인보다 빠르게 실행될 가능성이 있음.
- fetch().then().then() 구문은 Promise 체인이므로, 마이크로태스크에서 처리되지만 일반적으로 await보다는 우선순위가 조금 낮음.
- 네트워크 요청 속도나 브라우저 스케줄링에 따라 약간의 차이가 있을 수 있음.
실행 예상 순서:
- console.log('0', Promise), console.log('2', Promise) → 동기 코드이므로 즉시 실행
- console.log('1', data) → await로 비동기 완료 후 실행 (마이크로태스크 우선순위 높음)
- console.log('3', json) → Promise 체인으로 처리되므로 나중에 실행
정리:
- async/await는 마이크로태스크 우선순위가 높아 then 체인보다 먼저 실행될 수 있음.
- fetch 호출은 비동기로 작동하며 즉시 Promise<pending>을 반환하지만, 결과를 기다릴 때 await가 먼저 처리됨.
- 네트워크 상태나 브라우저의 이벤트 루프 스케줄링에 따라 미세한 차이가 발생할 수 있음.
마이크로태스크 큐(Microtask Queue)란?
마이크로태스크 큐는 JavaScript의 **이벤트 루프(Event Loop)**에서 작업을 처리하는 두 가지 주요 큐(매크로태스크 큐, 마이크로태스크 큐) 중 하나로, 우선순위가 높은 작업을 실행하는 역할을 함.
마이크로태스크는 주로 비동기 Promise 처리 및 await와 관련된 작업이 들어가며, 현재 실행 중인 태스크(스크립트)가 끝난 후 즉시 실행되기 때문에 다른 비동기 작업보다 빠르게 실행됨.
마이크로태스크 큐의 주요 특징
- 우선순위가 높음
- 매크로태스크(예: setTimeout, setInterval)보다 항상 먼저 실행됨.
- 비동기 작업 종료 후 즉시 실행
- 현재 실행 중인 동기 작업(콜 스택)이 완료된 후 바로 실행됨.
- 주요 비동기 API와 연관
- Promise.then(), catch(), finally(), MutationObserver, queueMicrotask() 등이 마이크로태스크로 들어감.
마이크로태스크의 실행 순서 예제
console.log('A');
setTimeout(() => {
console.log('B');
}, 0);
Promise.resolve().then(() => {
console.log('C');
});
console.log('D');
// 실행 결과
A
D
C
B
실행 순서 설명:
- console.log('A') → 동기 코드, 즉시 실행.
- setTimeout() → 매크로태스크 큐에 등록됨 (콜백 실행 대기 중).
- Promise.resolve().then() → 마이크로태스크 큐에 등록됨 (실행 대기 중).
- console.log('D') → 동기 코드, 즉시 실행.
- 마이크로태스크(then)가 먼저 실행되므로 C 출력.
- 매크로태스크(setTimeout)가 실행되어 B 출력.
마이크로태스크와 매크로태스크 비교
특징 | 마이크로태스크 | 매크로태스크 |
우선순위 | 높음 (Promise, await) | 낮음 (setTimeout, setInterval) |
실행 시점 | 현재 실행 중인 작업 완료 직후 실행 | 모든 마이크로태스크 후 실행 |
주요 API | Promise.then(), queueMicrotask() | setTimeout(), setInterval(), I/O |
예제 코드 결과 | 즉시 실행되지만 동기 코드 이후 수행 | 이후 스케줄링을 통해 수행 |
마이크로태스크 실행 흐름
- 콜 스택에 있는 동기 코드를 모두 실행.
- 마이크로태스크 큐가 비어 있을 때까지 실행.
- 매크로태스크(예: setTimeout) 실행.
- 다시 마이크로태스크 확인 및 실행.
- 반복...
queueMicrotask()를 사용한 마이크로태스크 등록
queueMicrotask()를 사용하면 명시적으로 마이크로태스크 큐에 작업을 추가할 수 있음.
console.log('Start');
queueMicrotask(() => {
console.log('Microtask 1');
});
console.log('End');
// 실행 결과
Start
End
Microtask 1
마이크로태스크 활용 시 주의점
- 무한 루프 방지:
- 마이크로태스크가 계속 생성되면 이벤트 루프가 다른 작업을 실행하지 못함.
- 예: 무한 Promise.then() 체이닝.
- 비효율적인 태스크 등록:
- 필요 이상으로 마이크로태스크를 많이 등록하면 성능 저하 발생.
정리
- 마이크로태스크는 비동기 작업 중 가장 빠르게 실행되는 큐이며, 주요 비동기 API(Promise, await)와 연관됨.
- 동기 코드 실행 후 바로 마이크로태스크가 실행되고, 그 이후 매크로태스크가 실행됨.
- queueMicrotask()를 사용하여 명시적으로 마이크로태스크 등록이 가능함.
728x90
'웹개발 > javascript' 카테고리의 다른 글
[자바스크립트] reduce() (0) | 2025.01.09 |
---|---|
[자바스크립트] 큐(Queue) (0) | 2024.08.09 |
[자바스크립트] Math 객체와 수학 연산 (0) | 2024.08.08 |
[자바스크립트] 해체 할당 (0) | 2024.08.08 |
[자바스크립트] 객체 메서드 심층 분석 (0) | 2024.08.08 |