본문 바로가기
문제해결

Nginx 413 Request Entity Too Large

by KKambi 2021. 5. 9.

문제상황

- 공지사항 게시판을 구현하면서, 본문에 들어갈 이미지를 업로드할 수 있는 API를 구현하던 상황
- 특정 용량이 넘는 이미지를 업로드하려고 하면 nginx에서 413 Request Entity Too Large 에러가 발생했습니다.
- 클라이언트(브라우저)의 개발자 도구에선 CORS Error로 보여졌습니다.

 

 

원인

저희는 Reverse proxy로 nginx를 사용하고 있었는데, 기본적으로 파일 업로드 크기가 1MB로 제한되어 있더라구요. 그래서 이 설정을 수정해야만 합니다.

Forward proxy?
- 일반적인 프록시를 말하며, 다수 클라이언트의 요청을 받아 미들웨어처럼 목적지에 대신 요청을 보내서 받은 응답을 클라이언트에 전달(forward)해준다.
- 캐싱 기능을 통한 성능 향상, 특정 도메인만 사용 가능하도록 웹 환경 제한, 오리진의 익명성 강화 등
Reverse proxy?
- 클라이언트가 아닌 서버를 위한 프록시
- 클라이언트 측의 요청을 받아 서버에게 전달한 뒤, 다시 클라이언트에게 결과를 응답한다.
- 로드 밸런싱, 보안 강화, 캐싱, SSL 암호화 등

즉, 클라이언트와 서버 간의 통신은 클라이언트 ↔ 포워드 프록시 ↔ 리버스 프록시 ↔ 서버로 이루어진다고 할 수 있습니다.

 

 

해결

파일 업로드 크기 제한을 늘리기 위해 nginx 설정 파일을 수정합시다. 저희는 AWS Elastic Beanstalk를 사용해서 어플리케이션을 배포하기 때문에 프로젝트 루트의 .ebextensions/nginx 디렉토리의 파일들을 수정해야 합니다.

- eb로 배포한 인스턴스의 nginx 설정은 /etc/nginx/nginx.conf 에서 확인할 수 있습니다.
- .ebextensions/nginx/conf.d/*.conf : 해당 위치의 설정 파일들은 nginx 설정의 http 블록에 위치합니다.
- .ebextensions/nginx/conf.d/elasticbeanstalk/*.conf : 해당 위치의 설정 파일들은 nginx 설정의 http.server 블록에 위치합니다.

저는 그래서 04_max_body_size.conf 라는 파일을 만들어 파일 업로드 제한을 5MB로 증가시켰습니다.
아래 파일을 읽어 nginx.conf의 http.server 블록에 해당 설정이 추가됩니다.

// .ebextensions/nginx/conf.d/elasticbeanstalk/04_max_body_size.conf
client_max_body_size 5M;
구글링해보니 이를 http 블록 또는 server 블록에 넣는지 다 제각각이었는데, 어느 곳에 넣어도 의도대로 동작하였습니다. 

 

 

다시, 문제 발생

그런데 5MB 이미지 업로드에 실패했습니다. 저는 MultipartFile을 이용해서 이미지 업로드 API를 구현했는데, 이와 관련해서 예외가 발생했습니다. 업로드 크기 제한을 초과했다는 내용이었습니다.

multipart.MaxUploadSizeExceededException: 
Maximum upload size exceeded; nested exception is java.lang.IllegalStateException:
org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: 
The field sourceFile exceeds its maximum permitted size of 1048576 bytes.
MultipartFile?
- 스프링에서 제공하는 인터페이스
- multipart request로 받은 파일을 표현
- multipart는 http 통신에서 multipart/fomr-data라는 Content-Type으로, http message body 부분에 boundary 기준으로 여러 데이터를 한 번 요청으로 보내는 것

 

 

원인과 해결

nginx처럼 스프링에서 제공하는 mutlipartfile에는 기본 제한이 걸려있었습니다. 이를 다음 설정으로 수정해주면 됩니다. (스프링 부트 2.0 이상에 해당하는 설정이고, 그 이전 버전은 조금씩 다르다고 하니 추가 문서를 참고하세요)

// application.yml
spring:
  servlet:
    multipart:
      max-file-size: 5MB
      max-request-size: 5MB

max-file-size는 요청에 담을 수 있는 한 파일의 최대 크기(multipart에서 boundary로 구분되는 특정 영역), max-request-size는 총 요청 크기(multipart 총 크기)를 의미합니다. 아무것도 설정하지 않았을 때 기본적으로 전자는 1MB, 후자는 10MB라고 합니다. 저는 어차피 1개 요청에 1개의 이미지 파일만을 업로드할 수 있는 구조라 똑같이 5MB로 제한했습니다. 

 

이렇게 크기 제한을 늘리고 원하는 대로 본문 이미지를 업로드할 수 있게 되었습니다. 해결! 🤗

 

 

추가학습

AWS Elastic Beanstalk는 nginx를 default reverse proxy로 사용하여 어플리케이션을 Elastic Load Balancer에 매핑하는데, 이 때 nginx 구성을 어떻게 변경할 수 있는지 "역방향 프록시 구성" 탭에서 확인할 수 있습니다. 이 외에도 플랫폼 확장, 리버스 프록시 교체, 어플리케이션 빌드 및 명령 스크립트 등에 대한 정보를 제공합니다.

 

Elastic Beanstalk Linux 플랫폼 확장 - AWS Elastic Beanstalk

Elastic Beanstalk Linux 플랫폼 확장 AWS Elastic Beanstalk Linux 플랫폼은 애플리케이션 개발 및 실행을 지원하기 위해 다양한 기능을 기본적으로 제공합니다. 필요한 경우 여러 가지 방법으로 플랫폼을 확

docs.aws.amazon.com

 

스프링 부트 버전별 파일 크기 제한 설정, max-file-size와 max-request-size를 설명한 글입니다.

 

Confusion regarding spring.http.multipart.max-file-size vs spring.servlet.multipart.max-file-size

I have spent days wasted getting Spring Boot Upload file to work but, as is always with Spring you have no clue how the magic works and even after years of working with this framework - you have to

stackoverflow.com

댓글