오늘의 명언
“ 당신은 소프트웨어 품질을 추구할 수도 있고, 포인터 연산을 할 수도 있다. 그러나 두 개를 동시에 할 수는 없다. ”
-
베르트랑 마이어 (Bertrand Meyer)
300x250
프로젝트를 진행하던 도중 백엔드로 이미지파일과 이미지 정보를 전송하는 일이 있었는데 그때 사용하는 FormData라는 API를 사용하는 방법에 대해서 간단하게 알아보고자 합니다.
서버에 데이터 전송 과정
클라이언트에서 서버로 데이터를 주고받을 때 HTTP 통신 규약으로 전송이 되는데, HTTP Request Header에 전송할 데이터는 어떤 것인지 명시하기 위해 Content-Type이라는 속성을 사용합니다. RestFul API 요청을 많이 사용하므로 보통은 Content-Type에 application/json으로 설정하여 많이 사용합니다. 정리하면 Body에 담은 데이터를 어떤 방식으로 인코딩하여 전송할지 설정하는 것입니다.
이미지 데이터 전송 과정
통상 알고 있는 이미지 데이터는 png나 jpg인데, 이 이미지파일을 전송할 때 파일자체가 전송되는 게 아니라 그 파일을 문자로 변환하여 Body에 담아서 보냅니다. 그런데 우리는 이미지 파일을 서버로 전송할 때 이미지 파일만이 아니라 정보를 담고 있는 객체도 포함해서 보낼 것이므로 Content-Type multipart/form-data 속성을 사용하여 FormData 형식으로 데이터를 Key Value 값으로 넣어서 이미지와 이미지정보를 담아서 보내는 방법을 알아보겠습니다.
FormData 사용법
필드 및 해당 값을 Key / Value 쌍으로 구성하여 사용합니다.
// FormData 객체 생성
let formData = new FormData();
// key value 추가
formData.append('item',1);
// input Type이 'file'인 경우 사용
// filename은 파일의 이름
formData.append('file',blob, fileName);
// Key 값으로 삭제
formData.append('item');
// 해당 Key값의 value를 반환
formData.get('item');
// Key와 관련된 모든 값의 배열을 반환
formData.getAll('item');
// 주어진 Key 값의 해당 하는 필드가 있을 경우 True / False
formData.has('item');
// formData Key값 확인
for(const key of formData.keys()){
console.log(key);
}
// formData value값 확인
for(const key of formData.values()){
console.log(key);
}
// formData key value 값 확인
formData.append('key1', 'value1');
formData.append('key2', 'value2');
for(var data of formData.entries()) {
console.log(data[0]+ ', '+ data[1]);
}
// 결과
// key1, value1
// key2, value2
서버로 FormData 전송
서버로 전송할 때 form data 타입 형식에 맞춰 헤더 타입을 mutipart/form-data로 설정을 하고 FormData 객체를 생성하여 데이터를 설정하고 Body에 담아서 전송합니다.
// FormData 객체 생성
const formData = new FormData();
// file 추가
formData.append('file', file);
// Content-Type 설정
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
// axios post
const { data } = await axios.post('/contents', formData, config);
Nuxt 예제
Nuxt로 된 예제파일입니다 input태그에 담은 데이터 접근은 e.target.files [0]로 할 수 있으니 React로 비슷하게 구현할 수 있습니다 한번 참고용으로 봐주세요.
<template>
<input
type="file"
accept="image/*"
multiple="multiple"
class="form-control-file"
@change="fileChange"
/>
</template>
export default {
name:'test',
methods:{
fileChange(e) {
// input 태그로 담은 파일 데이터
const file = e.target.files[0]
console.log(file)
// Content-Type 설정
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
// FormData 객체 안에 파일 데이터 넣기
const formData = new FormData()
formData.append('image', file, 'NuxtLogo')
//axios post로 formData 담아서 서버로 보내기
const { data } = await axios.post('/contents', formData, config);
}
}
}
File 데이터와 Json 객체 담아서 전송
// FormData 객체 생성
const formData = new FormData();
// image file 추가
formData.append('image', file);
const data ={
titie: 'test'
}
// Blob 객체에 data를 json으로 변환한뒤 담는다.
const blob = new Blob([JSON.stringify(data)], {
// JSON 타입 지정
type: 'application/json',
});
formData.append('data', blob);
// Content-Type 지정
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
};
const { data } = await axios.post('/contents', formData, config);
File이 여러 개일 때 추가 방법 (다중 파일)
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
FormData API에 대해서 간단하게 알아보았습니다. 프로젝트를 진행할 때 이미지 또는 영상 등 다양한 파일들을 서버로 보내게 될 텐데 formData로 설정하여 한번에 묶어서 보내는 방법으로 사용하시면 좋을 거 같습니다. 도움이 되셨으면 좋겠고 혹여나 틀린 부분이나 수정되어야 할 부분이 있으면 댓글 부탁드립니다. 감사합니다.
반응형
잘못된 내용이 있으면 댓글 부탁드립니다. 감사합니다.