Node.js 스트림으로 대용량 CSV 파일 처리하기
문제 상황
고객사에서 제공한 700MB CSV 파일을 파싱해서 DB에 넣는 작업을 진행하던 중 JavaScript heap out of memory 에러가 발생했다. 기존 코드는 fs.readFileSync로 전체 파일을 메모리에 올린 후 처리하는 방식이었다.
해결 방법
스트림을 사용해 파일을 청크 단위로 읽으면서 처리하도록 변경했다.
const fs = require('fs');
const readline = require('readline');
const { promisify } = require('util');
async function processCSV(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
let batch = [];
const BATCH_SIZE = 1000;
for await (const line of rl) {
const parsed = parseLine(line);
batch.push(parsed);
if (batch.length >= BATCH_SIZE) {
await insertBatch(batch);
batch = [];
}
}
if (batch.length > 0) {
await insertBatch(batch);
}
}
성능 개선
- 메모리 사용량: 1.2GB → 150MB
- 처리 시간: OOM으로 실패 → 약 3분 소요
- 배치 단위로 DB 삽입해서 커넥션 효율도 개선
추가 고려사항
csv-parser 같은 라이브러리를 쓰면 더 편하지만, 의존성을 최소화하고 싶어서 직접 구현했다. 나중에 복잡한 CSV 처리가 필요하면 라이브러리 도입을 검토할 예정이다.
스트림 에러 핸들링도 추가해야 하는데, fileStream.on('error') 같은 이벤트 리스너를 붙여서 처리하면 된다.