1. 서론
FastAPI는 현대적이고 빠른 웹 프레임워크로, Python 3.6+의 타입 힌트를 활용하여 빠르고 직관적인 API를 구축할 수 있도록 도와줍니다. 아울러, 데이터베이스와의 상호작용에서 발생할 수 있는 다양한 상황을 효율적으로 처리하기 위해 Alembic과 같은 데이터베이스 마이그레이션 도구가 중요하니다. Alembic은 SQLAlchemy를 기반으로 하며, 여러분이 데이터베이스 스키마의 변경 사항을 관리하는 데 도움을 줍니다. 이 글에서는 FastAPI와 Alembic을 이용하여 데이터베이스 마이그레이션을 어떻게 처리하는지에 대해 자세히 살펴보겠습니다.
2. FastAPI와 Alembic 개요
FastAPI는 비동기적이고 경량화된 웹 서버를 구축할 수 있게 해주는 강력한 프레임워크입니다. RESTful API를 쉽게 발급할 수 있도록 설계되어 있으며, Swagger UI와 Redoc을 통해 자동으로 문서화를 지원합니다. 주로 SQLAlchemy ORM과 함께 사용되며, 데이터베이스와의 원활한 연결을 도와줍니다.
Alembic은 데이터베이스 마이그레이션을 관리하는 툴로, SQLAlchemy와 밀접한 관계를 가지고 있습니다. Alembic을 사용하면 데이터베이스 스키마 변경을 코드로 작성하고, 이를 통해 버전 관리를 할 수 있게 됩니다. 이를 통해 개발자는 데이터베이스 변화에 대한 관리를 더 쉽게 수행할 수 있습니다.
3. 개발 환경 구성
이제 FastAPI와 Alembic을 활용할 수 있는 개발 환경을 구성해 보겠습니다. 아래는 필요한 패키지 설치 방법입니다.
pip install fastapi[all] sqlalchemy alembic
위 명령어를 통해 FastAPI와 SQLAlchemy, Alembic을 설치합니다. 설치가 완료되면, 새로운 프로젝트 디렉토리를 생성하고 하위 디렉토리로 이동합니다.
mkdir fastapi-alembic-example
cd fastapi-alembic-example
이제 FastAPI 애플리케이션을 구성해보겠습니다.
4. FastAPI 애플리케이션 구성
FastAPI 애플리케이션을 위한 기본 구조를 만들어 봅시다. 다음 코드를 사용하여 main.py
파일을 생성합니다.
from fastapi import FastAPI
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
app = FastAPI()
# 데이터베이스 세션을 생성하기 위한 의존성
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/")
def read_root():
return {"Hello": "World"}
위의 코드는 SQLite 데이터베이스에 연결하고 FastAPI 애플리케이션을 초기화합니다. 기본적인 “/
” 엔드포인트를 통해 방문할 수 있는 간단한 환영 메시지를 반환합니다.
5. Alembic 설정
Alembic을 초기화해 보겠습니다. 아래 명령어로 Alembic 설정을 생성할 수 있습니다.
alembic init alembic
위 명령어를 실행하면, alembic
이라는 디렉토리와 alembic.ini
파일이 생성됩니다. 이 파일에서 데이터베이스 URL을 설정해야 합니다.
[alembic]
script_location = alembic
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = INFO
handlers = console
[logger_sqlalchemy]
level = WARN
handlers = console
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers = console
qualname = alembic
[handler_console]
class = StreamHandler
args = []
level = NOTSET
formatter = generic
[formatter_generic]
format = %(asctime)s - %(levelname)s - %(message)s
[alembic:app]
# DB에서 마이그레이션을 위한 FastAPI 데이터베이스 URL 설정
url = sqlite:///./test.db
6. 데이터베이스 모델 정의
이제 Alembic이 관리할 데이터베이스 모델을 정의합니다. 다음과 같이 models.py
파일을 생성하고 작성합니다.
from sqlalchemy import Column, Integer, String
from .database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String, unique=True, index=True)
email = Column(String, unique=True, index=True)
full_name = Column(String, index=True)
disabled = Column(Boolean, default=False)
위와 같이 User
모델을 정의했으며, 이 모델은 사용자의 ID, 사용자 이름, 이메일, 전체 이름 및 비활성화 상태를 포함합니다.
7. 데이터베이스 마이그레이션 생성
Alembic을 사용하여 데이터베이스 마이그레이션을 생성해야 합니다. 다음 명령어를 통해 자동으로 마이그레이션 파일을 생성할 수 있습니다.
alembic revision --autogenerate -m "create users table"
위 명령어를 실행하면 alembic/versions
디렉토리에 새로운 마이그레이션 파일이 생성됩니다. 이 파일은 생성된 users
테이블에 대한 모든 변경 사항을 담고 있습니다.
8. 마이그레이션 적용
생성된 마이그레이션 파일을 데이터베이스에 적용하기 위해 아래와 같이 명령어를 실행합니다.
alembic upgrade head
위 명령어를 실행하면 데이터베이스에 users
테이블이 생성됩니다. 이 과정을 통해 Alembic이 데이터베이스 스키마를 관리하는데 필요한 기본적인 설정을 마쳤습니다.
9. FastAPI와 Alembic 연동
이제 FastAPI 애플리케이션에서 Alembic으로 만든 데이터베이스 모델을 연동해 보겠습니다. main.py
파일을 수정하여 사용자의 데이터를 처리하는 엔드포인트를 추가합니다.
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import models
from .database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
@app.post("/users/", response_model=models.User)
def create_user(user: models.User, db: Session = Depends(get_db)):
db.add(user)
db.commit()
db.refresh(user)
return user
위 코드를 통해 /users/
엔드포인트가 생성되어 사용자를 추가할 수 있게 되었습니다.
10. 결론
FastAPI와 Alembic을 통합하여 데이터베이스 마이그레이션을 관리하는 방법에 대해 알아보았습니다. 이 과정에서 FastAPI의 기본적인 설정과 Alembic을 통한 DB 마이그레이션이 어떻게 이루어지는지 살펴보았습니다. 이러한 방식을 통해 여러분의 웹 애플리케이션에서 데이터베이스 변경 사항을 보다 효과적으로 관리할 수 있을 것입니다.