HTTP multipart

이번에는 사내 서버 교육 중에 언급했던 multipart에 대해 알아보려고 한다. 

 

mutipart를 알아보기 전에,

우선 실제로 multipart/form-data를 사용하는 HTML에서 <form> 태그의 enctype 속성에 대해 살펴보고자 한다. 


enctype(인코딩 타입)

HTML form을 post 방식으로 전송할 때는 전송하는 데이터를 인코딩하기 위해 인코딩 타입에 대한 명시가 필요한데 해당 속성이 enctype이다.  

enctype(인코딩 타입) 속성은 form에서 데이터를 전송할 때(post) 전송되는 리소스(파일, 텍스트 등)를 인코딩하기 위한 속성으로, 인코딩 된 리소스는 MIME Type으로 해당 리소스가 어떤 타입(이미지, 파일 등) 식별할 수 있게 해준다. 

(MIME - 인터넷에서 전송되는 파일, 컨텐츠가 어떤 형식인지 구별할 수 있는 식별자로 현재는 미디어 타입(Media Type)이라 불린다. 윈도우즈에서 파일 확장자와 비슷한 역할을 한다.)

 

간단히 말해 form 태그의 enctype는 form data가 서버로 보내질 때 해당 데이터가 인코딩되는 방법을 알려주는 속성이다. 

"enctype"에는 3가지가 있다. 

 

1) application/x-www-form-urlencoded 

- 기본값으로, 모든 문자들은 서버로 보내기 전에 인코딩됨을 명시한다.

- mutlipart/form-data를 제외한 모든 경우에 사용한다. 

 

2) mutipart/form-data 

- 모든 문자를 인코딩하지 않음을 명시한다.

- <form> 요소가 파일이나 이미지(<input type="file">)를 서버로 전송할 때 주로 사용한다. 

 

3) text/plain 

- 공백 문자(space)는 "+" 기호로 변환하지만, 나머지 문자는 모두 인코딩되지 않음을 명시한다.

- 즉, 인코딩 없이 전송

- 보완성이 없어 디버깅 요도로만 사용해야 한다. (개발 외에는 사용하지 않는게 매우 좋다.)

 

 

"multipart/form-data"는 파일 업로드가 없는 폼에서도 사용가능하지만,

파일 전송을 위해 추가적으로 표시되는 요소들(파일 데이터 구분자)이 있어서

기본값인 "application/x-www-form-urlencoded" 보다 기본 데이터가 커지므로 짧은 데이터 전송에는 비효율적이다.

 

따라서 파일 전송이 없는 경우에는 기본값인  "application/x-www-form-urlencoded"를 사용하는 것이 가장 효율적이다. 

 

하지만 파일 전송을 해야하는데

"application/x-www-form-urlencoded"로 enctype(인코딩 타입)을 잘못 표시한다면

전송한 데이터를 처리하는 페이지에서는 파일 정보에 접근할 수 없게 된다.

그렇기에 폼에 파일 전송이 있다면, "multipart/form-data"로 인코딩 타입을 표시해야 바이너리 정보로 제대로 처리 페이지로 전송된다. 

 


 

multipart의 등장과 multipart/form-data의 의미

그러면 이제 multipart를 통해 어떻게 파일 업로드를 하는지 알아보자.

 

<input type="file" />

우선 위 태그는 파일 업로드를 위한 input 태그이다. 

 

앞서 말했듯이

<form> 안에 사용하면 서버로 파일을 전송할 수 있는데, 이 때 다른 form-data들도 같이 전송이 된다. 

서버로 전송되는 데이터들은 HTTP Request 형태로 서버로 전송되는데, 파일 업로드가 가능한 이유는 HTTP Request에 특별한 비밀이 있기 때문이다. 

 

HTTP Request는 Body에 클라이언트가 전송하려는 데이터를 넣을 수 있다. 또한 Body에 들어가는 데이터 타입을 HTTP Header의 Content-type에 명시해줌으로써 서버가 각 타입에 맞게 처리할 수 있게 해준다. 

 

근데 보통 HTTP Request의 Body는 한 종류의 타입이여서 Content-type도 타입을 하나만 명시할 수 있게 되어있다. 

(예시. text는 text/plain, png는 image/png 등등)

그리고 위에서 언급했던 enctype의 3가지 중 기본값인 "application/x-www-form-urlencoded"가 Content-type으로 들어간다. 

 

<form>
 <input type="file" />
 <input type="text" />
   ...
</form>

여기서 문제는 위 코드처럼 파일을 업로드하면서

다른 form data들도 같이 보낼 때 두 input의 Content-type이 다르다는 것이다.

(예를 들어서 텍스트는 "application/x-www-form-urlencoded"이고, 사진 파일이라면 "image/jpeg"이다.)

 

근데 HTTP Header에는 Content-type에 위에서 언급했듯이 한 가지만 명시할 수 있기에

서로 다른 종류의 데이터가 하나의 HTTP Request Body에 들어가야 하는데,

이런 경우 데이터를 구분해서 넣어주는 방법이 필요했고,

 

그렇게 만들어진 것이 "multipart" 타입이다!!

 

HTTP Request에서 multipart의 Body를 전송하는 규약을 통해 파일 업로드를 구현하는 것이다. 

추가적으로 form에서 파일과 다른 데이터가 함께 전송하는 경우는 바로 "multipart/form-data" 이다.


HTTP multipart/form-data의 raw 데이터 모양

출처 -&nbsp;https://lng1982.tistory.com/209

 

multipart/form-data로 데이터 보낼 때는 Request header와 body의 모습이다.

서버에서 정상적으로 데이터 처리가 가능하도록 Content-Type은 multipart/form-data로 지정되어 있고,

boundary에 지정되어있는 문자열이 파일 데이터의 구분자로 사용되고 있다. (빨간 박스)

 

boundary의 문자열 마지막에 --가 붙은 것은 body의 끝을 의미한다. 

 

이러한 HTTP 통신 규격에 맞게 HTTP header와 body 데이터를 생성한 후,

HTTP server에 요청(Request)하면 서버에서도 HTTP 통신 규격에 맞게 데이터를 파싱 후 처리하게 되는 것이다. 

 

 

추가적으로 좀 더 살펴보면,

출처 - https://lng1982.tistory.com/209

헤더와 헤더를 구분하는 것이 개행문자이고

헤더와 바디를 구분하는 것은 개행문자를 2개

body에 포함되어 있는 파일데이터를 구분하는 것은 boundary이다. 

 

 

결국 파일을 보낸다고 한번에 파일이 전송되는 것이 아니라

파일을 이루고 있는 여러 문자들이 HTTP Request body에 담겨져 여러 개로 쪼개져서 서버로 전송된다. 


참고)

 

MDN- 폼

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#attributes_for_form_submission

위키피디아 -MIME

https://en.wikipedia.org/wiki/Media_type

HTML 파일 업로드의 원리

https://blog.naver.com/jjoommnn/130032927466

HTTP multipart/form-data raw 데이터 형태는?

https://lng1982.tistory.com/209

'인턴' 카테고리의 다른 글

CSS Rendering  (0) 2023.01.30