파이썬/Fast API

프로젝트 배포 자동화 가이드 Part 1: 개발 환경 구성

코샵 2025. 2. 3. 11:12
반응형

윈도우에서 개발한 FastAPI 프로젝트를 리눅스 환경에서 배포하는 과정을 자동화해보겠습니다. 특히 Python 버전과 의존성 관리를 자동화하여 편리하게 배포할 수 있도록 구성하겠습니다.

프로젝트 구조 설정

my-fastapi-project/
├── app/
│   ├── api/
│   ├── core/
│   ├── models/
│   └── main.py
├── tests/
├── .github/
│   └── workflows/
│       ├── ci.yml
│       └── cd.yml
├── scripts/
│   ├── generate_requirements.py
│   ├── get_python_version.py
│   └── start.sh
├── Dockerfile
├── docker-compose.yml
└── .env.example

Python 버전 감지 스크립트

현재 개발 환경의 Python 버전을 자동으로 감지하는 스크립트입니다.

# scripts/get_python_version.py
import sys
import json

def get_python_version():
    version = sys.version_info
    return {
        "major": version.major,
        "minor": version.minor,
        "micro": version.micro,
        "full": f"{version.major}.{version.minor}.{version.micro}"
    }

if __name__ == "__main__":
    version_info = get_python_version()
    print(json.dumps(version_info))

의존성 자동 생성 스크립트

현재 프로젝트의 의존성을 자동으로 감지하여 requirements.txt를 생성합니다.

# scripts/generate_requirements.py
import pkg_resources
import subprocess
from pathlib import Path

def generate_requirements():
    # 현재 환경의 모든 패키지 가져오기
    installed_packages = [
        f"{dist.key}=={dist.version}"
        for dist in pkg_resources.working_set
    ]

    # FastAPI 필수 패키지 추가
    required_packages = [
        "fastapi",
        "uvicorn[standard]",
        "python-dotenv",
        "sqlalchemy",
        "alembic",
        "pytest",
        "httpx"
    ]

    # requirements.txt 생성
    output_path = Path("requirements.txt")
    with output_path.open("w") as f:
        for package in required_packages:
            if any(p.startswith(package) for p in installed_packages):
                matching_pkg = next(p for p in installed_packages if p.startswith(package))
                f.write(f"{matching_pkg}\n")
            else:
                f.write(f"{package}\n")

if __name__ == "__main__":
    generate_requirements()
    print("requirements.txt has been generated successfully!")

동적 Dockerfile

Python 버전을 자동으로 감지하여 적용하는 Dockerfile입니다.

# Dockerfile
ARG PYTHON_VERSION
FROM python:${PYTHON_VERSION}-slim as builder

WORKDIR /app
ENV PYTHONPATH=/app

# 가상환경 생성
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 프로덕션 스테이지
FROM python:${PYTHON_VERSION}-slim

WORKDIR /app
ENV PYTHONPATH=/app

# 가상환경 복사
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# 애플리케이션 코드 복사
COPY ./app /app/app

# 시작 스크립트 복사
COPY ./scripts/start.sh /app/start.sh
RUN chmod +x /app/start.sh

CMD ["/app/start.sh"]

GitHub Actions CI 워크플로우

Python 버전 감지와 의존성 생성을 자동화하는 CI 설정입니다.

# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      python_version: ${{ steps.get_python_version.outputs.version }}

    steps:
    - uses: actions/checkout@v2

    - name: Get Python Version
      id: get_python_version
      run: |
        python_version=$(python scripts/get_python_version.py | jq -r .full)
        echo "version=${python_version}" >> $GITHUB_OUTPUT

    - name: Generate Requirements
      run: python scripts/generate_requirements.py

    - name: Cache requirements.txt
      uses: actions/cache@v2
      with:
        path: requirements.txt
        key: ${{ runner.os }}-requirements-${{ hashFiles('**/requirements.txt') }}

  test:
    needs: prepare
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: ${{ needs.prepare.outputs.python_version }}

    - name: Restore cached requirements
      uses: actions/cache@v2
      with:
        path: requirements.txt
        key: ${{ runner.os }}-requirements-${{ hashFiles('**/requirements.txt') }}

    - name: Install dependencies
      run: pip install -r requirements.txt

    - name: Run tests
      run: pytest tests/

docker-compose.yml

개발 환경 설정을 위한 docker-compose 파일입니다.

version: '3.8'

services:
  web:
    build:
      context: .
      args:
        - PYTHON_VERSION=${PYTHON_VERSION}
    ports:
      - "8000:8000"
    env_file:
      - .env
    volumes:
      - ./app:/app/app
    depends_on:
      - db
      - redis
    networks:
      - app-network

  db:
    image: postgres:13
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    networks:
      - app-network

  redis:
    image: redis:6
    networks:
      - app-network

networks:
  app-network:

volumes:
  postgres_data:

이렇게 구성하면 개발자의 Python 버전을 자동으로 감지하고, 프로젝트의 의존성도 자동으로 관리할 수 있습니다. CI/CD 파이프라인에서도 이 정보들을 활용하여 일관된 환경을 구성할 수 있습니다.