Callback Hell#
콜백 지옥은 여러 비동기 작업을 순차적으로 처리해야 할 때 발생하는 중첩된 콜백 구조를 말한다. 코드가 깊게 중첩되어 가독성이 떨어지고 유지보수가 어려워지는 문제가 있다.
이는 주로 여러 비동기 작업(API 호출, 파일 읽기, 타이머 등)이 순차적으로 실행되어야 할 때 발생하며, 코드가 피라미드 형태로 깊이 중첩되는 특징을 보인다.
콜백 지옥의 원인#
- 비동기 작업의 연속성:
A 작업의 결과가 B 작업의 입력으로 필요할 때, 콜백 안에 콜백을 중첩해야 한다. - JavaScript의 단일 스레드 특성:
비동기 작업 완료 시점을 콜백 함수로 처리해야 하므로 중첩이 불가피한다.
주요 문제점#
문제점 | 설명 |
---|
가독성 저하 | 코드의 들여쓰기 수준이 과도하게 증가하여 논리 흐름 파악이 어렵다. |
에러 처리 복잡 | 각 콜백마다 별도의 에러 핸들링이 필요해 중복 코드가 발생한다. |
유지보수 난이도 | 기능 수정 시 중첩 구조에서 의도치 않은 버그 발생 가능성이 높다. |
해결 방법#
1
2
3
4
5
6
7
8
9
10
11
| getData(function(a) {
getMoreData(a, function(b) {
getEvenMoreData(b, function(c) {
getYetEvenMoreData(c, function(d) {
getFinalData(d, function(finalData) {
console.log("최종 데이터:", finalData);
}, errorCallback);
}, errorCallback);
}, errorCallback);
}, errorCallback);
}, errorCallback);
|
함수 분리 (모듈화)#
각 콜백을 별도의 명명된 함수로 분리하여 중첩을 줄인다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| function handleFinalData(finalData) {
console.log("최종 데이터:", finalData);
}
function handleD(d) {
getFinalData(d, handleFinalData, errorCallback);
}
function handleC(c) {
getYetEvenMoreData(c, handleD, errorCallback);
}
function handleB(b) {
getEvenMoreData(b, handleC, errorCallback);
}
function handleA(a) {
getMoreData(a, handleB, errorCallback);
}
getData(handleA, errorCallback);
|
Promise 사용#
Promise는 비동기 작업의 결과를 나타내는 객체로, 콜백 지옥을 해결하기 위한 더 나은 방법을 제공한다.
.then()
을 사용해 비동기 작업을 순차적으로 연결하고, .catch()
로 통합 에러 처리 가능하다.
1
2
3
4
5
6
7
8
9
10
11
| getDataPromise()
.then(a => getMoreDataPromise(a))
.then(b => getEvenMoreDataPromise(b))
.then(c => getYetEvenMoreDataPromise(c))
.then(d => getFinalDataPromise(d))
.then(finalData => {
console.log("최종 데이터:", finalData);
})
.catch(error => {
console.error("에러 발생:", error);
});
|
Async/Await 사용#
ES2017에서 도입된 Async/Await는 비동기 코드를 동기 코드처럼 작성할 수 있게 해준다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| async function processData() {
try {
const a = await getDataPromise();
const b = await getMoreDataPromise(a);
const c = await getEvenMoreDataPromise(b);
const d = await getYetEvenMoreDataPromise(c);
const finalData = await getFinalDataPromise(d);
console.log("최종 데이터:", finalData);
} catch (error) {
console.error("에러 발생:", error);
}
}
processData();
|
콜백 지옥 vs. 해결 후 코드 비교#
콜백 지옥 코드 | Promise/async-await 코드 |
---|
깊은 들여쓰기와 계층적 구조 | 평평한 구조와 직관적인 흐름 |
분산된 에러 처리 | 단일 .catch() 또는 try/catch 로 통합 |
추가 전략#
참고 및 출처#