728x90

FastAPI 개발자 tiangolo는 FastAPI를 어떻게 사용할까 궁금해서 찾아본 프로젝트

https://github.com/tiangolo/full-stack-fastapi-postgresql

이번 게시글에서는 프로젝트 데이터베이스 마이그레이션 도구인 alembic을 어떻게 적용하였는지 분석하려고 함

 

alembic 관련 파일은 아래와 같음

```

.env # 환경 변수 설정이 담긴 파일 → DB 설정을 이 파일에서 확인 가능

alembic.ini # Alembic의 설정 파일로, 데이터베이스 마이그레이션 설정을 정의 

app

└──  alembic # 데이터베이스 마이그레이션을 관리하는 Alembic 설정 파일 및 스크립트가 저장된 디렉토리

           ├──  env.py # alembic 실행 시 실행되는 파일로, SQLAIchemy의 Engine을 설정하고 마이그레이션 스크립트 실행
           └──  versions # 버전 별 데이터베이스 마이그레이션 스크립트가 저장된 디렉토리

                   └── e2412789c190_initialize_models.py # 데이터 베이스 테이블 및 인덱스 생성 스크립트

└──  models.py # ORM 도구에서 데이터 모델을 정의하는데 사용되는 파일로, 이 파일의 모델과 DB 차이를 바탕으로 마이그레이션 스크립트가 생성됨

```

.env

파이썬에서는 프로젝트 별로 환경변수를 관리하기 위하여 .env파일을 널리 사용함

.env파일에 설정된 alembic에 사용되는 환경변수는 아래와 같음

# Postgres
POSTGRES_SERVER=db
POSTGRES_USER=postgres
POSTGRES_DB=app
POSTGRES_PASSWORD=changethis

alembic.ini

alembic.ini 파일은 Alembic 데이터베이스 마이그레이션 도구의 설정 파일로, 주로 데이터베이스 연결 및 마이그레이션 관련 설정을 포함

  • 일반적으로 사용되는 설정
    • 데이터베이스 연결 정보 설정 (sqlalchemy.url)
    • 마이그레이션 스크립트 경로 설정 (script_location)
    • 로깅 설정 (loggers, handlers, formatters)
    • 버전 관리 설정 (version_table)
    • 그 외 커스텀 설정

tiangolo 백엔드 프로젝트의 alembic.ini는 아래와 같은 설정으로 구성되어 있음

# A generic, single database configuration.

[alembic]
script_location = app/alembic # 마이그레이션 스크립트가 있는 디렉토리의 경로를 지정

[loggers]
keys = root,sqlalchemy,alembic # 설정될 로거의 이름을 지정

[handlers]
keys = console # "console"이라는 핸들러가 설정되어 있다는 것을 지정

[formatters]
keys = generic # "generic"이라는 포매터가 설정되어 있다는 것을 지정

[logger_root] # "root"에 대한 로거를 구성
level = WARN
handlers = console
qualname = 

[logger_sqlalchemy] # "sqlalchemy"에 대한 로거를 구성
level = WARN 
handlers =
qualname = sqlalchemy.engine

[logger_alembic] # "alembic"에 대한 로거를 구성
level = INFO
handlers =
qualname = alembic

[handler_console] # 콘솔 핸들러를 구성 (콘솔 핸들러는 로그 메시지를 콘솔에 출력)
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic] #  "generic" 포매터에 대한 설정을 정의
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

env.py

 alembic 실행 시 실행되는 파일로, SQLAIchemy의 Engine을 설정하고 마이그레이션 스크립트 실행

  • 주요 작업
    • 모듈 및 패키지 가져오기
    • context.config를 사용하여 Alembic Config 객체를 설정
      이 객체는 사용 중인
      .ini 파일 내의 값을 제공
    • fileConfig(config.config_file_name)을 호출하여 Python 로깅을 설정
      .ini 파일의 로깅 구성을 기반으로 로그 기능을 활성화
    • app.models에서 SQLModel을 가져와 target_metadata로 설정
      마이그레이션 스크립트에서 사용할 데이터베이스 모델의 메타데이터를 지정
    • get_url함수는 .env(환경 변수)를 통해 PostgreSQL 데이터베이스 연결 URL을 생성
    • run_migrations_offline 함수는 오프라인 모드에서 마이그레이션을 실행
    • run_migrations_online 함수는 온라인 모드에서 마이그레이션 실행
    • context.is_offline_mode()를 사용하여 현재 마이그레이션 모드가 오프라인인지 확인하고, 그에 따라 run_migrations_offline 또는 run_migrations_online 함수를 호출하여 마이그레이션을 실행

versions / e2412789c190_initialize_models.py

데이터 베이스 테이블 및 인덱스 생성 스크립트

일반적으로 alembic을 이용하여 마이그레이션 스크립트를 자동적으로 생성하면 models.py파일을 기반으로 테이블 생성/삭제 스크립트만 생성됨

index 생성 스크립트는 수동으로 추가했을 것으로 예상됨

alembic이 뭔지 모르는 경우 alembic 소개 및 기초 사용법 포스팅 참고

"""Initialize models

Revision ID: e2412789c190
Revises:
Create Date: 2023-11-24 22:55:43.195942

"""
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
from alembic import op

# revision identifiers, used by Alembic.
revision = "e2412789c190"
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "user",
        sa.Column("email", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
        sa.Column("is_active", sa.Boolean(), nullable=False),
        sa.Column("is_superuser", sa.Boolean(), nullable=False),
        sa.Column("full_name", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column(
            "hashed_password", sqlmodel.sql.sqltypes.AutoString(), nullable=False
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(op.f("ix_user_email"), "user", ["email"], unique=True)
    op.create_table(
        "item",
        sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
        sa.Column("id", sa.Integer(), nullable=False),
        sa.Column("title", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
        sa.Column("owner_id", sa.Integer(), nullable=False),
        sa.ForeignKeyConstraint(
            ["owner_id"],
            ["user.id"],
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table("item")
    op.drop_index(op.f("ix_user_email"), table_name="user")
    op.drop_table("user")
    # ### end Alembic commands ###

 

참고 : FastAPI 개발자가 직접 개발한 FastAPI backend 시리즈

FastAPI 개발자가 직접 개발한 FastAPI backend 프로젝트 구조

FastAPI 개발자가 직접 개발한 FastAPI backend alembic

FastAPI 개발자가 직접 개발한 FastAPI backend DB 초기화 방법

FastAPI 개발자가 직접 개발한 FastAPI backend pyproject.toml

FastAPI 개발자가 직접 개발한 FastAPI backend 설정파일 config.py

FastAPI 개발자가 직접 개발한 FastAPI backend 데이터모델 models.py

 

728x90

+ Recent posts