관리실에서 큰 사진을 올리면 413 request entity too large가 발생했다.
이 오류는 보통 애플리케이션 코드보다 앞단에 있는 웹서버가 요청 본문 크기를 제한할 때 나온다.
이번 구조에서는 muabow.com -> nginx -> admin Flask app 순서로 요청이 흐르기 때문에, 먼저 nginx 제한을 의심하는 게 맞았다.
현재 구조
브라우저
-> /admin/upload
-> nginx
-> 내부 Flask admin app
관리 앱 자체에도 업로드 제한이 있었지만, 실제로는 그 앞단 nginx에서 먼저 요청이 막힐 수 있는 구조였다.
바로 바꾼 것
이번에는 운영 중단 없이 먼저 효과를 볼 수 있는 쪽으로 정리했다.
- Flask 업로드 제한을
32MB -> 64MB로 올렸다. - 업로드가 너무 큰 경우 관리실 안에서 안내 문구를 보여주게 했다.
- 가장 중요한 부분으로, 브라우저가 사진을 업로드하기 전에 자동으로 줄이고 JPEG로 압축해서 보내도록 바꿨다.
즉 지금은 원본 대용량 사진을 그대로 서버에 밀어넣는 대신, 브라우저가 먼저 업로드용 크기로 정리한 뒤 전송한다.
왜 브라우저 선처리로 갔는가
루트 권한이 없는 상태에서는 /etc/nginx 설정을 바로 바꾸기 어렵다.
반면 브라우저 선처리는 애플리케이션 배포만으로 바로 적용할 수 있다.
이 방식의 장점은 단순하다.
- 휴대폰 원본 사진 같은 큰 파일도 바로 올라갈 가능성이 높아진다.
- 서버 저장 공간도 덜 사용한다.
- 사용자는
413만 보는 대신 자동 처리된 업로드 흐름을 그대로 쓸 수 있다.
실제 동작
업로드 폼에서 사진을 고르면 다음 순서로 처리한다.
- 브라우저가 이미지를 읽는다.
- 가장 긴 변을 기준으로 적당한 크기까지 줄인다.
- JPEG로 다시 만든다.
- 줄어든 파일을 업로드한다.
GIF는 프레임 손실이 생길 수 있으므로 그대로 통과시켰다.
남아 있는 근본 해결
운영 권한이 정리되면 nginx에도 본문 크기 제한을 명시해두는 편이 낫다.
client_max_body_size 64m;
이 한 줄은 server 블록이나 /admin 프록시 위치에 둘 수 있다.
즉 현재 상태는:
- 실사용은 브라우저 선처리로 먼저 해결
- 서버 설정은 나중에 루트 권한으로 정리
이 두 단계로 이해하면 된다.
이번 변경 파일
관리 앱의 서버 코드와 업로드 템플릿
지금 기준으로는 이 정도면 충분히 운영 가능한 상태다.
이후에는 업로드 후 자동 회전 보정, HEIC 대응, WebP 저장 같은 쪽으로 더 다듬을 수 있다.