"콜백 지옥"이란, 비동기 함수에서 여러 개의 콜백을 중첩시키는 구조로 인해 코드가 들여쓰기(Indentation) 깊이가 많아지고 복잡해지는 현상을 의미합니다. Express 서버에서도 비동기 작업을 콜백으로 처리하다 보면 이런 현상이 발생할 수 있습니다.
아래는 콜백 지옥을 만든 간단한 Express 서버 예시입니다. 이 서버는 여러 비동기 작업을 콜백을 이용해 처리하는 방식으로 구성되어 있습니다.
예시 코드: 콜백 지옥
const express = require('express');
const app = express();
// 예시로 사용할 비동기 함수들 (콜백을 사용하는 비동기 함수들)
function step1(callback) {
setTimeout(() => {
console.log('Step 1 complete');
callback(null, 'Step 1 Data');
}, 1000);
}
function step2(data, callback) {
setTimeout(() => {
console.log('Step 2 complete with', data);
callback(null, 'Step 2 Data');
}, 1000);
}
function step3(data, callback) {
setTimeout(() => {
console.log('Step 3 complete with', data);
callback(null, 'Step 3 Data');
}, 1000);
}
// 라우터에서 콜백 지옥 예시
app.get('/callback-hell', (req, res) => {
step1((err, result1) => {
if (err) {
res.status(500).send('Error in Step 1');
return;
}
step2(result1, (err, result2) => {
if (err) {
res.status(500).send('Error in Step 2');
return;
}
step3(result2, (err, result3) => {
if (err) {
res.status(500).send('Error in Step 3');
return;
}
res.send('All steps completed: ' + result3);
});
});
});
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
위의 코드를 보면 각각의 실행 함수 그리고 해당 에러 처리를 위한 콜백이 연달아서 있는것을 볼수 있습니다.
에러 처리가 힘들뿐더러, 읽기에도 불편한 코드가 됩니다.
async/await를 사용하여 위의 "콜백 지옥" 코드를 개선할 수 있습니다. async/await는 비동기 코드를 동기적으로 작성하는 방식으로, 코드의 가독성을 높이고 중첩을 줄여줍니다. 아래는 async/await로 리팩토링한 코드입니다.
const express = require('express');
const app = express();
// 예시로 사용할 비동기 함수들 (콜백을 사용하는 비동기 함수들)
function step1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Step 1 complete');
resolve('Step 1 Data');
}, 1000);
});
}
function step2(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Step 2 complete with', data);
resolve('Step 2 Data');
}, 1000);
});
}
function step3(data) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('Step 3 complete with', data);
resolve('Step 3 Data');
}, 1000);
});
}
// /callback-hell 경로 처리 (async/await 사용)
app.get('/callback-hell', async (req, res) => {
try {
const result1 = await step1();
const result2 = await step2(result1);
const result3 = await step3(result2);
res.send('All steps completed: ' + result3);
} catch (err) {
res.status(500).send('Error occurred: ' + err);
}
});
// 서버 시작
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
- 코드 가독성 향상: async/await를 사용하면 콜백을 중첩하지 않고 동기적인 흐름으로 비동기 작업을 처리할 수 있어 코드가 훨씬 읽기 쉬워집니다.
- 에러 처리: try/catch 구문으로 전체 비동기 코드에서 발생할 수 있는 오류를 한 곳에서 처리할 수 있습니다.
- 유지보수 용이: 코드가 간결해지고, 각 단계를 추적하기가 쉬워집니다.
'Node.js > 1. node.js 란?' 카테고리의 다른 글
1-5. Node.js 이벤트 루프 (0) | 2025.01.07 |
---|---|
1-3 node.js의 단점! (0) | 2025.01.06 |
1-2 node.js의 특징. event-driven, non-blocking I/O , 단일 스레드 (0) | 2025.01.06 |
1-1 node.js 는 무엇일까요? (1) | 2014.02.13 |