multipart - woowacourse-teams/2023-fun-eat GitHub Wiki
โํ์โ์๋ ํธ์์ ์์์ ๋จน๊ณ ๋ฆฌ๋ทฐ๋ฅผ ์์ฑํ ์ ์๋ ํผ์ด ์๋ค.
์ฌ์ฉ์๋ ๋ฆฌ๋ทฐ์ ์ฌ์ง, ๋ณ์ , ํ๊ทธ, ๋ฆฌ๋ทฐ ๋ด์ฉ, ์ฌ๊ตฌ๋งค ์์ฌ๋ฅผ ๋จ๊ธธ ์ ์๋ค.
์ด ๊ณผ์ ์์ ์ด๋ฏธ์ง ํ์ผ์ ์๋ฒ๋ก ๋ณด๋ผ ๋ ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
์ด๋ค ๋ฌธ์ ๊ฐ ์๊ธฐ๋์ง ์์๋ณด์.
์ด๋ฏธ์ง๋ File ํํ์ด๋ค.
<input ref={inputRef} type="file" accept="image/*" onChange={handle} />๋ณดํต ์์ ํ์์ฒ๋ผ input type์ file๋ก ์ฃผ๋ฉด ํ์ผ ์ ๋ก๋๋ฅผ ํ ์ ์๋ค.
์ด๋ ๊ฒ file์ ์๋ฒ๋ก ์ ์กํ๋ฉด ํด๋น file ๋ฐ์ดํฐ๋ฅผ multipart/form-dataํํ๋ก ๋ฐ๊ฒ ๋๋ค.
์ฐ๋ฆฌ๊ฐ ์๊ฐํ๋ โํ์ผ์ด๋ฆ.ํ์ฅ์โ ํ์์ด ์๋ ์ด์ง ๋ฐ์ดํฐ ํ์์ผ๋ก ๋ฐ๋๋ค.
์ด์ File ํํ์ ์ด๋ฏธ์ง์ ๋ด์ฉ์ ํ ๋ฒ์ ์๋ฒ๋ก ๋ณด๋ด๋ณด์.
์ด๋, formData ๊ฐ์ฒด๋ฅผ ํตํด ๋ณด๋ผ ์ ์๋ค.
formData๋ form ๋ฐ์ดํฐ๋ฅผ ๋์ ์ผ๋ก ์์ฑํ๊ณ ์ ์กํ ์ ์๋ ๊ฐ์ฒด์ด๋ค.
append()๋ฅผ ์ฌ์ฉํด ๋ด์ฉ์ key์ value ํ์์ผ๋ก ๋ณด๋ผ ์ ์๋ค.
formData.append('image', reviewImageFile, reviewImageFile.name);์ด formData๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ multipart/form-data ํ์์ผ๋ก ๋ณด๋ผ ์ ์๋ค.
form์ ๋ด์ฉ์ ๋ชจ๋ ์์ฑํ๊ณ ์ ์ถ์ ๋๋ฌ๋ณด์.
์์ฑํ ๋ฐ์ดํฐ๋ค์ Body์ ๋ฃ์ด HTTP Request๋ก ์๋ฒ์ ์ ์ก๋๋ค.
์ด๋, Body์ ํ์ ์ ๋ช ์ํ๋ ๊ฒ์ด Content-type Headers์ด๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก form์ ์ ์กํ๋ฉด Content-type์ application/x-www-form-urlencoded ์ด๋ค.
๊ทธ๋ฐ๋ฐ ์ฐ๋ฆฌ๋ ์ด๋ฏธ์ง๋ฅผ ๋ด์ฉ๊ณผ ํจ๊ป ์ ์กํด์ผ ํ๋ค.
์ด๋ฏธ์ง๋ file ํํ์ด๊ณ , ๋ด์ฉ์ json ํํ๋ก ๋์ Content-type์ด ๋ค๋ฅด๋ค.
๋ค๋ฅธ ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ ํ๋์ HTTP Request Body์ ๋ฃ์ด์ผ ํ๋ค๋ฉด ์ด๋ป๊ฒ ๊ตฌ๋ถํ ์ ์์๊น?
์ด๋, multipart ํ์ ์ ํตํด ํด๊ฒฐํ ์ ์๋ค.
multipart๋ ๋ค์ํ ํํ์ ์ฝํ ์ธ ๋ฅผ ํจ๊ป ์ ์กํ ๋ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
๊ทธ๋ผ, Content-type์ multipart/form-data๋ก ์ง์ ํ๋ฉด ๋ ๊น?
์์ค. ์๋๋ค.
์์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
์ ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊น?
๊ธฐ๋ณธ์ ์ผ๋ก formData์ ํ์ผ์ด ์์ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ๋ ์๋์ผ๋ก boundary๋ฅผ ๋ถ์ฌ์ค๋ค.
๊ทธ๋ฐ๋ฐ Content-type์ ์ค์ ํด ์ฃผ๋ฉด ์ด๊ฒ Override ๋์ด boundary๊ฐ ์ฌ๋ผ์ง๊ฒ ๋๋ค.
๊ทธ๋์ ์์ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด Content-type์ ์ ์ ์ผ๋ฉด ํด๊ฒฐ๋ ๊น?
์์ค. ์๋๋ค.
์ด์ ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
์ ์ด๋ฐ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊น?
formData๋ฅผ ์ ์กํ ๋, ์ด๋ฏธ์ง ์ด์ธ์ ๋ด์ฉ์ JSON.stringify ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
const ๋ด์ฉ = {
rating,
tagIds,
content,
rebuy,
};
const ๋ด์ฉjson๋ณํ = JSON.stringify(๋ด์ฉ);์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ๋, ๋ฐ์ดํฐ๋ ๋ฌธ์์ด ํํ์ฌ์ผ ํ๊ธฐ์ ๊ฐ์ฒด๋ฅผ ๋ฌธ์์ด๋ก ์ธ์ฝ๋ฉ ํ ํ ์ ์กํด์ผ ํ๋ค.
๋ฐ๋ผ์ JSON.stringify() ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ JSON ๋ฌธ์์ด๋ก ๋ณํํ๋ค.
์ฌ๊ธฐ์ json ๋ฐ์ดํฐ๋ฅผ application/json ํ์
์ผ๋ก ๋ช
์ํด ์ฃผ์ง ์์ octet-stream(8๋นํธ ๋จ์์ ์ด์ง ๋ฐ์ดํฐ)์ผ๋ก ์ธ์ํ๊ฒ ๋ ๊ฒ์ด๋ค.
์ด๋ 'Blob(Binary Large Object)'์ ํตํด ํด๊ฒฐํ ์ ์๋ค.
Blob์ ์ด๋ฆ ๊ทธ๋๋ก ๋ฐ์ด๋๋ฆฌ ํํ๋ก ํฐ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ ์ ์๋ค.
์๊น JSON.stringify()ํ JSON ๋ฌธ์์ด์ Blob ์ฒ๋ฆฌํด ๋ณด์.
const jsonBlob = new Blob([๋ด์ฉjson๋ณํ], { type: 'application/json' });Blob ์ฒ๋ฆฌ๋ฅผ ํ๋ฉด JSON ๋ฌธ์์ด์ ์ด์ง ๋ฐ์ดํฐ๋ก ๋ณํํด ์ค๋ค.
type์ application/json ์ ๋ช
์ํ์ฌ ๋ฐ์ดํฐ๊ฐ JSON ์ ํ์์ ์๋ ค์ค๋ค.
์ด๋ ๊ฒ Blob ์ฒ๋ฆฌ๋ ๋ด์ฉ์ formData์ ๋ฃ์ด์ค๋ค.
formData.append('reviewRequest', jsonBlob);๊ทธ๋ฆฌ๊ณ body์ formData๋ฅผ ์ค์ด POST๋ก ๋ณด๋ด๋ฉด
const response = await fetch(url, {
method: 'POST',
body: formData,
credentials: 'include',
});
์์ฑ ์ฑ๊ณต!!!