

new Promise(executor): Promise 객체를 생성합니다. executor라는 실행 함수는 즉시 동기적으로 실행됩니다.resolve(value): executor 내부에서 호출되며, Promise의 상태를 pending에서 fulfilled로 바꾸고, 결과 value를 Promise 내부에 저장하는 상태 전환 트리거입니다.reject(reason): executor 내부에서 호출되며, 상태를 pending에서 rejected로 바꾸고, 실패 원인 reason을 저장하는 상태 전환 트리거입니다..then(onFulfilled): Promise가 fulfilled 상태가 되었을 때 그 결과 값을 받아 처리할 콜백 함수(onFulfilled)를 마이크로태스크 큐에 등록하는 메서드입니다..catch(onRejected): Promise가 rejected 상태가 되었을 때 그 실패 원인을 받아 처리할 콜백 함수(onRejected)를 마이크로태스크 큐에 등록하는 메서드입니다..finally(onFinally): 성공/실패 여부와 관계없이, Promise가 처리된 후 항상 실행될 콜백(onFinally)을 마이크로태스크 큐에 등록합니다.중요한 점:
.then,.catch,.finally는 즉시 실행되지 않습니다. 이들은 미래에 실행될 콜백 함수를 예약(등록)하는 역할을 하며, 실제 실행은 이벤트 루프의 마이크로태스크 처리 규칙에 따릅니다.
아래 코드는 resolve/reject와 then/catch의 상호작용을 모두 포함하고 있습니다.
console.log("① 스크립트 시작");
const p = new Promise((resolve, reject) => {
console.log("② Promise executor 실행");
setTimeout(() => {
console.log("③ 타이머 콜백 실행 (매크로태스크)");
const ok = Math.random() > 0.5;
if (ok) {
// 상태: pending → fulfilled
resolve("성공 값");
} else {
// 상태: pending → rejected
reject(new Error("실패 이유"));
}
}, 0);
});
p.then((value) => {
console.log("④ then 콜백 (마이크로태스크):", value);
}).catch((err) => {
console.log("⑤ catch 콜백 (마이크로태스크):", err.message);
}).finally(() => {
console.log("⑥ finally 콜백 (마이크로태스크)");
});
console.log("⑦ 스크립트 끝");
스크립트가 처음 실행될 때, 콜 스택에 있는 모든 동기 코드가 즉시 처리됩니다.
console.log("① 스크립트 시작") 실행.new Promise()의 executor 함수가 즉시 동기적으로 실행되어 console.log("② ...")가 출력됩니다.setTimeout이 Web APIs에 타이머(0ms) 등록을 요청합니다..then, .catch, .finally는 Promise p에 각각의 콜백 함수를 등록만 하고 지나갑니다.console.log("⑦ 스크립트 끝") 실행.| Call Stack | Web APIs | Microtask Queue | Macrotask Queue |
|---|---|---|---|
main() | Timer(0ms) | (비어있음) | (비어있음) |
이 단계가 끝나면 모든 동기 코드가 실행되고 콜 스택은 비워집니다.
setTimeout의 콜백 함수(③번)를 매크로태스크 큐로 보냅니다.| Call Stack | Web APIs | Microtask Queue | Macrotask Queue |
|---|---|---|---|
| (비어있음) | (비어있음) | (비어있음) | [타이머 콜백] |
console.log("③ ...")가 출력됩니다.resolve() 또는 reject()가 호출됩니다. 바로 이 순간, Promise의 상태가 변경됩니다..then 또는 .catch 콜백과 .finally 콜백이 마이크로태스크 큐에 등록됩니다.| Call Stack | Web APIs | Microtask Queue | Macrotask Queue |
|---|---|---|---|
타이머 콜백 | (비어있음) | [then/catch, finally] | (비어있음) |
then 또는 catch, 그리고 finally 콜백)을 순서대로 콜 스택으로 옮겨 모두 실행합니다.console.log("④ ...") 또는 console.log("⑤ ...")가 출력됩니다.console.log("⑥ ...")가 출력됩니다.위 과정을 거쳐 나타나는 최종 출력 순서는 두 가지 경우로 나뉩니다.
then) → 6 (finally)catch) → 6 (finally)핵심 이유: 동기 코드(①, ②, ⑦)가 가장 먼저 실행됩니다. 그 후 이벤트 루프는 매크로태스크(③)를 실행합니다. 이 매크로태스크 안에서 resolve/reject가 호출되면서 마이크로태스크(④/⑤, ⑥)가 큐에 등록되고, 매크로태스크가 끝나자마자 즉시 실행됩니다.
resolve/reject와 then/catch의 관계를 시각적으로 표현하면 다음과 같습니다.
┌─────────── resolve(value) ───────────┐
new Promise ─► pending ─────────────────► fulfilled ──► .then(onFulfilled)
└──────────── reject(reason) ───────────┘
└──► rejected ──► .catch(onRejected)
(어느 쪽이든 공통) ──────────────────────────────────► .finally(onFinally)
※ .then/.catch/.finally 콜백들은 "마이크로태스크 큐"에서 실행됩니다.
resolve/reject는 Promise의 상태를 바꾸는 트리거이며, Promise 내부에 결과(값 또는 이유)를 저장합니다..then/.catch는 그 결과를 소비하기 위해 콜백을 마이크로태스크 큐에 등록하는 예약 메서드입니다.콜 스택(동기) → 마이크로태스크 큐 → 매크로태스크 큐 순입니다.fulfilled 또는 rejected가 되면 절대 변하지 않습니다.