FormData로 이미지 파일 전송

SooSoo·2021년 9월 22일
4

공부정리

목록 보기
3/7
post-custom-banner

계기

웹에서 서버로 이미지 파일을 전송하는데 제대로 동작하지 않는 에러를 만났다.

이전에 FormData에 대한 내용을 접한적이 있어 Content-Type 설정에 대한 문제일 것으로 예상하고 HTTP 헤더를 수정했더니 그제서야 동작이 되었다.

해결을 위해 Content-Type 헤더를 multipart/form-data로 수정해주기는 하였으나 그래야만 하는 이유를 몰랐다.

그래서 이번을 계기로 FormData, MIME, Content-Type에 대해 간단히 조사해보았다.
MDN을 메인 레퍼런스로 사용했다.

Contenty-Type

가장 먼저 Content-Type에 대해 찾아보았다.
MDN의 정의에 따르면 Content-Type은 다음과 같다.

Content-Type 개체 헤더는 리소스의 media type을 나타내기 위해 사용됩니다.

어떤 유형의 미디어타입이 전송되고 있는지 알려주는 것이 주요목적이다.

세부적으로는 media-type / charset / boundary로 나눌 수 있다.
다음처럼 표현할 수 있다.

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something

media-type이 해당 데이터의 MIME type을 나타낸다. MIME type에 대해서는 곧 알아본다.

charset은 문자 인코딩 표준을 나타낸다.

boundary는 멀티파트 객체가 있을 경우 메시지 간의 경계선을 나타내기 위해 사용된다.

MDN의 예제는 다음과 같다.

POST /foo HTTP/1.1
Content-Length: 68137
Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
Content-Disposition: form-data; name="description"
---------------------------974767299852498929531610575
some text
---------------------------974767299852498929531610575
Content-Disposition: form-data; name="myFile"; filename="foo.txt"
Content-Type: text/plain
(content of the uploaded file foo.txt)
---------------------------974767299852498929531610575--

전달되는 여러 타입의 메시지들이 Boundary를 기준으로 분리되어 있는 것을 볼 수 있다!

MIME 타입

MIME 타입도 MDN의 정의부터 찾아봤다.

MIME 타입이란 클라이언트에게 전송된 문서의 다양성을 알려주기 위한 메커니즘입니다

명확하지 않아 위키피디아의 정의도 함께 가져왔다.

미디어 타입(media type), MIME 타입(MIME type), 콘텐츠 타입(content type)은 인터넷에 전달되는 파일 포맷과 포맷 콘텐츠를 위한 2 부분의 식별자이다

리소스가 어떤 포맷인지 식별할 수 있게하고 이를 통해 브라우저가 어떤 기본동작을 할지 알 수 있게 하는 기능이라고 볼 수 있겠다.

주로

type/subtype

형태로 사용한다.

사용될 수 있는 타입으로는

text, image, audoio, video, application(이진 데이터를 나타내는 형식)

이 있고,

text/plain
text/html
image/jpeg
image/png
audio/mpeg
audio/ogg
audio/*
video/mp4
application/octet-stream

이런 형태로 사용한다.

여기서 multipart/form-data의 필요성이 생긴다.

보내려는 메시지의 형식이 하나로 규정되지 않고 복합적이라면 어떻게 해야할까?

이미지와 이미지에 대한 설명을 보낸다면,
text와 image 중 한 형식을 선택하긴 어려울 것이다.

멀티파트 타입은 일반적으로 다른 MIME 타입들을 지닌 개별적인 파트들로 나누어지는 문서의 카테고리를 가리킵니다. 즉 이 타입은 합성된 문서를 나타내는 방법입니다.

multipart/form-data는 그 중에서도 HTML Form의 내용을 전송시에 이용할 수 있다.
각 파트가 구분되어 있고, 각자 자신의 HTTP 헤더를 가진다. 이 헤더의 Content-type이 달라서 여러 종류의 type을 보낼 수 있다.

Content-Type: multipart/form-data; boundary=aBoundaryString
(other headers associated with the multipart document as a whole)
--aBoundaryString
Content-Disposition: form-data; name="myFile"; filename="img.jpg"
Content-Type: image/jpeg
(data)
--aBoundaryString
Content-Disposition: form-data; name="myField"
(data)
--aBoundaryString
(more subparts)
--aBoundaryString--

FormData

Form 내에서 이미지와 텍스트 등을 함께 전송하려면 Content-type을 multipart/form-data로 설정해주는 것까지는 확실해졌다.

마지막으로 FormData를 사용하는 간단한 방법을 알아본다.

   const test = new FormData()

   test.append('name',englishName)
   test.append('image',images[0])

FormData 생정자를 통해 새로운 FormData 객체를 만들어준다.

생성된 객체에 키/밸류의 형태로 원하는 필드들을 담아준다.
append 외에 set을 활용할 수도 있고 이외에 다양한 메서드들을 사용할 수 있다.
append의 경우는 객체에 키가 존재하면 기존 키에 새로운 값을 추가하고, 없으면 새로 등록해준다.
set은 객체에 키가 있든없든 새로운 값을 설정해준다는 차이가 있다.

이외의 메서드는 MDN Form Data에서 확인할 수 있다.

API 호출은 axios를 활용하여 다음과 같이 해주었다.

await client.post('/api/form-test/', param, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }

레퍼런스)

MDN - Form Data

MDN - Content Type

MDN - MIME Type

위키백과 - 미디어 타입

profile
꾸준히
post-custom-banner

0개의 댓글