BFF 패턴으로 개발을 하려던 중에 multipart/form-data
형식으로 요청을 보내야 했었다.
우선 클라이언트에서 보낸 파일을 pages/api에 구현된 BFF에서 처리를 해야했다.
클라이언트에서 보내는 데이터를 처리하기 위해 처음에는 Multer로 열심히 시도를 해보았다. 하지만 왜 안되는 거지? 그것은 바로 Multer은 Express 미들웨어이기 때문... 아무생각 없이 사용한 나 자신 반성.. 내가 사용하고 있는 건 Next.js로 Express를 사용하지 않는다.
next-connect
라이브러리를 사용하면 multer를 사용할 수 있다고 하지만 Express에 종속적이지 않은 Formidable을 사용하기로 생각했다.
하지만 난 Spring 서버에 formData로 보내야한다... 그래서 외부 라이브러리를 사용하기로 했다.
제일 유명한 건 multer과 formidable이였다.
import formidable from 'formidable';
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(req, res) {
if (req.method !== 'POST') {
res.status(400).json({ error: 'Only POST method allowed' });
return;
}
const form = new IncomingForm();
form.keepExtensions = true;
form.multiples = true;
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: 'Failed to parse the request' });
return;
}
if (response.status === 200) {
res.status(200).json({ success: true });
} else {
res.status(500).json({ error: 'Failed to upload files' });
}
}
bodyParser: false
: Next.js에서는 기본적으로 모든 요청에 body parser가 적용된다. 파일 업로드 같은 멀티파트 형식의 데이터를 파싱하는데는 문제가 될 수 있기 때문에 body parser 비활성화form.keepExtensions = true
: 파일 확장자 유지form.multiples = true;
: 여러 파일을 한 번에 업로드npm install --save form-data
import fs from 'fs';
import path from 'path';
import FormData from 'form-data';
import { IncomingForm } from 'formidable';
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(req, res) {
if (req.method !== 'POST') {
res.status(400).json({ error: 'Only POST method allowed' });
return;
}
const form = new IncomingForm();
form.keepExtensions = true;
form.multiples = true;
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: 'Failed to parse the request' });
return;
}
const formData = new FormData();
formData.append('registerStoreRequestDto', fields.data);
const images = Array.isArray(files.images) ? files.images : [files.images];
images.forEach(file => {
const ext = path.extname(file.name);
formData.append('images', fs.createReadStream(file.path), file.name + ext);
});
try {
const httpInstance = createHttpInstance(req);
const response = await httpInstance.post('/store', formData, {
headers: formData.getHeaders(),
});
if (response.status === 200) {
res.status(200).json({ success: true });
} else {
res.status(500).json({ error: 'Failed to upload files' });
}
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to upload files' });
}
});
}
path.extname(file.originalFilename)
를 사용하여 파일 확장자를 얻었다. => 확장자가 안들어가서 당황스러웠다.. 나중에 따로 글을 작성해야겠다.formidable
의 parse
함수는 fileds
와 files
두 개의 객체를 전달하는데 이름에서 예상할 수 있지만 fields
는 필드정보를 담고있고 files
객체는 업로드한 파일에 대한 정보를 담고 있다.