- 출처 / 참고: Nginx Official Documentation (ngx_http_core_module - client_max_body_size), Apache HTTP Server Documentation (core - LimitRequestBody), RFC 7231 (HTTP/1.1 Semantics and Content)
명령어:
curl,nginx -T,apachectl,httpd,grep,tail
키워드: HTTP 413, Request Entity Too Large, Payload Too Large, client_max_body_size, LimitRequestBody, upload_max_filesize, post_max_size
사용처: 웹 애플리케이션 대용량 파일 첨부 및 REST API 요청 시 본문 크기 제한으로 인한 업로드 차단 해제
실행예제
웹 애플리케이션으로 대용량 파일 업로드 또는 큰 JSON 페이로드 전송 시 웹 서버(Nginx / Apache)가 413 Request Entity Too Large(또는 HTTP/2 이상에서 413 Payload Too Large)를 즉시 반환하는 상태를 진단하고 에러 로그 및 현재 설정값을 점검합니다.
# 1. 클라이언트 관점: 특정 크기(예: 10MB)의 더미 파일을 생성하여 파일 업로드 요청 테스트
$ dd if=/dev/zero of=test_10mb.bin bs=1M count=10
$ curl -v -F "file=@test_10mb.bin" https://example.com/upload
* Connected to example.com (192.168.1.100) port 443
> POST /upload HTTP/1.1
> Content-Length: 10486016
< HTTP/1.1 413 Request Entity Too Large
< Server: nginx
# -> 파일 전송 직후 웹 서버 레벨에서 413 에러를 즉각 반환하는지 확인
# 2. Nginx 에러 로그에서 413 관련 메시지 확인
$ sudo tail -n 20 /var/log/nginx/error.log
# [출력 예시]
# [error] 18452#18452: *412 client intended to send too large body: 10485760 bytes, client: 203.0.113.10, server: example.com, request: "POST /upload HTTP/1.1", host: "example.com"
# 3. Apache 에러 로그에서 413/LimitRequestBody 관련 메시지 확인
$ sudo tail -n 20 /var/log/apache2/error.log # 또는 /var/log/httpd/error_log
# [출력 예시]
# [core:error] [pid 1234:tid 1402] Request body exceeds LimitRequestBody limit (10485760 bytes)
# 4. 현재 Nginx 전체 설정에서 client_max_body_size 지시어 확인 (기본값은 1m)
$ sudo nginx -T 2>/dev/null | grep -E "client_max_body_size"
# 아무것도 출력되지 않는다면 Nginx 기본값인 1MB로 엄격하게 제한 중인 상태임
# 5. 현재 Apache 설정에서 LimitRequestBody 지시어 검색
$ sudo grep -rnE "LimitRequestBody" /etc/apache2/ /etc/httpd/ 2>/dev/null
스크립트
현재 시스템에 설치된 웹 서버(Nginx / Apache)와 백엔드(PHP-FPM)의 설정 파일을 탐색하여 본문/업로드 크기 제한 지시어의 현재 설정값을 추출 및 비교하고 누락 여부를 진단하는 쉘 스크립트입니다.
#!/bin/bash
# check_upload_limits.sh - Diagnose HTTP 413 Request Entity Too Large limits across Web & WAS
echo "=========================================="
echo " [HTTP 413 본문 업로드 제한 진단]"
echo "=========================================="
# 1. Nginx 본문 크기 제한 점검
echo -e "\n[1] Nginx 'client_max_body_size' 설정 점검:"
if command -v nginx &>/dev/null; then
NGINX_BODY_LIMITS=$(nginx -T 2>/dev/null | grep -rnE "client_max_body_size" | grep -v "#")
if [ -n "$NGINX_BODY_LIMITS" ]; then
echo " [설정됨] 명시적인 client_max_body_size 설정 내역:"
echo "$NGINX_BODY_LIMITS" | sed 's/^/ /'
else
echo " [주의] client_max_body_size 지시어가 설정되어 있지 않습니다."
echo " -> Nginx 기본값인 1MB(1m)가 적용되어 1MB 초과 업로드 시 413 발생"
fi
else
echo " - Nginx가 설치되어 있지 않습니다."
fi
# 2. Apache 본문 크기 제한 점검
echo -e "\n[2] Apache 'LimitRequestBody' 설정 점검:"
APACHE_CONF_DIR=""
[ -d "/etc/apache2" ] && APACHE_CONF_DIR="/etc/apache2"
[ -d "/etc/httpd" ] && APACHE_CONF_DIR="/etc/httpd"
if [ -n "$APACHE_CONF_DIR" ]; then
APACHE_LIMITS=$(grep -rnE "LimitRequestBody" "$APACHE_CONF_DIR" 2>/dev/null | grep -v "#")
if [ -n "$APACHE_LIMITS" ]; then
echo " [설정됨] Apache LimitRequestBody 설정 내역 (단위: Bytes):"
echo "$APACHE_LIMITS" | sed 's/^/ /'
else
echo " [기본값 사용 중] LimitRequestBody 기본값 0(무제한) 또는 1GB(배포판별 상이) 적용 중"
fi
else
echo " - Apache 설정 디렉터리를 찾을 수 없습니다."
fi
# 3. PHP 환경 점검 (설치된 경우 백엔드 업로드 제한 확인)
echo -e "\n[3] 백엔드(PHP) 업로드 관련 제한 점검:"
if command -v php &>/dev/null; then
UPLOAD_MAX=$(php -r 'echo ini_get("upload_max_filesize");')
POST_MAX=$(php -r 'echo ini_get("post_max_size");')
MEM_LIMIT=$(php -r 'echo ini_get("memory_limit");')
echo " - upload_max_filesize : ${UPLOAD_MAX} (단일 파일 최대 용량)"
echo " - post_max_size : ${POST_MAX} (전체 POST 본문 최대 용량)"
echo " - memory_limit : ${MEM_LIMIT} (스크립트 실행 메모리)"
echo " -> Nginx 제한을 늘려도 위 PHP 설정값이 작으면 파일 저장 시 백엔드 오류 발생"
else
echo " - PHP CLI가 감지되지 않아 백엔드 검사를 건너뜁니다."
fi
echo -e "\n=========================================="
echo " [진단 완료]"
echo "=========================================="
해설
HTTP 413 Request Entity Too Large 오류는 클라이언트가 웹 서버로 보낸 HTTP 요청의 Content-Length 또는 실제 바이트 스트림 크기가 웹 서버 설정 파일에 허용된 최대 본문 크기를 초과했을 때 발생합니다.
1. 주요 발생 원인
- Nginx의
client_max_body_size기본값(1MB):- Nginx의 기본 허용 본문 용량은 단
1m입니다. 이미지, PDF, 엑셀 등 조금이라도 큰 파일을 업로드하면 Nginx가 요청 본문을 읽는 즉시 통신을 중단하고 413 응답을 반환합니다.
- Nginx의 기본 허용 본문 용량은 단
- Apache의
LimitRequestBody바이트 제한:- 기본값은 0(무제한) 또는 배포판 기본 설정(보통 1GB)이나, 보안 강화 목적으로 512KB나 1MB 등 작은 바이트 단위로 지정되어 있는 경우 초과 패킷이 차단됩니다.
- 리버스 프록시와 백엔드 WAS 간 설정 불일치:
- 스프링 부트(
spring.servlet.multipart.max-file-size)나 PHP-FPM(upload_max_filesize)은 50MB로 설정해 두었으나, 앞단 Nginx가 1MB로 유지되어 애플리케이션 계층까지 도달하지 못하고 앞단에서 413 에러를 뱉는 경우입니다.
- 스프링 부트(
2. 단계별 해결 방법
1) Nginx 설정 수정 (client_max_body_size)
Nginx에서는 http, server, 또는 특정 업로드 location 블록에 허용할 최대 용량을 선언합니다.
# /etc/nginx/nginx.conf 또는 /etc/nginx/conf.d/*.conf
http {
# 모든 가상 호스트 공통 적용 (예: 50MB)
client_max_body_size 50M;
server {
server_name example.com;
# 특정 업로드 엔드포인트만 대용량(예: 500MB) 허용 시
location /api/upload {
client_max_body_size 500M;
proxy_pass http://127.0.0.1:8080;
}
}
}
- 무제한 설정:
client_max_body_size 0;으로 지정하면 검사를 비활성화할 수 있으나 보안상 권장하지 않습니다. - 수정 후 반영:
sudo nginx -t && sudo systemctl reload nginx
2) Apache 설정 수정 (LimitRequestBody)
Apache에서는 바이트(Byte) 단위로 크기를 지정합니다.
# /etc/apache2/apache2.conf 또는 /etc/httpd/conf/httpd.conf
# 50MB = 52,428,800 Bytes
<Directory "/var/www/html/uploads">
LimitRequestBody 52428800
</Directory>
# 특정 가상 호스트 전체 적용 시
<VirtualHost *:443>
ServerName example.com
LimitRequestBody 52428800
</VirtualHost>
- 수정 후 반영:
sudo apachectl configtest && sudo systemctl reload apache2
3) 백엔드 파이프라인 동기화 (PHP-FPM / Spring Boot)
웹 서버를 통과한 패킷이 백엔드에서 다시 거부당하지 않도록 일관성 있게 값을 맞춰야 합니다.
- PHP (
php.ini):upload_max_filesize = 50M post_max_size = 55M ; post_max_size는 upload_max_filesize보다 커야 함 memory_limit = 128M - Spring Boot (
application.yml):spring: servlet: multipart: max-file-size: 50MB max-request-size: 55MB
주의사항
- 디스크 임시 버퍼 파티션 용량 부족 주의:
- Nginx는 클라이언트 본문 크기가
client_body_buffer_size(보통 8KB~16KB)를 초과하면 본문을 메모리가 아닌/var/lib/nginx/body/경로의 디스크 임시 파일에 기록합니다. 이때 해당 파티션의 디스크 공간이 부족하면 413 대신 500 내부 서버 오류가 발생하므로 디스크 용량을 사전 확인해야 합니다.
- Nginx는 클라이언트 본문 크기가
- 클라우드 로드밸런서(AWS ALB, Cloudflare 등)의 페이로드 제한 체인:
- 웹 서버의
client_max_body_size를 500MB로 늘렸더라도 앞단 CDN/WAF(예: Cloudflare 무료 플랜은 100MB 제한, AWS API Gateway는 10MB 제한)에 의해 앞단에서 먼저 413이 반환될 수 있습니다. 인프라 전체 경로의 페이로드 제한을 함께 점검해야 합니다.
- 웹 서버의
- 무차별 대용량 허용에 따른 DoS 공격 위험:
client_max_body_size 0;으로 완전 해제하거나 수 GB 단위로 전역 오픈할 경우, 악의적인 공격자가 기가바이트 단위의 더미 바이트 스트림을 전송하여 웹 서버의 디스크 I/O와 네트워크 대역폭을 고갈시킬 수 있습니다. 서비스 요구사항에 부합하는 최소한의 한도로 명시해야 합니다.