FastAPI Pydantic SQLAlchemy 연동 완전 정복(2025년)

 

이 글은 FastAPI, Pydantic 2.x, 그리고 SQLAlchemy를 처음 접하는 개발자부터 실무에 활용하고자 하는 분들을 대상으로 합니다.

  • FastAPI 기반 웹 API를 만들 때 Pydantic 2.x 모델을 활용한 데이터 검증, SQLAlchemy ORM과의 자연스러운 연동 방식을 단계별로 이해할 수 있도록 돕습니다.
  • Python 기초 문법을 알고 있고, 웹 프레임워크 또는 ORM 사용 경험이 약간 있는 개발자. 초등학생도 이해할 수 있을 정도로 친절한 설명을 제공합니다.

FastAPI 개요

FastAPI는 현대적인 비동기(Asynchronous) 웹 프레임워크로, Starlette를 기반으로 하고, Pydantic을 통해 입력 검증과 직렬화를 제공하여 빠르고 안정적인 API를 구축할 수 있습니다.

  • 주요 특징
    • 비동기 지원: async def로 작성한 경로 함수(route)가 기본 비동기 처리
    • 자동 문서화: OpenAPI(Swagger)와 ReDoc을 자동 생성
    • 높은 성능: Uvicorn + ASGI 기반으로 빠른 처리 속도
  • 사용 장점
    1. 타입 힌트를 적극 활용한 유효성 검사
    2. 생산성과 가독성 모두 제고
    3. 최소한의 설정으로 바로 사용 가능

Pydantic 2.x 개념 이해

PydanticPython 타입 힌트를 기반으로 런타임 시 데이터 검증(validation)과 직렬화(serialization)를 수행합니다. 2.x 버전은 더 가볍고 빠른 성능을 목표로 핵심 구조가 일부 변경되었습니다.

BaseModel 사용법

  1. 모델 정의
    from pydantic import BaseModel, Field
    
    class User(BaseModel):
        id: int
        name: str = Field(..., max_length=50)
        signup_ts: datetime | None = None
    
  2. 인스턴스 생성
    user = User(id=1, name="Alice")
    

필드 검증(Validation)

  • 기본 검증: 타입이 일치하지 않으면 ValidationError 발생
  • 제약 조건: Field 파라미터로 min_length, max_length, gt, lt 등 설정 가능
  • 커스텀 검증: @field_validator 데코레이터로 복잡한 규칙 적용

직렬화와 역직렬화

  • 직렬화: model.json() 또는 model.dict()로 Python 객체 → JSON/Dict 변환
  • alias: 필드 이름을 외부와 다르게 매핑 가능
  • export 옵션: exclude_none=TrueNone 필드 자동 제외

SQLAlchemy 소개

SQLAlchemy는 Python ORM(Object-Relational Mapping) 라이브러리로, 데이터베이스 테이블을 Python 클래스로 다룰 수 있게 해 줍니다.

엔진과 세션 설정

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, echo=True)
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)

모델 정의와 매핑

from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String

Base = declarative_base()

class UserORM(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)

Pydantic과 SQLAlchemy 연동

Pydantic 2.x와 호환되는 SQLAlchemy 버전(1.4+)을 사용하면, from_orm 옵션으로 SQLAlchemy ORM 인스턴스를 Pydantic 모델로 쉽게 변환할 수 있습니다.

from_orm 옵션

  1. Pydantic 모델 설정
    class UserSchema(BaseModel):
        id: int
        name: str
    
        model_config = ConfigDict(from_attributes=True)
    
  2. ORM → Pydantic 변환
    db_user = session.query(UserORM).first()
    user_data = UserSchema.from_orm(db_user)
    

SQLModel 대안

  • SQLModel: FastAPI의 창시자 Sebastián Ramírez가 만든, Pydantic + SQLAlchemy를 합친 통합 라이브러리
  • 장점: 별도 연동 설정 불필요, from_orm이 기본
  • 단점: 커스터마이징 한계

CRUD 구현 예제

  1. Create
    @app.post("/users/", response_model=UserSchema)
    def create_user(user: UserSchema, db: Session = Depends(get_db)):
        db_user = UserORM(**user.model_dump())
        db.add(db_user); db.commit(); db.refresh(db_user)
        return db_user
    
  2. Read
    @app.get("/users/{user_id}", response_model=UserSchema)
    def read_user(user_id: int, db: Session = Depends(get_db)):
        return db.get(UserORM, user_id)
    
  3. Update
    @app.put("/users/{user_id}", response_model=UserSchema)
    def update_user(user_id: int, user: UserSchema, db: Session = Depends(get_db)):
        db_user = db.get(UserORM, user_id)
        for k, v in user.model_dump(exclude_unset=True).items():
            setattr(db_user, k, v)
        db.commit(); db.refresh(db_user)
        return db_user
    
  4. Delete
    @app.delete("/users/{user_id}")
    def delete_user(user_id: int, db: Session = Depends(get_db)):
        db_user = db.get(UserORM, user_id)
        db.delete(db_user); db.commit()
        return {"ok": True}
    

FastAPI 라우터와 의존성 주입

  • 라우터 구조: @app.get(), @app.post() 등 데코레이터로 엔드포인트 선언
  • 의존성 주입: Depends(get_db)로 DB 세션, 인증, 설정 등을 간편하게 삽입
def get_db():
    db = SessionLocal(); 
    try: yield db
    finally: db.close()

에러 처리 및 응답 모델

  • HTTPException
    from fastapi import HTTPException
    if not db_user:
        raise HTTPException(status_code=404, detail="User not found")
    
  • 응답 모델: response_model 파라미터로 자동 검증 및 문서화

설정 관리 및 환경 변수

  • pydantic-settings
    from pydantic_settings import BaseSettings
    
    class Settings(BaseSettings):
        database_url: str
        class Config:
            env_file = ".env"
    settings = Settings()
    
  • .env 파일: 민감한 정보는 분리합니다.

테스트 작성 팁

  • pytest 사용
    from fastapi.testclient import TestClient
    client = TestClient(app)
    
    def test_create_user():
        response = client.post("/users/", json={"id":1,"name":"Alice"})
        assert response.status_code == 200
    
  • 테스트 DB: 별도 SQLite 인메모리 사용

성능 최적화 전략

  • 데이터베이스 튜닝: 인덱싱, 쿼리 최적화
  • 캐싱: Redis 활용, FastAPI의 BackgroundTask

배포 및 운영 고려사항

  • Docker 이미지 구성: Dockerfiledocker-compose.yml
  • Alembic 마이그레이션:
    alembic init alembic
    alembic revision --autogenerate -m "init"
    alembic upgrade head
    
  • CI/CD: GitHub Actions, Jenkins 등 연동

결론 및 요약

지금까지 FastAPI, Pydantic 2.x, 그리고 SQLAlchemy를 연동해 실무 API를 만드는 데 핵심이 되는 개념과 문법을 살펴보았습니다.

  • 핵심 요약:
    1. Pydantic으로 입력 검증 및 직렬화
    2. SQLAlchemy ORM과 from_orm 옵션으로 매끄러운 모델 변환
    3. FastAPI에서 의존성 주입과 자동 문서화 활용

FastAPIPydantic, SQLAlchemy를 연동해, 견고하고 확장성 있는 Python 기반 API 서버를 구축해 보시길 바랍니다!

2025년 최신 npm 설치 가이드 – 윈도우, 맥, 리눅스 완벽 정복

 

Leave a Comment