Multipart 정리

Jake Seo·2021년 6월 24일
5

자바 잡지식

목록 보기
4/17

Multipart를 잘 이해하기 위해서는 HTTP 통신에 대한 선행 지식이 있어야 합니다.

Multipart의 기본 정의

  • HTTP 요청의 한 종류로 HTTP 서버로 파일 혹은 데이터를 보내기 위한 요청 방식이다.
  • 주로 HTML Input 엘리먼트에서 enctype으로 이용된다.
    • 기본 enctypeapplication/x-www-form-urlencoded이다.
    • text-plain도 있긴 한데 잘 쓰이진 않는다.
  • 큰 용량의 바이너리 데이터를 전송하는데 적합하다.
    • application/x-www-form-urlencoded enctype은 큰 용량의 데이터를 전송하기엔 적합하지 않다.

Multipart HTTP 요청 파헤치기

POST /cgi-bin/qtest HTTP/1.1
Host: aram
User-Agent: Mozilla/5.0 Gecko/2009042316 Firefox/3.0.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://aram/~martind/banner.htm
Content-Type: multipart/form-data; boundary=2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Length: 514

--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile1"; filename="r.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile2"; filename="g.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile3"; filename="b.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f--

위는 Multipart HTTP 요청의 예시이다. 일반적인 HTTP 요청과 비슷한 형태를 띄지만, 약간 다른 점이 있다.

  • 보통 Multipart 요청을 보낼 때 HTTP 메소드는 POST를 사용한다.
  • Content-Typemultipart/form-data이다.
  • boundary라는 것이 존재하여 각 엔티티를 나눈다.
  • 내용의 끝에는 항상 \r\n을 개행(CRLF)으로 사용해준다.
  • boundary로 나누어진 각 부분을 content-transfer-encoding 헤더에 정의된대로 인코딩할 수도 있다.

Boundary란 뭘까?

  • 파일을 첨부할 때, 브라우저가 생성한 값이다.
  • 일반적으로 여러 개의 엔티티가 전송되었을 때 각각의 key/value 쌍을 구분하기 위해서 boundary를 이용한다.
  • 위의 HTTP 예제에서는 3개의 GIF 파일이 보내졌는데, 그들을 각각 구분하는 용도로 boundary가 사용되었다.
  • boundary는 1~70자의 문자들로 --로 시작하여 --로 끝난다.
  • 서버에서는 boundary로 나누어 각 데이터들을 읽는다.

boundary로 나뉘어 여러 엔티티가 전송되기 때문에 Multipart 라는 이름을 쓰는 것 같다. (추측)

자주 등장하는 이슈 - WAS에서 FileSize의 제한 생각하기

보안이나 운영상 이슈 때문에 보통은 기본 파일 첨부 사이즈가 제한되어 있다. 이것 때문에 헷갈려 하는 분들이 많다.

톰캣에서 파일 사이즈 제한 풀기

일반적으로 사용하는 WAS인 톰캣의 경우, 자동으로 FileSize에 제한이 걸려있는데, 아래와 같은 설정을 통해 풀어줄 수 있다.

209715200은 200MB정도의 크기이다.

  <servlet>
    ...
    <multipart-config>
      <file-size-threshold>0</file-size-threshold>
      <max-file-size>209715200</max-file-size>
      <max-request-size>209715200</max-request-size>
    </multipart-config>
    ...
  </servlet>
<Connector port="8080" protocol="HTTP/1.1"
  connectionTimeout="20000"
  redirectPort="8443"
  maxSwallowSize = "-1"/>

일반 스프링 MVC에서 파일 사이즈 제한 풀기

@Bean
public CommonsMultipartResolver multipartResolver() {
     CommonsMultipartResolver resolver=new CommonsMultipartResolver();
     resolver.setMaxUploadSize(15728640);
     resolver.setMaxUploadSizePerFile(15728640);
     return resolver;
}

스프링부트에서 파일 사이즈 제한 풀기

# 첨부파일 관련 설정
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

애노테이션으로 파일 사이즈 제한 풀기

@WebServlet("/uploadFiles")
@MultipartConfig( fileSizeThreshold = 0, maxFileSize = 209715200, maxRequestSize = 209715200)
public class FileUploadServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        // ...
    }
}

WAS에서 POST의 길이제한 생각하기

우리가 일반적으로 사용하는 WAS인 톰캣의 경우 Post의 길이 제한은 2MB로 설정되어 있다.

톰캣의 web.xml에 접근하면 아래와 같이 maxPostSize를 설정하는 항목이 있고, 이를 "0"으로 바꾸면 무제한의 용량을 서버가 받을 수 있게 된다. (톰캣 버전 7.0.63 미만에서는 0이 무제한을 의미하며, 그 이상 버전에서는 -1이 무제한을 의미한다고 한다.) 기본 값은 2097152 (2 megabytes)이다.

<!-- Define a Coyote/JK2 AJP 1.3 Connector on port 8009 -->
<Connector port="8009" 
           enableLookups="false" redirectPort="8443" debug="0"
           protocol="AJP/1.3" maxPostSize="0"/>
<!-- 0는 무제한을 의미한다. -->

이렇게 설정된 데는 다 이유가 있다. 만일 이렇게 용량 제한을 걸지 않으면, 서버를 폭파시킬 목적으로 해커가 어마어마하게 큰 요청을 계속 보내도 서버는 꾸역꾸역 처리하게 되고, 이 과정에서 과부하가 일어나서 서버가 폭발할 수 있다. 그러므로 이 제한을 해제할 때는 반드시 이러한 보안 이슈가 일어날 수 있다는 점을 감안하자. 또한, 한번에 무제한으로 늘리지 말고 필요한 만큼 조금씩 늘려가자.

레퍼런스

멀티파트 요청이란?
멀티파트의 형태
멀티파트에서 boundary란
스프링에서 멀티파트를 처리하는 방법
Mozilla Content-Type
RFC1341
forms
Multipart 구성방법
멀티파트를 이용한 업로드

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글