Node.js 멀티파트 파일 업로드 처리 시 메모리 누수 해결
문제 상황
재택근무 전환 이후 사내 파일 공유 시스템의 트래픽이 급증했다. 특히 500MB 이상의 대용량 파일 업로드 시 서버 메모리 사용률이 80%를 넘어가며 다른 요청까지 지연되는 현상이 발생했다.
기존 코드는 multer의 memoryStorage를 사용하고 있었다.
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
app.post('/upload', upload.single('file'), (req, res) => {
// req.file.buffer에 전체 파일이 로드됨
s3.upload({
Bucket: 'my-bucket',
Key: req.file.originalname,
Body: req.file.buffer
}, (err, data) => {
if (err) return res.status(500).send(err);
res.json({ url: data.Location });
});
});
해결 과정
- diskStorage로 전환: 메모리 대신 임시 디스크에 저장하도록 변경했다.
const storage = multer.diskStorage({
destination: '/tmp/uploads',
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`);
}
});
- 스트림 방식 업로드: S3 업로드 시 파일을 통째로 읽지 않고 스트림으로 전달했다.
const fs = require('fs');
app.post('/upload', upload.single('file'), (req, res) => {
const fileStream = fs.createReadStream(req.file.path);
s3.upload({
Bucket: 'my-bucket',
Key: req.file.originalname,
Body: fileStream
}, (err, data) => {
fs.unlinkSync(req.file.path); // 임시 파일 삭제
if (err) return res.status(500).send(err);
res.json({ url: data.Location });
});
});
결과
동일한 500MB 파일 업로드 시 메모리 사용량이 기존 대비 70% 감소했다. 동시 업로드 처리량도 3배 증가했다.
임시 파일 정리를 위한 cron job도 추가로 설정해두었다. 디스크 용량 모니터링은 CloudWatch로 진행 중이다.