사용자가 아이디, 이름, 비밀번호, 이미지 파일을 넣으면 서버에 해당 데이터를 함께 보내고 싶었어요. 네트워크 메서드인 fetch()
를 사용해서요!
이미지 파일 전송이 문제라서 이미지 파일만 먼저 테스트했어요. 로그인, 회원가입 실습 때 텍스트만 보내봤지 이미지는 처음이라 굉장히 생소했던.. 하루종일 끙끙대다가 FormData
에 append()
로 이미지 파일을 넣을 때의 key값을 백엔드분과 일치시키니 FormData
가 제대로 서버로 넘어가는걸 확인할 수 있었답니다~!🎉
서버에 보낸 FormData
를 콘솔에 찍으면 다음과 같이 나와요. 이메일, 이름, 닉네임, 비밀번호, 프로필 이미지, 이렇게 5가지를 담아 보냈어요. 그리고 FormData
를 콘솔에 찍어볼때는 console.log(FormData)
와 같은 식으로 하면 빈 객체만 나와요. for문을 사용해서 콘솔을 찍어줘야한다는 점-!까지 배울 수 있었습니다🤗
회원가입 버튼을 눌렀을 때 onClick이벤트로 아래의 함수가 실행됩니다. new FormData()
로 FormData
객체를 생성했고, 사용자가 입력한 email, name, nickname, password, 이미지파일을 append()
메소드로 넣어주었어요. 그리고 Request메시지의 본문(body)에 생성한 FormData
객체를 넣어주었어요.
// 회원가입 버튼의 onClick이벤트
const checkSignUp = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("email", email);
formData.append("name", name);
formData.append("nickname", nickname);
formData.append("password", password);
formData.append("profileImg", imgRef.current.files[0]);
fetch("API 주소", {
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
},
body: formData,
})
.then((response) => {
if (response.ok === true) {
return response.json();
}
throw new Error("에러 발생!");
})
.catch((error) => {
alert(error);
})
.then((data) => {
console.log(data);
});
};
formData
와 <form>
태그에 대해 공부해보니 제가 작성한 코드보다 더 효율적인 방법이 있는 것 같아 수정해보려고해요. 저는 HTML form태그가 있음에도 formData
객체에 append로 필드를 추가해주는 방식으로 코드를 짰어요. 근데 HTML form 태그가 있으면 해당 폼만 바로 formData
객체에 넘겨줄 수 있더라구요. 리팩토링에 성공하면 다음 포스팅 때 비교해볼 예정이에요!
FormData
FormData
란?FormData
는 fetch()
와 같은 네트워크 메서드를 통해 HTML 폼(form)을 보내요. 폼(form)을 쉽게 보내도록 도와주는 객체죠.
// FormData 생성하기
const formData = new FormData();
new FormData(form)
로 만들 수 있어요.<!-- HTML form -->
<form id="formElem">
<input type="text" name="name" value="hyerin">
<input type="text" name="surname" value="joo">
<input type="submit">
</form>
// HTML form 직접 넘기기
fetch('API 주소', {
method: 'POST',
body: new FormData(formElem)
});
HTML form이 없을 때
: formData.append(name, value)
와 같이 메서드로 직접 name
과 value
를 가진 폼 필드를 추가해 만들 수도 있어요.
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
fetch('API 주소', {
method: 'POST',
body: formData;
});
fetch()
와 같은 네트워크 메서드가 FormData 객체를 본문(Body)으로 받는다.Content-Type
속성은 multipart/form-data
로 지정되어 전송된다.Content-Type
속성은 항상 multipart/form-data
. 콘솔로 FormData
에 값이 제대로 담긴건지 확인하고 싶을 때, 저는 처음에 아무것도 모르고 console.log(FormData)
를 남발했어요. 계속 빈 객체만 콘솔에 찍혔답니다. 반복문을 사용해야 확인할 수 있다는걸 알게됐어요.
const formData = new FormData();
for (const keyValue of formData) console.log(keyValue);
<form>
태그🤔 서버 관점에선
FormData
를 사용한 방식과 일반 폼 전송 방식(<form>
)에 차이가 없다고 해요. 심지어 HTTP 요청 메시지의 본문(Body)에FormData
를 보낼 때, 헤더의Content-Type
속성은<form>
태그의enctype
속성과 관련있다는 것을 알게 됐답니다. 그래서<form>
태그의enctype
은 무엇인지 정리하게 됐어요.
enctype
속성<form>
태그의 enctype 속성은 폼 데이터가 서버로 제출될 때 해당 데이터가 인코딩되는 방법을 명시해요. 이 속성은 <form>
요소의 method 속성값이 POST
인 경우에만 사용할 수 있어요.
<form enctype="속성값">
📜 인코딩(Encoding)이란?
- 사용자가 입력한 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것입니다. 컴퓨터는 모든 정보를 0과 1인 바이너리, 즉 숫자로 저장합니다.
- 반대로 디코딩은 0과 1로 구성된 바이너리 데이터를 다시 문자로 복구하는 것입니다.
application/x-www-form-urlencoded
multipart/form-data
text/plain
Content-Type
폼(form) 데이터가 서버로 제출될 때 해당 데이터가 인코딩되는 방법까지 알았으니, 이제 HTTP요청 메시지의 Content-Type
을 어떻게 작성해야할 지 알 수 있어요. 요청(Request) 메시지의 헤더에서 서버에게 어떤 유형의 데이터가 실제 전송되었는지를 Content-Type
을 통해 알려줄 수 있답니다.
HTML 양식은 앞서 <form>
태그의 enctype 속성값에서 본 것과 같이 세 가지의 인코딩 방법을 제공하죠. <input type="file">
요소가 포함된 경우에는 multipart/form-data
를 사용해요.
// 요청 메시지의 헤더
headers: {
"Content-Type" : "multipart/form-data",
}