728x90
반응형
1. 콜백 함수란
콜백 함수는 다른 함수에 인자로 전달되어 특정 시점에 호출되는 함수입니다. Node.js에서는 비동기 작업이 완료되었을 때 결과를 처리하기 위해 콜백 함수를 사용합니다. Node.js의 초기 비동기 처리 방식으로, 현재도 많은 내장 모듈에서 사용되고 있습니다.
2. 콜백 함수의 기본 구조
2.1 동기 콜백
// 배열의 forEach는 동기 콜백
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
console.log(num);
});
console.log('완료');
// 출력: 1, 2, 3, 4, 5, 완료 (순차적)
2.2 비동기 콜백
const fs = require('fs');
// fs.readFile은 비동기 콜백
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('에러:', err.message);
return;
}
console.log('파일 내용:', data);
});
console.log('파일 읽기 요청 완료');
// 출력: 파일 읽기 요청 완료 → 파일 내용: ...
3. Node.js 콜백 컨벤션
Node.js의 콜백 함수는 Error-First Callback 패턴을 따릅니다.
- 첫 번째 인자는 항상 에러 객체 (에러가 없으면 null)
- 두 번째 인자부터 결과 데이터
// Error-First Callback 패턴
function readFileCallback(err, data) {
// 첫 번째: 에러 체크
if (err) {
console.error('에러 발생:', err.message);
return;
}
// 두 번째: 성공 시 데이터 처리
console.log('데이터:', data);
}
fs.readFile('file.txt', 'utf8', readFileCallback);
4. 콜백 함수 활용 예시
4.1 커스텀 콜백 함수 만들기
function fetchUserData(userId, callback) {
// 비동기 작업 시뮬레이션
setTimeout(() => {
if (!userId) {
callback(new Error('userId가 필요합니다'), null);
return;
}
const user = {
id: userId,
name: '홍길동',
email: 'hong@example.com'
};
callback(null, user);
}, 1000);
}
// 사용
fetchUserData(1, (err, user) => {
if (err) {
console.error(err.message);
return;
}
console.log('사용자 정보:', user);
});
반응형
4.2 여러 비동기 작업 연결
const fs = require('fs');
fs.readFile('config.json', 'utf8', (err, configData) => {
if (err) {
console.error('설정 파일 읽기 실패');
return;
}
const config = JSON.parse(configData);
fs.readFile(config.dataFile, 'utf8', (err, data) => {
if (err) {
console.error('데이터 파일 읽기 실패');
return;
}
console.log('데이터:', data);
});
});
5. 콜백 지옥(Callback Hell)
중첩된 콜백이 많아지면 코드 가독성이 떨어지는 콜백 지옥이 발생합니다.
5.1 콜백 지옥 예시
// 콜백 지옥 - 가독성이 매우 떨어짐
getUser(userId, (err, user) => {
if (err) return handleError(err);
getOrders(user.id, (err, orders) => {
if (err) return handleError(err);
getOrderDetails(orders[0].id, (err, details) => {
if (err) return handleError(err);
getProductInfo(details.productId, (err, product) => {
if (err) return handleError(err);
console.log('최종 결과:', product);
});
});
});
});
5.2 콜백 지옥 해결 방법
// 방법 1: 함수 분리
function handleUser(err, user) {
if (err) return handleError(err);
getOrders(user.id, handleOrders);
}
function handleOrders(err, orders) {
if (err) return handleError(err);
getOrderDetails(orders[0].id, handleDetails);
}
function handleDetails(err, details) {
if (err) return handleError(err);
console.log('결과:', details);
}
getUser(userId, handleUser);
// 방법 2: Promise 또는 async/await 사용 (권장)
async function getProductData(userId) {
const user = await getUser(userId);
const orders = await getOrders(user.id);
const details = await getOrderDetails(orders[0].id);
return details;
}
6. 콜백을 프로미스로 변환
Node.js의 util.promisify를 사용하면 콜백 기반 함수를 프로미스로 변환할 수 있습니다.
const util = require('util');
const fs = require('fs');
// 콜백 기반 함수를 프로미스로 변환
const readFileAsync = util.promisify(fs.readFile);
// 프로미스로 사용
readFileAsync('file.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
// 또는 async/await로 사용
async function readFile() {
const data = await readFileAsync('file.txt', 'utf8');
console.log(data);
}
결론
콜백 함수는 Node.js 비동기 처리의 기본 패턴으로, Error-First Callback 컨벤션을 따릅니다. 중첩이 깊어지면 콜백 지옥이 발생할 수 있으므로, 함수 분리나 프로미스/async-await로의 전환을 고려해야 합니다. util.promisify를 활용하면 기존 콜백 기반 코드를 쉽게 프로미스로 변환할 수 있습니다.
728x90
반응형
'Node.js' 카테고리의 다른 글
| Node.js의 프로미스(Promise) 사용법 (0) | 2026.02.22 |
|---|---|
| Node.js의 비동기 프로그래밍(Asynchronous Programming) (0) | 2026.02.21 |
| Node.js의 이벤트 루프(Event Loop) (0) | 2026.02.21 |
| Node.js 설치 및 설정 방법 (0) | 2026.02.21 |
| Node.js란 무엇인가 (0) | 2026.02.21 |