Node.js 스트림으로 대용량 CSV 파싱 메모리 문제 해결
문제 상황
데이터 마이그레이션 작업 중 500MB 규모의 CSV 파일을 파싱하는 배치 작업에서 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 에러가 발생했다.
기존 코드는 파일 전체를 메모리에 올린 후 처리하는 방식이었다.
const fs = require('fs');
const csv = require('csv-parser');
fs.readFile('large-data.csv', 'utf8', (err, data) => {
// 파일 전체가 메모리에 로드됨
const rows = data.split('\n');
// 처리 로직...
});
해결 방법
fs.createReadStream과 csv-parser를 조합해 스트림 방식으로 변경했다.
const fs = require('fs');
const csv = require('csv-parser');
fs.createReadStream('large-data.csv')
.pipe(csv())
.on('data', (row) => {
// 한 행씩 처리
processRow(row);
})
.on('end', () => {
console.log('파싱 완료');
})
.on('error', (err) => {
console.error('에러 발생:', err);
});
결과
- 메모리 사용량: 약 600MB → 60MB로 감소
- 처리 속도: 큰 차이 없음 (오히려 약간 빨라짐)
- 안정성: 1GB 이상 파일도 문제없이 처리
스트림은 데이터를 청크 단위로 나눠 처리하므로 파일 크기에 관계없이 일정한 메모리만 사용한다. Node.js에서 대용량 파일을 다룰 때는 스트림이 기본이어야 한다는 걸 다시 확인했다.