

Dansup 프로젝트에서, 백엔드 개발자로부터 사용자가 회원가입할 때 기입한 "
Object 형태의 작성 정보와File 형태의 이미지,동영상을 각각 다른 api가 아닌 '하나의 api'를 통해 함께 서버로 보내달라"는 요청을 받았다.
FormData.append(name, value) 메서드를 이용해 FormData에 데이터를 추가할 수 있다 → 단, FormData의 value로 'string'과 'Blob' 타입의 데이터만 추가할 수 있다! (*File은 Blob을 확장한 형태)원래 Object 데이터는 JSON 문자열로 변환하여 Content-Type을 'application/json'으로 지정하여 서버로 전송하고,
File 데이터는 FormData에 추가하여 Content-Type을 'multipart/form-data'로 지정하여 FormData를 서버로 전송한다.
🤔 그렇다면, Object 데이터와 File 데이터를 '하나의 api'로 함께 서버로 전송하려면 어떻게 해야할까?
⇒ ⭐️두 가지 타입 이상의 데이터를 구분하여 함께 전송할 수 있는, Content-Type 'multipart/form-data'를 이용⭐️해야 하기 때문에, File 데이터 뿐만 아니라 Object 데이터 또한 FormData에 추가하여 Content-Type을 'multipart/form-data' 지정하여 FormData를 서버로 전송하면 된다...!!
📍 Object 데이터를 FormData에 추가하는 자세한 과정은 다음과 같다.
Object 데이터를 JSON.stringify( )를 이용하여 JSON 문자열로 변환한다.JSON.stringify(Obj)const blob = new Blob([JSON.stringify(Obj)], {type: 'application/json'});
formData.append('info', blob);Object 데이터와 File 데이터를 함께 FormData에 추가하는 전체 코드는 다음과 같다.
//FormData 객체 생성
const formData = new FormData();
//FormData에 'Object 데이터' 추가
const blob = new Blob([JSON.stringify(Obj)], {type: 'application/json'});
formData.append('info', blob);
//FormData에 'File 데이터' 추가
formData.append('file', file);
⇒ 이렇게 Object 데이터와 File 데이터를 함께 추가한 FormData를 Content-Type을 'multipart/form-data'로 지정하여 '하나의 api'로 서버로 전송하면 된다!!
위에서 설명한 내용을 토대로 Dansup 프로젝트에서, 사용자가 회원가입할 때 기입한 Object 형태의 작성 정보와 File 형태의 이미지,동영상을 '하나의 api'를 통해 함께 서버로 전송하는 코드를 다음과 같이 작성했다.
import { useMutation } from '@tanstack/react-query';
import { register } from '@/apis/auth';
~
const registerMutation = useMutation(register, {
onSuccess: data => {
console.log(data);
},
onError: error => {
console.log(error);
},
});
//사용자가 정보를 모두 기입 후 제출 버튼을 누르면
const handleSubmit = () => {
//1. FormData 객체 생성
const formData = new FormData();
//2. FormData에 'Object 형태의 작성 정보' 추가
formData.append(
'signUpDto',
new Blob(
[
JSON.stringify({
username: ~,
nickname: ~,
intro: ~,
genres: ~,
hashtag1: ~,
hashtag2: ~,
hashtag3: ~,
portfolios: ~,
})
],
{ type: 'application/json' }
)
);
//3. FormData에 'File 형태의 이미지' 추가
if (imgFile instanceof File) {
formData.append('profileImage', imgFile);
} else {
formData.append('profileImage', ''); //imgFile이 없다면, ''(빈 string) 추가
}
//4. FormData에 'File 형태의 동영상' 추가
if (videoFile instanceof File) {
formData.append('profileVideo', videoFile);
} else {
formData.append('profileVideo', ''); //videoFile이 없다면, ''(빈 string) 추가
}
//5. Object 형태의 작성 정보와 File 형태의 이미지,동영상이 함께 추가된 FormData를 register api('하나의 api')를 호출해서 서버로 전송
registerMutation.mutate({
formData: formData,
accessToken: accessToken,
});
};
백엔드 개발자님께서 사용자가 이미지나 동영상 File을 따로 첨부하지 않으면, 서버로 File 대신 null을 보내달라고 하셨다.
문제) 그런데, FormData에 추가한 null이 자동으로 'null'로 변환되어 서버로 전송되어 문제가 발생했다..!! 😓
원인) 알고보니 FormData.append(name, value) 메서드를 이용해 value에 데이터를 추가할 시에, value에 문자열 이외의 데이터 타입을 넣으면 무시되고 '문자열로 자동 변환'되는 특징이 있었다!
문제 해결!) 그래서 백엔드 개발자님께 말씀드려 이미지나 동영상 File이 없는 경우에는 null이 아니라 ''(빈 string)을 추가하는 것으로 문제를 해결했다..!
if (imgFile instanceof File) {
formData.append('profileImage', imgFile);
} else {
formData.append('profileImage', ''); //File이 없다면, ''(빈 string) 추가
}