FastAPI에서 Pydantic V2 마이그레이션 후 성능 개선

배경

사내 주문 API 서버가 Pydantic V1을 사용 중이었다. Pydantic V2가 6월에 정식 출시되었고, Rust 기반으로 재작성되어 성능 개선이 크다는 얘기를 들었다. 피크 타임에 검증 로직이 병목이라는 모니터링 결과가 있어서 마이그레이션을 진행했다.

주요 변경사항

1. Config 클래스 변경

# Before (V1)
class OrderRequest(BaseModel):
    order_id: int
    items: List[dict]
    
    class Config:
        orm_mode = True

# After (V2)
class OrderRequest(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    
    order_id: int
    items: List[dict]

orm_modefrom_attributes로 바뀌었고, Config 내부 클래스 대신 model_config 속성을 사용한다.

2. validator 데코레이터

# Before
@validator('items')
def validate_items(cls, v):
    if len(v) == 0:
        raise ValueError('empty items')
    return v

# After
@field_validator('items')
@classmethod
def validate_items(cls, v):
    if len(v) == 0:
        raise ValueError('empty items')
    return v

@validator@field_validator로 변경되었고, 명시적으로 @classmethod를 붙여야 한다.

3. dict() 메서드

# Before
data = order.dict()

# After  
data = order.model_dump()

.dict() 대신 .model_dump()를 사용한다. JSON 직렬화는 .model_dump_json().

성능 측정

실제 프로덕션 데이터 10,000건으로 테스트했다.

  • 단순 모델 검증: 0.8초 → 0.15초 (5.3배)
  • 중첩 모델 검증: 2.1초 → 0.12초 (17.5배)
  • JSON 직렬화: 1.2초 → 0.3초 (4배)

특히 중첩이 깊은 모델에서 체감 차이가 컸다.

주의사항

FastAPI 0.104+ 버전이 필요하다. 그 이전 버전은 Pydantic V2를 완전히 지원하지 않는다. SQLAlchemy ORM 모델 변환 시 from_attributes=True 설정을 빠뜨리면 런타임 에러가 발생한다.

마이그레이션 가이드를 따라가면 대부분 자동 변환이 가능하지만, 커스텀 validator가 많으면 수동 작업이 필요하다. 테스트 커버리지가 충분하다면 반나절 정도면 작업 가능했다.