📌 상황
이름, 주소, 이미지 정보를 서버로 전달해야 했다.
이미지는 multer를 사용했기에 프론트에서 이미지 정보를 formData로 보내야 했고,
문자열로 데이터를 전달할 때와 axios의 header 안의 Content-Type이 달라졌다.
그렇기 때문에 이름, 주소는 문자열로 전달하고,
이미지를 formdata로 보내서 API를 두 번 호출해야했다.
그런데 나는 API 호출을 최소화하고 싶었기에 한 번에 같이 보낼 수 있는 방법이 없을까 고민했다.
아무리 검색해봐도 이렇게 정보를 함께 보내는 경우를 볼 수 없어서
백엔드 팀원과 새벽에 3시간을 고전하다가, 결국 해결책을 찾았다.
이름, 주소도 formdata 안에 넣어서 이미지와 함께 보내는 것이다.
이런 방법도 있다~ 하면서 참고로 봐주시면 좋겠다.
🤔 해결 과정
formData란?
HTML의 form을 대신하는 객체로, 직접 폼 객체를 만들어서 서버에 전달할 때 사용함.
주로 이미지를 전달할 때 사용함
1. 이미지 정보를 배열로 저장하기
// 이미지 파일 선택하면 실행되는 함수
// 이미지 정보가 담긴 배열이 상태에 저장됨
const onChangeImg = (e) => {
e.preventDefault();
if (e.target.files) {
const imgArr = e.target.files;
if (imgArr.length > 3) {
alert('이미지는 3개까지 등록 가능합니다.');
e.target.value = '';
} else setImgs(imgArr); // 이미지 정보가 담긴 배
}
};
2. 보낼 정보를 모두 formdata로 변환해서 전달하기
name, address, description 정보는 모두 상태값으로 만들어서
input을 통해 유저에게 값을 받았다고 가정했다.
이미지를 보내기 위해 formdata로 해당 배열을 감싸는 것처럼
위 정보들도 함께 감싸서 하나의 formdata를 만들었다.
그 다음에 API를 호출해서 formdata 자체를 전달하면 된다!
// 전송 누르면 실행되는 함수
const onClickRegistration = async () => {
const formData = new FormData();
// 모든 정보가 입력되야 실행됨
if (name && address && description && owner && imgs) {
formData.append('name', name);
formData.append('address', `${address}${detailaddress}`);
formData.append('description', description);
Array.from(imgs).forEach((img) => {
formData.append('file', img); // name명은 백과 맞춰야함
});
try {
await axios(`/api/farms`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
data: formData,
});
alert('등록되었습니다.');
navigate('/farm');
} catch (e) {
alert('등록에 실패했습니다.');
console.log(e);
}
} else {
alert('정보를 모두 입력해주세요.');
}
};
'Programming > Client' 카테고리의 다른 글
[Typescript] 'HTMLElement | null' 형식은 'HTMLElement' 형식에 할당할 수 없습니다. (0) | 2023.03.30 |
---|---|
[React] 프론트단에서 페이지네이션 구현하기 (0) | 2023.02.15 |
[React] 전역에서 사용 가능한 모달 만들기 (0) | 2023.01.08 |
[Javascript] 모듈로 설정된 파일의 변수는 전역 변수가 아니다! (0) | 2023.01.06 |
[Javascript] array.reduce() 콜백함수 속 증감연산자 (0) | 2022.05.03 |