비동기 작업을 처리할 때, 콜백 함수가 중첩적으로 사용되면서 코드의 가독성이 크게 떨어지는 문제를 말합니다.
이는 코드가 단계적으로 실행되는 구조를 유지하기 위해 비동기 작업마다 콜백을 정의하고, 이를 다시 다른 콜백으로 연결할 때 발생합니다.
콜백 지옥의 대표적인 예는 아래와 같습니다:
javascript
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
processFile(data, (err, processedData) => {
if (err) throw err;
saveFile('output.txt', processedData, (err) => {
if (err) throw err;
console.log('File saved successfully');
});
});
});
위 코드는 함수 호출이 계속 중첩되면서 이해하기 어려워지고, 디버깅도 까다로워집니다.
콜백 지옥 예방 방법
1. Promise 사용
Promise는 비동기 작업의 결과를 나타내는 객체입니다.
콜백 지옥을 방지하기 위해 .then() 체인을 사용하여 코드의 가독성을 높일 수 있습니다.
javascript
readFile('file.txt')
.then((data) => processFile(data))
.then((processedData) => saveFile('output.txt', processedData))
.then(() => console.log('File saved successfully'))
.catch((err) => console.error(err));
javascript
async function handleFile() {
try {
const data = await readFile('file.txt');
const processedData = await processFile(data);
await saveFile('output.txt', processedData);
console.log('File saved successfully');
} catch (err) {
console.error(err);
}
}
handleFile();
비동기 제어 기술
1. Promise
Promise는 비동기 작업이 성공(resolve)하거나 실패(reject)한 후의 결과를 처리하는 객체입니다.
상태:
pending (대기)
fulfilled (성공)
rejected (실패)
사용법
javascript
코드 복사
const promise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve('Success!');
} else {
reject('Error!');
}
});
promise
.then((message) => console.log(message))
.catch((error) => console.error(error));
장점
비동기 작업을 순차적으로 처리하거나 병렬 처리할 때 유용합니다.
.then(), .catch(), .finally()로 흐름을 제어할 수 있습니다.
javascript
코드 복사
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
장점
코드의 가독성을 높여주는 구조적 접근 방식.
try...catch 블록을 통해 에러 핸들링을 쉽게 처리 가능.

단순한 비동기 작업은 Promise를 사용하고, 복잡한 흐름 제어가 필요할 때는 async/await를 사용하는 것이 좋습니다.
Promise와 async/await는 콜백 지옥을 해결하고 비동기 작업의 가독성과 유지보수성을 크게 향상시킵니다.