반응형
Node.js에서 비동기 프로그래밍을 구현하는 방법인 콜백, 프라미스, async/await, 네이티브 비동기 방식의 장점과 단점을 살펴보겠습니다.
1. 콜백 (Callback)
장점:
- 간단함: 사용법이 단순하며, JavaScript 초창기부터 사용되어 널리 알려져 있습니다.
- 효율적: 메모리 사용이 적고, 이벤트 루프의 성능을 최대한 활용합니다.
- 보편성: 많은 Node.js API가 콜백 기반으로 설계되어 있어 직접 사용하거나 이해하기 쉽습니다.
단점:
- 콜백 헬: 중첩된 콜백이 많아질 경우 코드가 난해해지고 가독성이 떨어집니다. 이를 "콜백 지옥(callback hell)" 또는 "피라미드 코드(pyramid of doom)"라고 합니다.
- 에러 처리의 어려움: 에러 처리가 각 콜백 내에서 이루어져야 하므로 코드가 더 복잡해질 수 있습니다.
- 유연성 부족: 여러 비동기 작업을 조합하거나 연결하는 것이 어렵습니다.
// 콜백 헬의 예
fs.readFile('file1.txt', 'utf8', (err, data1) => {
if (err) throw err;
fs.readFile('file2.txt', 'utf8', (err, data2) => {
if (err) throw err;
fs.readFile('file3.txt', 'utf8', (err, data3) => {
if (err) throw err;
console.log(data1, data2, data3);
});
});
});
2. 프라미스 (Promise)
장점:
- 가독성 향상: 비동기 작업을 체인(chain) 형태로 연결할 수 있어 코드가 더 읽기 쉽고 관리하기 쉬워집니다.
- 에러 전파:
catch
블록을 사용하여 프로미스 체인의 모든 에러를 한 곳에서 처리할 수 있습니다. - 유연성:
Promise.all
,Promise.race
와 같은 메서드를 사용하여 병렬 또는 경쟁적으로 비동기 작업을 처리할 수 있습니다.
단점:
- 구문이 복잡할 수 있음: 복잡한 프로미스 체인은 여전히 이해하기 어려울 수 있습니다.
- 초기 학습 곡선: 콜백에 비해 이해하기 어렵다고 느낄 수 있으며, 초기 학습이 필요합니다.
// Promise를 사용한 예
const fs = require('fs').promises;
Promise.all([
fs.readFile('file1.txt', 'utf8'),
fs.readFile('file2.txt', 'utf8'),
fs.readFile('file3.txt', 'utf8')
])
.then(([data1, data2, data3]) => {
console.log(data1, data2, data3);
})
.catch(err => {
console.error('Error reading files:', err);
});
3. async/await
장점:
- 가독성: 동기 코드와 유사하게 작성할 수 있어 읽기 쉽고 이해하기 쉽습니다.
- 에러 처리:
try/catch
블록을 사용하여 직관적으로 에러를 처리할 수 있습니다. - 코드 구조 단순화: 복잡한 비동기 흐름을 더 쉽게 관리할 수 있습니다.
단점:
- 약간의 성능 저하:
async/await
는 프로미스를 사용하므로 약간의 성능 오버헤드가 있을 수 있습니다. - ES2017 이후:
async/await
는 ES2017에 도입되었기 때문에, 이전 버전의 Node.js에서는 사용할 수 없습니다. - 병렬 처리가 아닌 직렬 처리: 기본적으로
await
는 직렬 처리를 하므로, 병렬로 작업을 처리하려면 별도의 코드가 필요합니다.
// async/await를 사용한 예
const fs = require('fs').promises;
async function readFiles() {
try {
const [data1, data2, data3] = await Promise.all([
fs.readFile('file1.txt', 'utf8'),
fs.readFile('file2.txt', 'utf8'),
fs.readFile('file3.txt', 'utf8')
]);
console.log(data1, data2, data3);
} catch (err) {
console.error('Error reading files:', err);
}
}
readFiles();
4. 네이티브 비동기 API (Native Async APIs)
장점:
- 최적화: Node.js에서 기본 제공하는 비동기 API는 내부적으로 최적화되어 있어 효율적으로 동작합니다.
- 간단한 사용: 콜백을 간단하게 추가하여 사용할 수 있습니다. 비동기 작업에 적합한 많은 네이티브 API가 제공됩니다.
- API 지원: Node.js의 대부분의 핵심 모듈이 비동기 API를 제공하여 쉽게 사용할 수 있습니다.
단점:
- 콜백 기반: 여전히 콜백 기반이므로, 콜백 헬로 이어질 수 있습니다.
- 단일 접근 방식: 비동기 작업을 관리하거나 조합하는 데 있어 유연성이 부족할 수 있습니다.
const fs = require('fs');
// 비동기 파일 읽기
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
console.log('File content:', data);
});
요약
- 콜백은 단순하지만, 콜백 헬과 에러 처리가 어렵습니다.
- 프라미스는 가독성과 에러 처리를 개선하지만, 구문이 복잡할 수 있습니다.
- async/await은 가장 가독성이 좋고, 직관적인 에러 처리를 제공하지만, 성능 오버헤드와 병렬 처리를 따로 고려해야 합니다.
- 네이티브 비동기 API는 최적화되어 있고 간단하게 사용할 수 있지만, 콜백 기반으로 복잡한 비동기 흐름 관리에 한계가 있을 수 있습니다.
Node.js에서 비동기 작업을 처리할 때는 이들 방식의 장단점을 고려하여 상황에 맞는 방법을 선택하는 것이 중요합니다.
반응형
'언어 > Node.js' 카테고리의 다른 글
[ Node.js ] 비동기 함수에서 발생하는 에러 처리하기 (0) | 2024.06.16 |
---|---|
[ Node.js ] Node.js 문법 발전 역사 (JavaScript) (0) | 2024.06.16 |
[ Node.js ] 비동기 함수 구현 하는 방법 (0) | 2024.06.16 |
[ Node.js ] 프로젝트 작성 및 실행 (express-generator) (0) | 2024.06.16 |
Node.js ESM(ECMAScript) 모듈 사용해 보기 (0) | 2024.06.10 |