Node.js 멀티파트 파일 업로드 처리 방법 정리
배경
관리자 대시보드에 상품 이미지 업로드 기능을 추가해야 했다. Express 기반 API 서버에서 멀티파트 폼 데이터를 받아 S3에 업로드하는 구조로 설계했다.
Multer 설정
const multer = require('multer');
const multerS3 = require('multer-s3');
const aws = require('aws-sdk');
const s3 = new aws.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_KEY,
region: 'ap-northeast-2'
});
const upload = multer({
storage: multerS3({
s3: s3,
bucket: 'my-bucket',
key: function (req, file, cb) {
const timestamp = Date.now();
cb(null, `images/${timestamp}-${file.originalname}`);
}
}),
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
fileFilter: function (req, file, cb) {
if (!file.mimetype.startsWith('image/')) {
return cb(new Error('이미지 파일만 업로드 가능합니다'));
}
cb(null, true);
}
});
라우터 구현
router.post('/upload', upload.single('image'), (req, res) => {
if (!req.file) {
return res.status(400).json({ error: '파일이 없습니다' });
}
res.json({
url: req.file.location,
key: req.file.key
});
});
router.post('/upload-multiple', upload.array('images', 5), (req, res) => {
const urls = req.files.map(file => file.location);
res.json({ urls });
});
에러 처리
multer 에러는 별도로 핸들링이 필요했다.
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({ error: '파일 크기는 5MB를 초과할 수 없습니다' });
}
}
next(err);
});
정리
multer-s3를 사용하면 메모리에 파일을 올리지 않고 스트림으로 바로 S3에 업로드할 수 있어 메모리 효율적이다. 파일 크기 제한과 타입 검증은 fileFilter와 limits 옵션으로 간단히 처리 가능했다.