[2026] Python 웹 배포 | Heroku, AWS, Docker 배포 완벽 정리

[2026] Python 웹 배포 | Heroku, AWS, Docker 배포 완벽 정리

이 글의 핵심

from dotenv import load_dotenv import os.

들어가며

”개발은 끝, 이제 배포”

배포는 애플리케이션을 실제 사용자에게 제공하는 과정입니다.

실무 활용 사례: 데이터 분석, 웹 개발, 자동화 프로젝트에서 실제로 사용한 패턴과 코드를 바탕으로 정리했습니다. 초보자가 흔히 겪는 오류와 해결법을 포함합니다.

1. 배포 준비

requirements.txt

서버에 올릴 때는 개발 PC에 깔린 패키지 목록을 영수증처럼 고정해 두는 것이 안전합니다. pip freeze로 버전까지 적어 두면, 나중에 같은 조합을 다시 설치하기 쉽습니다.

# 패키지 목록 생성
pip freeze > requirements.txt
Flask==2.3.0
gunicorn==20.1.0
python-dotenv==1.0.0

환경 변수 (.env)

다음은 간단한 python 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# .env
SECRET_KEY=your-secret-key
DATABASE_URL=postgresql://user:pass@localhost/db
DEBUG=False

아래 코드는 python를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.

# app.py
from dotenv import load_dotenv
import os
load_dotenv()
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
app.config['DEBUG'] = os.getenv('DEBUG', 'False') == 'True'

2. Gunicorn 설정

Gunicorn으로 실행

아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# 설치
pip install gunicorn
# 실행
gunicorn app:app
# 워커 설정
gunicorn -w 4 -b 0.0.0.0:8000 app:app

gunicorn.conf.py

아래 코드는 python를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

bind = "0.0.0.0:8000"
workers = 4
worker_class = "sync"
timeout = 30
keepalive = 2

3. Docker 배포

Dockerfile

아래 코드는 dockerfile를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "app:app"]

docker-compose.yml

다음은 yaml를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      - db
  
  db:
    image: postgres:15
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
volumes:
  postgres_data:
# 실행
docker-compose up -d

4. Heroku 배포

Procfile

web: gunicorn app:app

runtime.txt

python-3.11.0

배포 명령어

아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# Heroku CLI 설치 후
heroku login
heroku create myapp
# 환경 변수 설정
heroku config:set SECRET_KEY=your-secret-key
# 배포
git push heroku main
# 로그 확인
heroku logs --tail

5. AWS 배포 (EC2)

EC2 설정

다음은 bash를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# 서버 접속
ssh -i key.pem ubuntu@ec2-instance
# Python 설치
sudo apt update
sudo apt install python3-pip python3-venv
# 프로젝트 클론
git clone https://github.com/user/myapp.git
cd myapp
# 가상환경
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Gunicorn 실행
gunicorn -w 4 -b 0.0.0.0:8000 app:app

Nginx 설정

아래 코드는 nginx를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name example.com;
    
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

다음은 간단한 bash 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

# Nginx 활성화
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

6. 프로덕션 배포 전에 확인할 항목

서버에 올리는 순간 앱은 디버그 모드가 꺼진 채 외부와 연결됩니다. 비밀 키·DB URL은 환경 변수로만 두고, Django라면 ALLOWED_HOSTScollectstatic·migrate까지 한 번에 점검하는 습관이 필요합니다. HTTPS는 인증서(예: Let’s Encrypt)나 프록시 뒤에서 종료하는 방식으로 맞춥니다. 다음은 python를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

# ✅ 환경 변수
# SECRET_KEY, DATABASE_URL 등
# ✅ DEBUG = False
app.config['DEBUG'] = False
# ✅ ALLOWED_HOSTS (Django)
ALLOWED_HOSTS = ['yourdomain.com']
# ✅ 정적 파일
python manage.py collectstatic
# ✅ 데이터베이스 마이그레이션
python manage.py migrate
# ✅ HTTPS 설정
# Let's Encrypt, Cloudflare

실전 심화 보강

실전 예제: Gunicorn + systemd 유닛 (프로덕션 최소 패턴)

애플리케이션은 myapp.wsgi:app이라고 가정합니다. 소켓 활성화 대신 여기서는 127.0.0.1:8000 바인드 예시를 둡니다. /etc/systemd/system/myapp.service: 다음은 ini를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

[Unit]
Description=My Gunicorn App
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
EnvironmentFile=/etc/myapp.env
ExecStart=/var/www/myapp/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 myapp.wsgi:app
Restart=always
[Install]
WantedBy=multi-user.target

배포 후 sudo systemctl daemon-reload && sudo systemctl enable --now myapp으로 기동합니다.

자주 하는 실수

  • DEBUG=True로 운영에 올려 시크릿·트레이스백이 노출되는 경우.
  • 가상환경 경로를 하드코딩해 배포 스크립트가 깨지는 경우.
  • 헬스체크 없이 로드밸런서만 믿고 프로세스가 죽은 줄 모르는 경우.

주의사항

  • 시크릿은 환경 변수·비밀 저장소에 두고 Git에 넣지 마세요.
  • ALLOWED_HOSTS·CORS·CSRF는 프로덕션 프로파일에서 재검증합니다.

실무에서는 이렇게

  • 리버스 프록시(Nginx/Caddy) 앞에 두고 TLS 종료를 맡깁니다.
  • 로그는 journald + 중앙 집중(CloudWatch, ELK)으로 보냅니다.
  • 컨테이너라면 읽기 전용 루트fs + non-root 유저를 기본으로 합니다.

비교 및 대안

방식장점
PaaS(Heroku 등)운영 단순
VM + systemd제어·비용 트레이드오프
Kubernetes대규모·멀티 서비스

추가 리소스


정리

핵심 요약

  1. Gunicorn: WSGI 서버
  2. Docker: 환경 일관성
  3. Heroku: 간단한 배포
  4. AWS: 유연하고 저렴
  5. Nginx: 리버스 프록시

다음 단계


관련 글

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3