웹에서 파일 업로드시 타임아웃이 되는 경우가 있는데요.
웹사이트에서 동영상이나 대용량 파일을 업로드하다 보면 업로드가 중간에 멈추거나 Timeout이 발생하는 경우가 있습니다.
특히 Cloudflare + Nginx + Gunicorn + Django 구조를 사용하고 있다면 어느 한 곳의 설정만 확인해서는 원인을 찾기 어렵습니다.
전체 구조를 보면 다음과 같습니다.
사용자 브라우저
↓
Cloudflare
↓
Nginx
↓
Gunicorn
↓
Django
↓
서버 디스크
각 단계마다 파일 크기 제한과 Timeout이 존재할 수 있습니다.
1. Cloudflare 업로드 용량 제한

가장 먼저 확인해야 할 부분입니다.
Cloudflare를 프록시로 사용하면 업로드 요청도 Cloudflare를 거치게 됩니다. 이때 플랜에 따라 HTTP 요청 크기 제한이 있습니다.
| Free | 100MB |
| Pro | 100MB |
| Business | 200MB |
| Enterprise | 500MB+ |
예를 들어 Free 또는 Pro 플랜에서 300MB짜리 동영상을 업로드한다면 서버의 Nginx 설정이 아무리 크게 되어 있어도 Cloudflare 단계에서 차단될 수 있습니다.
이 경우 대표적으로 413 Request Entity Too Large 오류가 발생할 수 있습니다.
즉,
브라우저
↓
Cloudflare
↓
❌ 100MB 제한
↓
Nginx까지 도달하지 않음
이라는 상황이 발생할 수 있습니다.
따라서 100MB 이상의 파일을 업로드해야 한다면 Cloudflare 제한을 반드시 확인해야 합니다.
2. Nginx의 client_max_body_size
Cloudflare를 통과했다고 끝나는 것이 아닙니다.
그다음에는 Nginx의 업로드 용량 제한이 적용됩니다.
예를 들어 Nginx에 다음과 같이 설정되어 있다면,
client_max_body_size 100M;
100MB를 초과하는 파일은 Nginx에서 거부합니다.
대용량 파일을 허용하려면 예를 들어:
server {
client_max_body_size 2G;
}
처럼 설정할 수 있습니다.
설정 변경 후에는 Nginx를 재시작하거나 설정을 reload합니다.
sudo nginx -t
sudo systemctl reload nginx
다만 중요한 점은 Nginx의 용량 제한을 2GB로 올린다고 Cloudflare의 100MB 제한까지 해결되는 것은 아니라는 것입니다.
3. Nginx Timeout 설정
파일 크기뿐 아니라 업로드에 걸리는 시간도 문제가 될 수 있습니다.
Nginx에서는 다음과 같은 설정을 확인할 수 있습니다.
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
특히 proxy_read_timeout은 Nginx가 Gunicorn으로부터 응답을 기다리는 시간과 관련이 있습니다.
대용량 파일을 업로드하면서 Django가 파일 저장이나 후처리를 오래 수행한다면 Timeout이 발생할 수 있습니다.
4. Gunicorn의 Timeout
Django를 Gunicorn으로 실행하고 있다면 Gunicorn도 확인해야 합니다.
Gunicorn의 기본 timeout은 일반적으로 30초입니다.
예를 들어 업로드 요청을 처리하는 데 30초 이상 걸리면 Worker Timeout이 발생할 수 있습니다.
설정은 다음과 같이 늘릴 수 있습니다.
gunicorn config.wsgi:application \
--bind 127.0.0.1:8000 \
--timeout 600
또는 Gunicorn 설정 파일에서:
timeout = 600
처럼 설정할 수 있습니다.
Gunicorn 로그에서 다음과 같은 메시지가 나타난다면 이 부분을 의심할 수 있습니다.
WORKER TIMEOUT
로그는 다음과 같이 확인할 수 있습니다.
sudo journalctl -u gunicorn -n 100
실시간으로 확인하려면:
sudo journalctl -u gunicorn -f
5. Django에서 발생하는 Timeout
사실 대용량 파일 업로드에서 가장 문제가 되는 부분 중 하나입니다.
단순히 파일을 서버에 저장하는 것이라면 비교적 문제가 적지만, 업로드 과정에서 다음 작업까지 동시에 수행한다면 시간이 크게 늘어날 수 있습니다.
- 동영상 변환
- FFmpeg 실행
- 썸네일 생성
- 영상 분석
- 압축
- AI 처리
- 데이터베이스 처리
예를 들어:
동영상 업로드
↓
Django
↓
파일 저장
↓
FFmpeg 영상 변환
↓
썸네일 생성
↓
DB 저장
↓
응답
이 모든 작업을 하나의 HTTP 요청 안에서 처리하면 Gunicorn이나 Nginx Timeout이 발생하기 쉽습니다.
가능하면 다음과 같은 구조로 분리하는 것이 좋습니다.
동영상 업로드
↓
파일 저장
↓
"업로드 완료" 응답
↓
백그라운드 작업
↓
FFmpeg / 썸네일 / 영상 처리
Celery나 RQ 같은 작업 큐를 이용하면 이런 구조를 만들 수 있습니다.
6. 서버 디스크 용량도 확인해야 한다
의외로 단순한 문제일 수도 있습니다.
대용량 동영상을 계속 업로드하면 서버 디스크가 가득 찰 수 있습니다.
확인 방법은:
df -h
입니다.
예를 들어:
Filesystem Size Used Avail Use%
/dev/root 100G 98G 2.0G 99%
처럼 나온다면 업로드 실패의 원인이 디스크 공간 부족일 가능성이 높습니다.
CPU와 메모리도 확인할 수 있습니다.
top
또는:
free -h
실제로 어디에서 Timeout이 발생했는지 확인하는 방법
가장 좋은 방법은 Cloudflare → Nginx → Gunicorn 로그를 동시에 확인하는 것입니다.
Nginx
sudo tail -f /var/log/nginx/access.log /var/log/nginx/error.log
Gunicorn
sudo journalctl -u gunicorn -f
업로드를 다시 시도하면서 로그를 보면 어느 단계에서 문제가 발생했는지 확인할 수 있습니다.
예를 들어 Nginx에서:
upstream timed out
이라는 메시지가 나온다면 Nginx와 Gunicorn 사이의 Timeout을 의심할 수 있습니다.
Gunicorn에서:
WORKER TIMEOUT
이 발생한다면 Gunicorn의 Timeout이나 Django 처리 시간을 확인해야 합니다.
반대로 100MB 이상의 파일에서만:
413 Request Entity Too Large
가 발생한다면 Cloudflare 또는 Nginx의 파일 크기 제한을 먼저 확인해야 합니다.
핵심은 '파일 크기'와 '처리 시간'을 구분하는 것
대용량 업로드 문제는 크게 두 가지로 나눌 수 있습니다.
① 파일 크기 제한
Cloudflare
↓
Nginx
↓
Django
각 단계에서 허용하는 최대 파일 크기가 다릅니다.
② 처리 시간 제한
Cloudflare
↓
Nginx
↓
Gunicorn
↓
Django
파일을 처리하는 데 너무 오래 걸리면 Timeout이 발생할 수 있습니다.
따라서 "파일이 커서 실패하는 것인지"와 "처리 시간이 오래 걸려서 실패하는 것인지"를 먼저 구분하는 것이 중요합니다.
대용량 동영상 업로드라면 어떤 구조가 좋을까?
단순히 Timeout을 600초, 1,000초로 늘리는 것만으로 해결하는 것은 좋은 방법이 아닙니다.
특히 동영상 업로드가 많은 서비스라면 다음과 같은 구조를 고려하는 것이 좋습니다.
┌──────────────┐
│ Browser │
└──────┬───────┘
↓
┌──────────────┐
│ File Storage│
└──────┬───────┘
↓
┌──────────────┐
│ Django │
└──────┬───────┘
↓
┌──────────────┐
│ Background │
│ Worker │
└──────────────┘
특히 Cloudflare를 사용하면서 100MB를 넘는 파일을 자주 업로드한다면 Cloudflare R2 같은 오브젝트 스토리지를 사용하거나, 업로드 전용 도메인을 Cloudflare 프록시에서 우회하는 방법도 고려할 수 있습니다.
정리
대용량 파일 업로드에서 문제가 발생한다면 다음 순서로 확인하면 됩니다.
1. Cloudflare
└─ 최대 요청 크기 확인
2. Nginx
├─ client_max_body_size
└─ proxy timeout
3. Gunicorn
└─ timeout
4. Django
└─ 업로드 및 후처리 시간
5. 서버
├─ 디스크 용량
├─ CPU
└─ 메모리
6. 로그
├─ Nginx error.log
└─ Gunicorn 로그
특히 100MB를 넘는 동영상 업로드에서 문제가 발생한다면 Cloudflare의 요청 크기 제한을 가장 먼저 확인하는 것이 좋습니다.
반대로 파일 크기와 관계없이 30초 전후로 끊긴다면 Gunicorn Timeout, Nginx 로그에 upstream timed out이 나타난다면 Nginx ↔ Gunicorn 구간을 우선적으로 확인하는 방식으로 원인을 좁혀갈 수 있습니다.
'Programming' 카테고리의 다른 글
| 파이썬 크롤링시 Cookie 받아서 하기 (0) | 2026.07.22 |
|---|---|
| 코딩 LLM 비교 - Claude, Gemini, ChatGPT (0) | 2026.07.18 |
| 바이브 코딩 구글 AI 스튜디오 이용하기 (0) | 2026.06.25 |
| 오라클 프리티어 정책 변경 (0) | 2026.06.15 |
| 티스토리 코드 복사 버튼 만들기 (0) | 2026.05.10 |