비동기 처리란?
프로그램이 특정 작업의 실행이 끝날 때까지 멈추지 않고, 다음 코드 실행을 이어가는 방식이다.
대표적으로 setTimeout, fetch, 이벤트 리스너 같은 작업이 비동기 로직이다.
하지만 결과가 필요한 시점에 값을 받아야 할 때가 있다.
비동기 처리 3단계 진화
1) 콜백 함수 방식 (Old)
비동기 작업이 끝난 후 실행할 함수를 매개변수로 넘겨주는 방식이다.
function getData(callback) {
setTimeout(() => {
callback("완료");
}, 1000);
}
getData(result => {
console.log(result);
});
문제는 이게 여러 단계로 이어지면?
getData(a => {
getData(b => {
getData(c => {
console.log("끝");
});
});
});
이런 형태 발생 → 흔히 말하는 콜백 지옥
코드가 깊어지면서 가독성이 떨어짐
유지보수도 힘들어짐
2) Promise 객체
콜백지옥 해결을 위해 등장.new Promise() 생성자로 만들며, 성공은 resolve, 실패는 reject를 통해 관리한다.
const p = new Promise((resolve, reject) => {
setTimeout(() => resolve("성공"), 1000);
});
p.then(data => console.log(data))
.catch(err => console.error(err))
.finally(() => console.log("작업 종료"));
Promise 상태
상태 | 의미 |
Pending | 작업 중 |
Fulfilled | resolve 호출됨 (성공) |
Rejected | reject 호출됨 (실패) |
Promise Chaining
여러 비동기 작업을 순서대로 처리 가능
fetch(url)
.then(res => res.json())
.then(data => data.name)
.catch(err => console.error(err));
3) async / await (Best 가독성)
Promise 문법을 더 동기 코드처럼 보이게 만든 문법 구조이다.await는 오직 async 함수 안에서만 사용 가능.
async function getData(){
const res = await fetch(url);
const data = await res.json();
console.log(data);
}
getData();
기존 .then() 방식보다 직관적이고 코드가 깔끔하다.
async 함수도 Promise를 반환한다
async function example(){
return 1;
}
example().then(console.log); // 1
try - catch로 에러 핸들링 가능
async function getUser(){
try {
const res = await fetch(url);
const data = await res.json();
console.log(data);
} catch (err) {
console.error("에러 발생", err);
}
}
Top-Level await
모듈 환경(ESM)에서는 함수 없이도 바로 await 사용 가능.
const res = await fetch(url);
const data = await res.json();
console.log(data);
주요 Promise 정적 메서드
메서드 | 설명 |
| 즉시 Fulfilled 상태의 Promise 생성 |
| 즉시 Rejected Promise 생성 |
| 모든 Promise가 성공할 때까지 기다림 (하나라도 실패 시 Reject) |
| 성공/실패 관계없이 모든 결과 반환 |
| 가장 먼저 성공한 Promise 반환 |
| 가장 먼저 끝난 Promise 반환 (성공/실패 무관) |
예제:
const p1 = new Promise(res => setTimeout(() => res("1초"), 1000));
const p2 = new Promise(res => setTimeout(() => res("2초"), 2000));
Promise.all([p1, p2]).then(console.log);
실제 활용 예시
Sleep 함수 구현
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
console.log("시작");
await sleep(1000);
console.log("1초 뒤 실행");
}
run();