← 뒤로가기

사진 업로드에서 413 request entity too large를 처리한 기록

관리실 사진 업로드 중 413 오류가 발생한 원인과, 브라우저 선처리 방식으로 우선 해결한 과정을 정리했다.

관리실에서 큰 사진을 올리면 413 request entity too large가 발생했다.

이 오류는 보통 애플리케이션 코드보다 앞단에 있는 웹서버가 요청 본문 크기를 제한할 때 나온다.
이번 구조에서는 muabow.com -> nginx -> admin Flask app 순서로 요청이 흐르기 때문에, 먼저 nginx 제한을 의심하는 게 맞았다.

현재 구조

브라우저
  -> /admin/upload
  -> nginx
  -> 내부 Flask admin app

관리 앱 자체에도 업로드 제한이 있었지만, 실제로는 그 앞단 nginx에서 먼저 요청이 막힐 수 있는 구조였다.

바로 바꾼 것

이번에는 운영 중단 없이 먼저 효과를 볼 수 있는 쪽으로 정리했다.

  1. Flask 업로드 제한을 32MB -> 64MB로 올렸다.
  2. 업로드가 너무 큰 경우 관리실 안에서 안내 문구를 보여주게 했다.
  3. 가장 중요한 부분으로, 브라우저가 사진을 업로드하기 전에 자동으로 줄이고 JPEG로 압축해서 보내도록 바꿨다.

즉 지금은 원본 대용량 사진을 그대로 서버에 밀어넣는 대신, 브라우저가 먼저 업로드용 크기로 정리한 뒤 전송한다.

왜 브라우저 선처리로 갔는가

루트 권한이 없는 상태에서는 /etc/nginx 설정을 바로 바꾸기 어렵다.
반면 브라우저 선처리는 애플리케이션 배포만으로 바로 적용할 수 있다.

이 방식의 장점은 단순하다.

  • 휴대폰 원본 사진 같은 큰 파일도 바로 올라갈 가능성이 높아진다.
  • 서버 저장 공간도 덜 사용한다.
  • 사용자는 413만 보는 대신 자동 처리된 업로드 흐름을 그대로 쓸 수 있다.

실제 동작

업로드 폼에서 사진을 고르면 다음 순서로 처리한다.

  1. 브라우저가 이미지를 읽는다.
  2. 가장 긴 변을 기준으로 적당한 크기까지 줄인다.
  3. JPEG로 다시 만든다.
  4. 줄어든 파일을 업로드한다.

GIF는 프레임 손실이 생길 수 있으므로 그대로 통과시켰다.

남아 있는 근본 해결

운영 권한이 정리되면 nginx에도 본문 크기 제한을 명시해두는 편이 낫다.

client_max_body_size 64m;

이 한 줄은 server 블록이나 /admin 프록시 위치에 둘 수 있다.

즉 현재 상태는:

  • 실사용은 브라우저 선처리로 먼저 해결
  • 서버 설정은 나중에 루트 권한으로 정리

이 두 단계로 이해하면 된다.

이번 변경 파일

관리 앱의 서버 코드와 업로드 템플릿

지금 기준으로는 이 정도면 충분히 운영 가능한 상태다.
이후에는 업로드 후 자동 회전 보정, HEIC 대응, WebP 저장 같은 쪽으로 더 다듬을 수 있다.

이어서 보기