안녕하세요. 이번 시간에는 AJAX로 폼 전송을 가능케해주는 FormData 객체에 대해 알아보겠습니다.
보통은 AJAX로 폼(form 태그) 전송을 할 일이 거의 없습니다. 주로 JSON 구조로 키-값 데이터를 전송하니까요. 하지만 폼 전송이 필요한 경우가 있습니다. 바로 이미지를 AJAX로 업로드할 경우입니다. 물론 이미지는 base64나, buffer, 이진 데이터 형식으로 서버로 전송해도 됩니다. 하지만 가장 자연스러운 것은 폼을 통해서 업로드하는 것이죠. input[type=file]을 사용해서요.
그런데 폼과 AJAX를 같이 쓴다는 것은 좀 이상하죠? 보통 폼 하면 제출 버튼을 누르면 action 속성에 지정한 페이지로 이동하면서 데이터를 전송하니까요. AJAX는 반대로 제출 버튼을 누르면 기본 폼 동작은 e.preventDefault()
로 멈추고, 페이지 전환 없이 데이터를 전송합니다.
페이지 전환 없이 폼 데이터를 제출하고 싶을 때 바로 FormData 객체를 사용합니다. AJAX 전송법은 다음 시간에 알아보고, 이번 시간에는 이 객체에 대해서 자세히 살펴보겠습니다.
FormData 객체는 window.FormData
에 위치합니다.
var formData = new FormData();
formData.append('name', 'zerocho');
formData.append('item', 'orange');
formData.append('item', 'melon');
자, new FormData()
로 새로운 객체를 생성해주시고요. append 메소드로 키-값 형식으로 하나씩 추가해주시면 되겠습니다. 같은 키를 가진 값을 여러 개 넣을 수도 있습니다. 덮어씌워지지 않고 추가됩니다. 참고로 값은 문자열로 자동 변환됩니다. 숫자를 넣어도 문자열이 되고, 배열을 넣어도 콤마로 구분한 문자열이 됩니다. 객체는 넣으면 무시됩니다. 이 점을 유의하세요!
기존 폼이 있는 경우는
var formData = new FormData(document.getElementById('폼 아이디'));
이렇게 선택하면 알아서 폼의 내용들의 formData 객체 안에 들어갑니다. 편리하죠?
append로 넣을 수만 있는 게 아니라 내용물을 확인할 수도 있습니다. 위의 코드와 이어집니다.
formData.has('item'); // true
formData.has('money'); // false
formData.get('item'); // orange
formData.getAll('item'); // ['orange', 'melon']
has 메소드로는 해당하는 키가 존재하는 지 확인할 수 있고요. get 메소드로 직접 가져올 수 있습니다. 유의할 점은 get은 처음 저장한 값 하나만 불러옵니다. 위에서 item 키에 값을 orange와 melon 두 개를 줬습니다. 그런데 get만 하면 orange밖에 뜨지 않습니다. 이 때 getAll 메소드가 있습니다. 해당 키에 매칭되는 값들을 전부 배열로 반환합니다.
var keys = formData.keys();
keys.next(); // { done: false, value: 'name' }
keys.next(); // { done: false, value: 'item' }
keys.next(); // { done: false, value: 'item' }
keys.next(); // { done: true, value: undefined }
var values = formData.values();
values.next(); // { done: false, value: 'zerocho' }
values.next(); // { done: false, value: 'orange' }
values.next(); // { done: false, value: 'melon' }
values.next(); // { done: true, value: undefined }
var entries = formData.entries();
entries.next(); // { done: false, value: ['name', 'zerocho'] }
entries.next(); // { done: false, value: ['item', 'orange'] }
entries.next(); // { done: false, value: ['item', 'melon'] }
entries.next(); // { done: true, value: undefined }
위의 코드는 반복자(이터레이터)를 사용한 코드입니다. 이터레이터 강좌는 여기를 참조하세요. 이터레이터는 상황에 따라 매우 유용할 수 있습니다. 물론 IE에서 안 되는 단점이 있지만요. FormData의 키나 값, 또는 키와 값 모두를 쉽게 보여줍니다. 반복문에 사용하면 좋습니다.
formData.append('test', ['hi', 'zero']);
formData.get('test'); // hi, zero
formData.delete('test');
formData.get('test'); // null
formData.set('item', 'apple');
formData.getAll('item'); // ['apple']
formData에 이제 값을 지워봅시다. delete 메소드를 사용하면 됩니다. append와 비슷한 set 메소드도 있습니다. set과 append의 차이점은 set도 추가를 해주기는 하지만, 기존 키가 있으면 그 값을 모두 덮어씌워버립니다. 위의 item에 대한 값이 orange와 melon이었는데 apple을 set하는 순간 item 값이 apple 하나로 덮어씌워졌습니다.
이상으로 FormData의 API에 대해 알아봤습니다. FormData에 이미지를 담고 싶으면
formData.append('img', document.getElementById('파일 인풋').files[0])
위와 같이 넣어주고 서버로 formData를 보내버리면 됩니다. 파일이 여러 개면 반복문으로 append를 하면 되고요. 주의할 점은 여러 개를 append할 때 항상 키값(위에서는 img)은 같아야 여러 파일이 같은 키로 업로드 됩니다.
네, 이제 폼데이터는 마스터 하셨고요. 이 값을 서버로 보내기만 하면 됩니다. AJAX로 보내려면 XMLHttpRequest에 대해서 알아야겠죠? 다음 시간에는 XMLHttpRequest에 대해 알아봅시다!