multipart/form-data(Content-type)

김철준·2023년 11월 11일
2

Javascript

목록 보기
16/16

프론트쪽에서 서버에 데이터를 보낼 때, 데이터 중 파일 객체 데이터가 포함되어있다면 특정 작업들을 추가적으로 해줘야한다.

특정 작업들이란 크게 두가지이다.

  1. 헤더의 content-type을 mulitpart/form-data로 변경
  2. 요청 데이터를 formData로 변환

헤더 Content-type 변경

mulitpart/form-data


axios.post("www.test.com",{
'Content-Type': 'multipart/form-data'
})

client.patch('/member/mypage', createFormData(params), formHeaders)

기본적으로 서버에 데이터를 보낼 때, content-type은 json으로 보내준다.

application/json

axios.post("www.test.com",{
'Content-Type': 'application/json'
})

기본적으로 프로젝트에서 axios 서버 통신 파일을 세팅할 때, json으로 설정해준다.

그래서 만약 특정 API를 요청할 때, header를 mulitpart/form-data로 변경해야한다면 요청 메서드의 세번째 인자에 담아 보내줘야한다.

export const formHeaders = {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
};

client.patch('/member/mypage', data, formHeaders)

데이터를 formData로 변환

여기서 헤더만 변경하는 것이 아니라 보내는 데이터를 formData로 변환해줘야하는 작업이 추가로 필요하다.

예를 들어서, 서버로 보내는 데이터가 다음과 같다고 해보자.


const data ={
name :"jev",
email:"test@test.com",
profile : new File() // 임의로 파일 객체 설정(유효한 코드 아님)
}

client.patch('/member/mypage', data, formHeaders)

이 때, 위와 같이 보내면 415(Unsupported Media Type)에러가 발생할 것이다.

이유는 data를 formData로 변경해주지 않아서이다.

data를 formData를 변경하기 위해서는 다음과 같이 하면 된다.

  • FormData 생성자를 사용하여 formData 객체를 생성
  • formData 객체에 data를 담아준다.
// 서버로 보낼 데이터
const data ={
name :"jev",
email:"test@test.com",
profile : new File() // 임의로 파일 객체 설정(유효한 코드 아님)
}

// 데이터를 formData로 변환해주는 함수
function createFormData(data){

const form = new FormData();

form.append("name",data.name);
form.append("email",data.email);
form.append("profile",data.profile)
  
  return form
}

// API 요청
client.patch('/member/mypage', createFormData(data), formHeaders)

위와 같이 해주면 요청이 성공적으로 된다.

Issue : formData value값이 객체라면?

사내 프로젝트를 진행하면서 서버로 보내줘야하는 데이터의 형태가 다음과 같았다.


const data = {
file : new File(), // 임의로 파일 객체 설정(유효한 코드 아님)
request:{
name :"jev",
email:"test@test.com"
}  

}

데이터가 두개의 key값을 가지는데 file key에 대한 값을 파일 객체, request key에 대한 값은 객체의 형태이다.

그렇다면 위에서 한 방법대로 formData로 변경해주면 되겠다싶어 다음과 같이 변경해줬다.

export const formHeaders = {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
};

// 서버로 보낼 데이터
const data = {
file : new File(), // 임의로 파일 객체 설정(유효한 코드 아님)
request:{
name :"jev",
email:"test@test.com"
}  

}

// 데이터를 formData로 변환해주는 함수
function createFormData(data){

const form = new FormData();

form.append("file",data.file);
form.append("request",data.request);
  
  formData.append(
    "request",
    new Blob([JSON.stringify(postData.request)], {
      type: "application/json",
    })
  );
  
  return form
}

// API
 client.post(`event`, createFormData(data), formHeaders);

하지만 위와 같이 요청을 하면 에러가 발생한다.

결론적으로 우선 다음과 같은 형태로 데이터를 보내줘야한다.

export const formHeaders = {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
};

// 서버로 보낼 데이터
const data = {
file : new File(), // 임의로 파일 객체 설정(유효한 코드 아님)
request:{
name :"jev",
email:"test@test.com"
}  

}

// 데이터를 formData로 변환해주는 함수
function createFormData(data){

const form = new FormData();

form.append("file",data.file);
form.append(
    "request",
    new Blob([JSON.stringify(data.request)], {
      type: "application/json",
    })
  );
  
  return form
}

// API
 client.post(`event`, createFormData(data), formHeaders);

그렇다면 왜 문자열화해주고 blob처리를 해줘야할까?

우선 formdata를 서버에 데이터를 전송할 때에, 일반 텍스트 데이터라면 그냥 전송해도 되지만 데이터가 객체라면 이를 이진 데이터로 처리하여 보내줘야한다.

텍스트 데이터


// success
const data = "jev"

const form = new FormData()

form.append("data",data)

객체 데이터

// failure
const data = {
name :"jev"
}

const form = new FormData()

form.append("data",data)

자바스크립트 객체는 텍스트가 아닌 이진 데이터이기 때문에, 이를 이진 형태로 전송해야한다.
Blob을 사용하면 이진 데이터를 효과적으로 전송할 수 있다.

Blob
Blob은 이진 형식의 데이터이다.
new Blob()을 통해 이진 데이터를 생성하거나 이진 데이터로 변환해줄 수 있다.

그리고 new Blob으로 데이터를 처리할 때, 일반 객체 데이터를 담을 경우 이를 문자열화해줘야하기 때문에 위와 같이 처리해주는 것이다.

export const formHeaders = {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
};

// 서버로 보낼 데이터
const data = {
file : new File(), // 임의로 파일 객체 설정(유효한 코드 아님)
request:{
name :"jev",
email:"test@test.com"
}  

}

// 데이터를 formData로 변환해주는 함수
function createFormData(data){

const form = new FormData();

form.append("file",data.file);
form.append("request",data.request);
  
  formData.append(
    "request",
    new Blob([JSON.stringify(postData.request)], {
      type: "application/json",
    })
  );
  
  return form
}

// API
 client.post(`event`, createFormData(data), formHeaders);

서버에 데이터를 보낼 때에, 파일이 있는 경우 원시 데이터뿐만 아니라 객체도 보내는 경우가 많으니 참고하도록 하자.

profile
FE DEVELOPER

2개의 댓글

comment-user-thumbnail
2024년 1월 8일

근데 글을보니까 어떤건 postData고 어떤건 data고 구분이 잘안가네용.. 혹시 오타인가요??

form.append("file",data.file);
form.append("request",data.request);

formData.append(
"request",
new Blob([JSON.stringify(postData.request)], {
type: "application/json",
})
);

이거는 왜 두번하는지 궁금합니다! 그리고 postData인지도..

1개의 답글