출시·고도화 중
Django 안내서 · 6/6
개발 서버(runserver)로 잘 돌아가던 프로젝트도 운영에 올리려면 설정을 바꾸고, 정적 파일을 모으고, 운영용 애플리케이션 서버와 리버스 프록시를 붙여야 합니다. 이 장에서는 그 순서를 따라가며 자주 쓰는 구성을 살펴봅니다.
운영 환경에서 반드시 확인해야 할 설정은 다음과 같습니다.
| 설정 | 운영 값 |
|---|---|
DEBUG | False. 켜 두면 오류 화면에 코드와 설정이 노출됩니다 |
SECRET_KEY | 길고 무작위인 값을 환경 변수 등 코드 밖에서 주입 |
ALLOWED_HOSTS | 서비스할 도메인 목록. DEBUG = False이면 비워 둘 수 없습니다 |
DATABASES | 운영 데이터베이스(보통 PostgreSQL) 접속 정보 |
STATIC_ROOT | collectstatic이 정적 파일을 모을 폴더 |
# mysite/settings.py (운영에 필요한 부분)
import os
DEBUG = False
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
ALLOWED_HOSTS = ["example.com", "www.example.com"]
CSRF_TRUSTED_ORIGINS = ["https://example.com", "https://www.example.com"]
STATIC_ROOT = BASE_DIR / "staticfiles"
# HTTPS 관련
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 3600SECURE_PROXY_SSL_HEADER는 앞단 프록시가 X-Forwarded-Proto 헤더를 확실히 설정하고 클라이언트가 보낸 같은 헤더를 덮어쓸 때만 켭니다. HSTS는 처음에 짧은 값으로 시작해 문제가 없을 때 늘립니다. 설정을 마쳤으면 배포 점검 명령으로 빠진 것이 없는지 확인합니다.
DJANGO_SECRET_KEY=... python manage.py check --deployDEBUG = False이면 Django는 정적 파일을 직접 서비스하지 않습니다. collectstatic으로 각 앱의 static/ 파일을 STATIC_ROOT 한곳에 모은 뒤 Nginx 같은 웹 서버나 CDN이 서비스하게 합니다.
python manage.py collectstatic --noinput
python manage.py migrate --noinput웹 서버를 따로 두기 어렵다면 WhiteNoise 패키지를 미들웨어로 추가해 파이썬 프로세스가 정적 파일을 효율적으로 내보내게 할 수 있습니다. 사용자가 올린 파일(MEDIA_ROOT)은 정적 파일과 분리하고, 여러 서버를 쓴다면 S3 같은 객체 저장소를 STORAGES 설정으로 연결합니다.
startproject가 만든 wsgi.py와 asgi.py에는 application 객체가 들어 있습니다. 일반적인 동기 뷰 위주라면 WSGI 서버 Gunicorn을, 비동기 뷰나 웹소켓(Django Channels)이 필요하면 ASGI 서버 Uvicorn이나 Daphne를 씁니다.
python -m pip install gunicorn uvicorn
# WSGI: 워커 프로세스 4개
gunicorn mysite.wsgi --workers 4 --bind 127.0.0.1:8000
# ASGI: Uvicorn 단독
uvicorn mysite.asgi:application --host 127.0.0.1 --port 8000 --workers 4워커 수는 CPU 코어 수를 기준으로 시작해 부하를 보며 조정합니다. 서버 프로세스는 systemd, Supervisor, 컨테이너 오케스트레이터 같은 프로세스 관리자로 실행해 장애 시 다시 뜨게 합니다.
애플리케이션 서버 앞에는 Nginx 같은 리버스 프록시를 둡니다. 프록시가 TLS 종료, 정적 파일 서비스, 느린 클라이언트 버퍼링을 맡고 동적 요청만 Gunicorn에 넘깁니다.
server {
listen 443 ssl;
server_name example.com;
location /static/ {
alias /srv/mysite/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}컨테이너로 배포하면 서버마다 같은 환경을 보장할 수 있습니다. 비밀 값은 이미지에 넣지 말고 실행할 때 환경 변수로 넘깁니다.
FROM python:3-slim
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN DJANGO_SECRET_KEY=build-only python manage.py collectstatic --noinput
CMD ["gunicorn", "mysite.wsgi", "--bind", "0.0.0.0:8000", "--workers", "4"]마이그레이션은 이미지 빌드가 아니라 배포 단계에서 한 번 실행합니다. 운영 중에는 LOGGING 설정으로 오류를 수집하고, ADMINS나 Sentry 같은 도구로 예외 알림을 받도록 해 둡니다.
DEBUG = False, 비밀 SECRET_KEY, ALLOWED_HOSTS를 맞추고 check --deploy로 점검합니다.collectstatic으로 정적 파일을 모아 웹 서버나 WhiteNoise로 서비스합니다.
댓글 0개
로그인 · 로그인하면 댓글을 남길 수 있습니다.
첫 댓글을 남겨 보세요.