자바스크립트에서 비동기 처리를 처음 접하면 대부분 콜백 함수를 사용한다.
하지만 전통적인 콜백 패턴에는 몇 가지 문제점이 있다.
1. 콜백 패턴의 문제점
1. 콜백 헬 (Callback Hell)
비동기 함수 내부에서 또 다른 비동기 작업을 수행해야 할 때, 콜백 함수가 중첩되며 코드 복잡도가 급격히 증가한다.
getData((res1) => {
getMoreData(res1, (res2) => {
getExtraData(res2, (res3) => {
console.log(res3);
});
});
});
코드가 계속 오른쪽으로 들여쓰기되어 가독성이 나쁘다.
또한 비동기 처리 결과를 함수 외부로 반환하거나 상위 스코프 변수에 할당하기 어렵다.
2. 에러 처리의 어려움
콜백 내부에서 발생한 에러는 외부 try/catch로 잡기 어렵다.
예를 들어, setTimeout의 콜백에서 발생한 에러는 이미 호출한 함수가 콜 스택에서 제거되었기 때문에 잡히지 않는다.
각 콜백마다 개별적으로 에러 핸들링을 해야 하고, 비동기 단계가 많아질수록 에러 전파가 어렵다.
이런 이유로 콜백 패턴만 사용하면 코드가 복잡하고 유지보수가 어렵다.
2. Promise: 콜백 패턴의 대안
ES6에서 도입된 Promise는 비동기 작업의 상태를 명확히 표현하고, 콜백 패턴의 단점을 보완한다.
const promise = new Promise((resolve, reject) => {
// 비동기 처리 수행
if (성공) resolve(result);
else reject(error);
});
- resolve: 성공 시 호출, 결과 전달
- reject: 실패 시 호출, 에러 전달
- 프로미스 상태는 pending → fulfilled / rejected로 결정된다.
즉, Promise는 비동기 처리 상태와 결과를 관리하는 객체다.
1. 후속 처리 메서드
.then()
- 첫 번째 콜백: Promise가 성공(resolve)했을 때 호출된다.
- 두 번째 콜백: Promise가 실패(reject)했을 때 호출된다.
promise.then(
(result) => console.log(result),
(error) => console.error(error)
);
.catch()
- 실패(rejected) 상태일 때만 호출된다.
- 체이닝 중간의 에러까지 모두 잡을 수 있다.
promise
.then((result) => doSomething(result))
.catch((error) => console.error(error));
.finally()
- 성공/실패 관계없이 항상 호출된다.
promise.finally(() => console.log("작업 완료"));
2. 프로미스 체이닝 (Promise Chaining)
.then()과 .catch()는 항상 새로운 Promise를 반환하므로 연속 호출이 가능하다.
fetch('/data.json')
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => console.error(err))
.finally(() => console.log("작업 완료"));
여러 비동기 작업을 순차적으로 처리할 수 있다. 하지만 체인이 길어지면 여전히 가독성이 떨어진다.
3. async/await: 프로미스 문법적 설탕
async/await는 Promise 위에서 동작하는 문법적 설탕이다. 동기 코드처럼 읽기 쉽고 try/catch로 에러 처리가 간단하다.
async function getData() {
try {
const res = await fetch('/data.json');
const data = await res.json();
console.log(data);
} catch (e) {
console.error(e);
} finally {
console.log("작업 완료");
}
}
getData();
- async : 함수가 항상 Promise를 반환하게 한다.
- await : Promise가 처리될 때까지 기다리고 결과를 변수에 할당한다.
즉, 비동기 코드도 마치 동기 코드처럼 작성할 수 있다.
3. 요약
방식 | 장점 | 단점 |
콜백 | 간단한 단일 비동기 | 중첩 시 콜백 헬, 에러 처리 어려움 |
Promise | 상태 관리 가능, 체이닝 가능 | 체인 길어지면 가독성 떨어짐 |
async/await | 동기 코드처럼 읽기 쉬움, try/catch로 에러 처리 가능 | 병렬 처리 시 주의 필요 |
- 단순 비동기 → 콜백도 가능
- 연속/복잡한 비동기 → Promise 또는 async/await 추천
- 실무 → 대부분 async/await + try/catch 조합을 사용한다.
'Frontend > Javascript Essentials' 카테고리의 다른 글
this — 호출 방식에 따라 달라지는 자바스크립트의 핵심 키워드 (0) | 2025.10.14 |
---|---|
호이스팅(Hoisting) (0) | 2025.10.14 |
클로저 — 함수가 변수를 기억하는 방식 (0) | 2025.10.12 |
프로토타입 기반 상속 (0) | 2025.10.12 |
이벤트 루프 (0) | 2025.10.11 |