fetch를 통해 Route Handler로 요청을 보낼 때, data에 파일을 그대로 넣었더니 json()
메서드로 파싱시, 에러가 발생했다.
// StoryForm.tsx
const uploadImageFile = async (file: File) => {
const res = await fetch(url, {
method: 'POST',
body: compressedImageFile,
});
//...
}
// route.ts
export const POST = async (req) => {
const requestBody = await req.json();
// SyntaxError: Unexpected token R in JSON at position 0
}
파일을 API Route로 보내고 처리하는 과정에서 JSON으로 데이터를 파싱하려고 시도했을 때 발생하는 문제는 파일 데이터를 JSON 형식으로 직접 보내려고 했기 때문이다.
파일은 바이너리 데이터이므로 JSON 형식으로 직접 변환되지 않는다. 따라서 파일을 전송할 때는 FormData 객체를 사용하여 멀티파트 형식으로 데이터를 인코딩해야 한다.
// StoryForm.tsx
const uploadImageFile = async (file: File) => {
const formData = new FormData();
formData.append('file', file);
const res = await fetch(url, {
method: 'POST',
body: formData,
});
//...
}
// route.ts
export const POST = async (req) => {
const requestBody = await req.formData();
// ...
}
Route Handler에서 요청 formData에 있는 내용이 File 타입인지 확인하기 위해, instanceof
를 통해 체크하려고 했다.
하.지.만
에러가 발생했다.
const checkIsFile = (value: unknown): value is File => {
return value instanceof File;
}
// ReferenceError: File is not defined
File
객체가 서버 측(Node.js) 환경에서 정의되어 있지 않기 때문이다. File
객체는 브라우저의 Web API의 일부로, 브라우저 환경에서만 사용할 수 있다. 따라서, Next.js의 서버 측 로직(ex: API Route Handler)에서는 접근할 수 없다.
formData에 담긴 file 객체의 타입을 체크하진 않고, 존재하는지만 확인하도록 함.
export const POST = async (req: NextRequest) => {
const formData = await req.formData();
const file = formData.get('file');
if (!file) {
return NextResponse.json({ message: "BadRequest" }, { status: 400 });
}
// ...
}