๐ FormData ์ฌ์ฉ๋ฒ & ์์ฉ ์ด์ ๋ฆฌ (+ fetch ์ ์ก)
FormData API
๋ณดํต ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๊ธฐ ์ํด์๋ HTML5 ์ ํผ ํ๊ทธ๋ฅผ ์ฌ์ฉํด ๋ค์๊ณผ ๊ฐ์ด ๋ฉ๋ด๋ฅผ ๊ตฌ์ฑํ์ฌ ์ ์ถ ํด๋ณธ ๊ธฐ์ต๋ค์ด ์์ ๊ฒ์ด๋ค.
<form action="./login" method="post">
<strong>์์ด๋</strong>
<input type="text" name="name" value="์์ด๋ ์
๋ ฅ">
<strong>๋น๋ฐ๋ฒํธ</strong>
<input type="password" name="password" value="๋น๋ฐ๋ฒํธ ์
๋ ฅ">
<strong>์ฑ๋ณ</strong>
<input type="radio" name="gender" value="M">๋จ์
<input type="radio" name="gender" value="F">์ฌ์
<strong>์์๋ถ์ผ</strong>
<input type="checkbox" name="part" value="eng">์์ด
<input type="checkbox" name="part" value="math">์ํ
<input type="submit" value="์ ์ถ">
</form>
์ด ์ฒ๋ผ ๋ณดํต์ HTML5์ <form> ํ๊ทธ์ด์ฉํด input ๊ฐ์ ์๋ฒ์ ์ ์กํ์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ์์ FormData() ํด๋์ค๋ฅผ ์ด์ฉํด ๋๊ฐ์ด ์คํฌ๋ฆฝํธ๋ก๋ ์ ์ก์ ํ ์ ์๋ค.
์ฆ, FormData๋ HTML ๋จ์ด ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋จ์์ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฐ์ฒด๋ผ๊ณ ๋ณด๋ฉด ๋๋ค. ๊ทธ๋ฆฌ๊ณ HTML์์์ Submit ์ ์ถ ๋์์ Ajax๋ฅผ ํตํด ์๋ฒ์ ์ ์ถํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
let formData = new FormData(); // new FromData()๋ก ์๋ก์ด ๊ฐ์ฒด ์์ฑ
formData.append('item','hi'); // <input name="item" value="hi"> ์ ๊ฐ๋ค.
formData.append('item','hello'); // <input name="item" value="hello">
FormData๋ ์ธ์ ํ์ฉ๋๋๊ฐ
๋๋ถ๋ถ์ ๋ ์๋ถ๋ค์ HTML์์๋ ์ถฉ๋ถํ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ์ ์๋๋ฐ ์ ๊ตณ์ด ์๋ฐ์คํฌ๋ฆฝํธ์์ ํผ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋์ง ์ ๋ฟ์ง ์์ ๊ฒ์ด๋ค. ์ฌ์ค์ ์๋ฐ์คํฌ๋ฆฝํธ์์ Ajax๋ก ํผ(form ํ๊ทธ) ์ ์ก์ ํ ์ผ์ด ๊ฑฐ์ ์๋ค๊ณ ๋ณด๋ฉด๋๋ค.
ํ์ง๋ง HTML์ด ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋จ ์์ form ์ ์ก ๋์์ด ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ์ด๋ฏธ์ง ๊ฐ์ ๋ฉํฐ๋ฏธ๋์ด ํ์ผ์ ํ์ด์ง ์ ํ ์์ด ํผ ๋ฐ์ดํฐ๋ฅผ ๋น๋๊ธฐ๋ก ์ ์ถ ํ๊ณ ์ถ์ ๋๋, ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์ข๋ ํ์ดํธํ๊ฒ ํผ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ถ์๋ formData ๊ฐ์ฒด๋ฅผ ์ด์ฉํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
// ์๋ฐ์คํฌ๋ฆฝํธ๋ก ์ง์ form ํ๊ทธ๋ฅผ ์์ฑ
let formData = new FormData(); // ์๋ก์ด ํผ ๊ฐ์ฒด ์์ฑ
formData.append('name','hyemin'); // ํผ ๋ฐ์ดํฐ๋ฅผ ์คํฌ๋ฆฝํธ๋ก ์ถ๊ฐ
formData.append('item','hi'); // <input name="item" value="hi"> ์ ๊ฐ๋ค.
formData.append('item','hello'); // <input name="item" value="hello">
// ๋ง์ผ HTML์ ๋ฏธ๋ฆฌ form ํ๊ทธ๊ฐ ์์ผ๋ฉด ์ ์ด์ฟผ๋ฆฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ์ฌ ์๋ ์๋ค.
// ์ ์ด์ฟผ๋ฆฌ์ธ ๊ฒฝ์ฐ
let formData1 = new FormData($("#formId"));
// ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ์ ธ ์ฌ ๊ฒฝ์ฐ
let formData2 = new FormData(document.getElementById("formId"));
์์ฒ๋ผ ํผ ๊ฐ์ฒด์ append() ๋ฉ์๋๋ก key์ value ๊ฐ์ ์ฐจ๋ก๋ก ์ถ๊ฐํด์ฃผ๋ฉด, ๊ณง input ํ๊ทธ์ ๊ฐ์ ์
๋ ฅํ๋ ๊ฒ๊ณผ ๊ฐ์ ํจ๊ณผ๋ฅผ ๊ฐ์ง๋ค. ์ฐธ๊ณ ๋ก ๊ฐ์ ๋ฌด์กฐ๊ฑด "๋ฌธ์์ด"๋ก ์๋ ๋ณํ ๋๋ค. ๊ฐ์ฒด๋ ๋ฐฐ์ด ๊ฐ์ ๋ณต์กํ ๋ฐ์ดํฐ๋ ๋ฃ์ ์ ์๋ค.
๐ฅ formData ์ฃผ์์ฌํญformData.append(name, value)ํจ์๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ๋ฃ์์์ value๋ ๋ฌธ์์ด๋ก๋ง ์ ๋ ฅ ๋๋ค.
๋ง์ผ ๋ฌธ์์ด ์ด์ธ์ ๋ฐ์ดํฐ ํ์ด์ ๋ฃ์ผ๋ฉด ๋ฌด์๋๊ณ ๋ฌธ์์ด๋ก ์๋ ๋ณํ ๋๋ค.
FormData ์ฌ์ฉ๋ฒ
formData.append(name, value)
// - form์ name ๊ณผ value ๋ฅผ ํ๋์ ์ถ๊ฐ
// - input์ name ์์ฑ๊ณผ value ์
๋ ฅ๊ฐ ์ญํ ์ ํ๋ค๊ณ ์๊ฐ ํ๋ฉด ๋๋ค.
formData.append(name, blob, fileName)
// - input ์ type ์ด 'file' ์ธ ๊ฒฝ์ฐ์ ์ฌ์ฉ
// - fileName์ file์ ์ด๋ฆ์ ํด๋น
formData.delete(name)
// - ์ฃผ์ด์ง name ์ผ๋ก ํ๋๋ฅผ ์ ๊ฑฐ
formData.get(name)
// - ์ฃผ์ด์ง name ์ ํด๋น ํ๋ ํ๋ value๋ฅผ ๋ฐํ
formData.getAll(name)
// - append ํจ์๋ก ์ถ๊ฐ์ name์ด ์ค๋ณต ๊ฐ๋ฅ
// - ๋ฐ๋ผ์ ์ฃผ์ด์ง name ์ ํด๋น ํ๋ ํ๋์ ๋ชจ๋ value๋ฅผ ๋ฐํ
formData.has(name)
// - ์ฃผ์ด์ง name ์ ํด๋นํ๋ ํ๋๊ฐ ์์ ๊ฒฝ์ฐ true, ์์ผ๋ฉด false๋ฅผ ๋ฐํ
formData.set(name, value)
formData.set(name, blob, fileName)
// - set ํจ์๋ append ํจ์ ์ฒ๋ผ ํ๋๋ฅผ ์ถ๊ฐ
// - append์ ๋น์ทํ set ๋ฉ์๋๋ set๋ ์ถ๊ฐ๋ฅผ ํด์ฃผ๊ธฐ๋ ํ์ง๋ง, ๊ธฐ์กด key๊ฐ ์์ผ๋ฉด ๊ทธ key๊ฐ์ ๋ชจ๋ ๋ฎ์ด์์๋ฒ๋ฆฐ๋ค
์์ ๋ฉ์๋๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ํ์ฉํ ์๊ฐ ์๋ค.
let formData = new FormData(); // ์๋ก์ด ํผ ๊ฐ์ฒด ์์ฑ
formData.append('item', 'hi');
// key๊ฐ ์กด์ฌํ๋ ์ง ํ์ธ. ๊ฐ์ด boolean type์ผ๋ก ๋ฐํ๋ฉ๋๋ค.
formData.has('item'); // true.
formData.has('money'); // false
// ๊ฐ์ ์ฒซ ๋ฒ์งธ ๊ฐ์ด ๋ฐํ๋ฉ๋๋ค.
formData.get('item'); // hi.
// ์ค๋ณต๋ key๊ฐ์ ๋ชจ๋ ๊ฐ์ ธ์ฌ ๋ ๋ฐฐ์ด ํ์์ผ๋ก ๊ฐ์ ธ์ต๋๋ค.
formData.append('item', 'hello'); // ๋๊ฐ์ item ํค์ ๊ฐ์ ๋ ์ถ๊ฐ
formData.getAll('item'); // ['hi','hello']
// ์ค๋ณต ๋ ๊ฐ์ ๋ฃ์๋๋ ๋ฐฐ์ด๋ก ํ๊บผ๋ฒ์ appendํ ์ ์์ต๋๋ค.
formData.append( 'test', ['hi','hyemin'] );
formData.get('test'); // hi,hyemin
// ์ญ์
formData.delete('test');
formData.get('test'); // null๊ฐ์ด ๋ค์ด๊ฐ๋๋ค.
// item๊ฐ์ ์์ ํฉ๋๋ค.
formData.set('item','test2');
formData.getAll('item); // ['test2']
formData ๊ฐ ์ฝ์ ์ถ๋ ฅ
formData ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ append ๋ฅผ ํตํด key์ value ๊ฐ๋ค์ ์์ฃผ ๋ง์ด ๋ฃ์๋ค๊ณ ํ์. ๊ทธ๋ฌ๋ฉด ๋ด๊ฐ ์ด๋ ํ ํผ ๋ฐ์ดํฐ๋ค์ ๋ฃ์๋์ง ํ์ธํ๊ณ ์ถ์๋, formData ๊ฐ์ฒด๋ฅผ console.log๋ก ์ถ๋ ฅํด ๋ณผ ๊ฒ์ด๋ค.
ํ์ง๋ง ๋ค์ ์ด๋ฏธ์ง์ ๊ฐ์ด ํผ ๋ฐ์ดํฐ์ keys์ values ๊ฐ๋ค์ ์ด๋์๋ ํ์ธํ ์ ์๋ค.
์๋ํ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ์์ FormData ๊ฐ์ฒด๋ ๋จ์ํ ๊ฐ์ฒด๊ฐ ์๋๋ฉฐ XMLHttpRequest ์ ์ก์ ์ํ์ฌ ์ค๊ณ๋ ํน์ํ ๊ฐ์ฒด ํํ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ๊ฐ๋จํ๊ฒ ๋ฌธ์์ด ํํ ์ ์์ด, console.log๋ฅผ ์ฌ์ฉํ์ฌ ํ์ธ์ด ๋ถ๊ฐ๋ฅํ ๊ฒ์ด๋ค.
๊ทธ๋ ์ง๋ง ์ ํ ํ์ธํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ์ ์๋๋ค.
formData ๊ฐ ์ํํ๊ธฐ
์ฌ๋ฌ๊ฐ์ ํผ ๋ฐ์ดํฐ๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ดํฐ๋ฌ๋ธ ํ๊ธฐ ๋๋ฌธ์ for๋ฌธ ์ผ๋ก ์ํ ํ ์๋ ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ํตํด ํผ ๋ฐ์ดํฐ ๊ฐ์ฒด์ ์ด๋ ํ ๊ฐ๋ค์ด ๋ค์ด์๋์ง ํ์ธ์ด ๊ฐ๋ฅํ๋ค.
let formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
// ํผ ๊ฐ์ฒด key ๊ฐ์ ์ํ.
let keys = formData.keys();
for (const pair of keys) {
console.log(pair);
}
// ํผ ๊ฐ์ฒด values ๊ฐ์ ์ํ.
let values = formData.values();
for (const pair of values) {
console.log(pair);
}
// ํผ ๊ฐ์ฒด key ์ value ๊ฐ์ ์ํ.
let entries = formData.entries();
for (const pair of entries) {
console.log(pair[0]+ ', ' + pair[1]);
}
formData์ ์ด๋ฏธ์ง ๋ด๊ธฐ
์ด๋ฏธ์ง์ ๊ฐ์ ๋ฉํฐ๋ฏธ๋์ด ํ์ผ์ ํผ ๋ฐ์ดํฐ์ ๋ด๊ณ ์ถ๋ค๋ฉด, ์๋ ์ฝ๋์ ๊ฐ์ด formData ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ด๋ฏธ์ง ํ์ผ์ด ๋ด๊ธด input ํ๊ทธ๋ฅผ querySelector ๋ก ๋ฐ์์์ files[0] ๋ฅผ append๋ก ๋ํด์ฃผ๋ฉด ๋๋ค.
์ด๋ฏธ์ง๋ base64, buffer, 2์ง data ํ์์ผ๋ก ์๋ฒ๋ก ์ ์กํด๋ ๋๋ค. (์ฐธ๊ณ ๊ธ)
<body>
<input type="file" id="fileInput">
<button type="submit" id="sendButton">์ ์ก</button>
<script>
const fileInput = document.querySelector("#fileInput");
const sendButton = document.querySelector("#sendButton");
sendButton.addEventListener("click",function(){
var formData = new FormData();
// form Data ๊ฐ์ฒด ์์ฑ
formData.append("attachedImage", fileInput.files[0]);
// ํ์ผ ์ธํ์ ๋ค์ด๊ฐ ํ์ผ๋ค์ files ๋ผ๋ ๋ฆฌ์คํธ๋ก ์ ์ฅ๋๋ค.
// input์ multiple์ ์ ์ธํด ์ฌ๋ฌ๊ฐ์ ํ์ผ์ ์ ํํ ๊ฒฝ์ฐ๊ฐ ์๋๋ผ๋ฉด files[0] ์ผ๋ก input์ ์ถ๊ฐํ ํ์ผ ๊ฐ์ฒด๋ฅผ ์ฐพ์ ์ ์๋ค.
});
</script>
</body>
formData ๊ฐ์ ๊ฐ์ฒด๋ก ๋ฐ๊ธฐ
์ด๋ฒ์๋ ์ข๋ ์ฌํ๋ ์์ฉ ์์ ์ด๋ค. ๋ง์ผ ํผ ๋ฐ์ดํฐ์ ๋ฃ์ key-value ๊ฐ๋ค์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌํ๊ณ ์ถ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด ๋ฆฌํฉํ ๋ง ํ ์ ์๋ค.
// ํผ๋ฐ์ดํฐ์ ๋ฃ์ key-value ๊ฐ๋ค์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌ
const obj = {
first: 'Akash',
middle: 'Rishi',
last: 'Mittal',
}
const formData = new FormData();
Object.entries(obj).forEach(item => formData.append(item[0], item[1]));
// ์ฑ๋ฅ์ ๋ฐ์ง๋ค๋ฉด, ๊ณ ์ฐจ ํจ์ ๋์ for๋ฌธ์ ์ด์ฉํด๋ ๋๋ค.
// for(let key in obj) {
// formData.append(key, obj[key])
// }
// ํผ๋ฐ์ดํฐ ๊ฐ ์ถ๋ ฅ
let entries = formData.entries();
for (const pair of entries) {
console.log(pair[0]+ ', ' + pair[1]);
}
๋ฐ๋๋ก formData ๊ฐ์ฒด์ ํผ ๋ฐ์ดํฐ๋ฅผ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ก ํ์๋ ๊ฐ๋ฅํ๋ค.
const obj2 = {};
formData.forEach((value, key) => obj2[key] = value);
console.log(obj2); // {first: 'Akash', middle: 'Rishi', last: 'Mittal'}
FormData ์๋ฒ ์ ์กํ๊ธฐ
๋ณธ๋ HTML์์ ํผ๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก ๋ณด๋ผ๋๋ ๋ค์๊ณผ ๊ฐ์ด action ๊ณผ method ์์ฑ ๋ถ๋ถ์ ์ ์ ํด์ input submit์ผ๋ก ๋ณด๋์๋ค.
<form action="/action_page.php" method="get">
<input type="text" id="fname" name="fname"><br><br>
<input type="text" id="lname" name="lname"><br><br>
<input type="submit" value="Submit">
</form>
ํ์ง๋ง formData()๋ ์๋ฐ์คํฌ๋ฆฝํธ ํด๋์ค์ด๊ธฐ์, ์๋ฒ์ ์ ์กํ๋ ค๋ฉด fetch api๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
fetch๋ก ํผ๋ฐ์ดํฐ ์ ์กํ๊ธฐ
์ฌ๊ธฐ์ ์ ์ํด์ผ ํ ์ ์, ์๋ฐ์คํฌ๋ฆฝํธ์์ ์๋ฒ๋ก form data๋ฅผ ๋ณด๋ด๋ ค๋ฉด body ์์ฑ ๋ถ๋ถ์ ์ผ๋ฐ์ ์ธ json์ด๋ ๊ฐ์ฒด ํ์ ํํ๊ฐ ์๋ form data ํ์ ํ์์ ๋ง์ถฐ์ ๋ณด๋ด์ผ ํ๋ค๋ ์ ์ด๋ค.
var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');
fetch('https://httpbin.org/post', {
method: 'POST',
cache: 'no-cache',
body: formData // body ๋ถ๋ถ์ ํผ๋ฐ์ดํฐ ๋ณ์๋ฅผ ํ ๋น
})
.then((response) => response.json())
.then((data) => {
console.log(data);
});
formData๋ฅผ ๋ณด๋ผ๋, header ๋ถ๋ถ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋์ผ๋ก ์ค์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ Content-Type์ application/x-www-form-urlencoded ..๋ฑ ๋ฐ๋ก ์ง์ ํ ํ์๊ฐ ์๋ค.
URLSearchParams
๋ง์ผ ์์ฒ๋ผ formData ๊ฐ์ฒด์ ์ผ์ผํ append ํ์ฌ ํผ ๋ฐ์ดํฐ ๊ฐ์ ๊ตฌ์ฑํ๋ ๊ฒ์ด ๋ฒ๊ฑฐ๋กญ๋ค๋ฉด, URLSearchParams() ์ ์ฌ์ฉํ๋ฉด ์ผ๋ฐ ๊ฐ์ฒดํํ๋ฅผ formdataํ์์ผ๋ก ์๋ ๋ณํ ํด์ฃผ์ด ๋ณด๋ค ๊ฐ๋
์ฑ ์ข๊ฒ ์ ์กํ ์ ์๋ค.
fetch('https://httpbin.org/post', {
method: 'POST',
cache: 'no-cache',
body: new URLSearchParams({ // ์ผ๋ฐ ๊ฐ์ฒด๋ฅผ fordataํ์์ผ๋ก ๋ณํํด์ฃผ๋ ํด๋์ค
aaa: 'a1',
bbb: 'b1'
})
})
.then((response) => response.json())
.then((data) => {
console.log(data);
});
# ์ฐธ๊ณ ์๋ฃ
https://ko.javascript.info/formdata
https://developer.mozilla.org/en-US/docs/Web/API/FormData
https://2ham-s.tistory.com/307