반응형
소개
FastAPI와 함께 자주 사용되는 Pydantic의 Field를 통해 데이터 유효성 검사를 구현하는 방법을 알아보겠습니다.
설치 방법
# pip 사용
pip install pydantic
# poetry 사용
poetry add pydantic
# pipenv 사용
pipenv install pydantic
기본 사용법
간단한 모델 정의
from pydantic import BaseModel, Field
class User(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
age: int = Field(gt=0, lt=150)
email: str = Field(..., pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
Field의 주요 검증 옵션
옵션 | 설명 | 예시 |
---|---|---|
default | 기본값 설정 | Field(default=0) |
gt/lt | 크기 비교 | Field(gt=0, lt=100) |
ge/le | 이상/이하 | Field(ge=0, le=100) |
min_length/max_length | 문자열 길이 | Field(min_length=2) |
regex/pattern | 정규식 패턴 | Field(pattern=r"\d+") |
description | 필드 설명 | Field(description="사용자 이름") |
고급 사용법
복잡한 검증 규칙
from typing import List
from pydantic import BaseModel, Field, validator
class Product(BaseModel):
name: str = Field(..., min_length=1)
price: float = Field(gt=0)
tags: List[str] = Field(default_factory=list, max_items=5)
@validator('price')
def validate_price(cls, value):
if not value.is_integer() and value * 100 % 10 != 0:
raise ValueError('가격은 1원 단위까지만 허용됩니다')
return value
중첩 모델
class Address(BaseModel):
street: str = Field(..., min_length=5)
city: str = Field(..., min_length=2)
country: str = Field(..., min_length=2)
class User(BaseModel):
name: str = Field(..., min_length=2)
addresses: List[Address] = Field(default_factory=list, max_items=3)
상수 및 제약 조건
from enum import Enum
from typing import Optional
class UserType(str, Enum):
ADMIN = "admin"
USER = "user"
GUEST = "guest"
class User(BaseModel):
name: str = Field(..., min_length=2)
type: UserType = Field(default=UserType.GUEST)
status: str = Field(
default="active",
pattern="^(active|inactive|suspended)$"
)
실전 예제
회원가입 검증
from datetime import date
from typing import Optional
from pydantic import BaseModel, Field, EmailStr, validator
class UserRegistration(BaseModel):
email: EmailStr = Field(
...,
description="사용자 이메일"
)
password: str = Field(
...,
min_length=8,
pattern=r"^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$",
description="최소 8자, 하나의 문자, 숫자, 특수문자 포함"
)
name: str = Field(
...,
min_length=2,
max_length=50,
description="사용자 이름"
)
birth_date: date = Field(
...,
description="생년월일"
)
phone: Optional[str] = Field(
None,
pattern=r"^\d{3}-\d{4}-\d{4}$",
description="전화번호 (000-0000-0000 형식)"
)
@validator('birth_date')
def validate_birth_date(cls, v):
if v > date.today():
raise ValueError('생년월일은 현재 날짜보다 이후일 수 없습니다')
return v
상품 정보 검증
from decimal import Decimal
from typing import List, Optional
class ProductCreate(BaseModel):
name: str = Field(
...,
min_length=2,
max_length=100,
description="상품명"
)
price: Decimal = Field(
...,
ge=Decimal('0'),
decimal_places=2,
description="상품 가격 (최대 소수점 2자리)"
)
description: Optional[str] = Field(
None,
max_length=1000,
description="상품 설명"
)
categories: List[str] = Field(
default_factory=list,
min_items=1,
max_items=5,
description="상품 카테고리 (1-5개)"
)
stock: int = Field(
default=0,
ge=0,
description="재고 수량"
)
@validator('categories')
def validate_categories(cls, v):
if len(set(v)) != len(v):
raise ValueError('중복된 카테고리가 있습니다')
return v
에러 처리
from pydantic import ValidationError
try:
user = User(
name="J", # 최소 길이 위반
age=200, # 최대값 위반
email="invalid-email" # 이메일 형식 위반
)
except ValidationError as e:
print(e.errors())
성능 최적화
Config 클래스 활용
class User(BaseModel):
name: str = Field(...)
age: int = Field(...)
class Config:
validate_assignment = True # 할당 시에도 검증
frozen = True # 불변 객체로 만들기
validate_all = True # 모든 필드 검증
캐시 활용
from functools import lru_cache
@lru_cache
def get_user_model():
return User
마치며
Pydantic의 Field는 데이터 유효성 검사를 매우 직관적이고 강력하게 구현할 수 있게 해줍니다. FastAPI와 함께 사용하면 API의 입력 데이터를 안전하게 처리할 수 있습니다.
'파이썬 > Fast API' 카테고리의 다른 글
[HTTP] 프론트엔드와 백엔드의 데이터 통신 Content-Type (2) | 2025.01.22 |
---|---|
FastAPI : 병렬 처리로 API 성능 최적화 (0) | 2024.12.04 |
FastAPI 애플리케이션 성능 최적화와 캐싱 (0) | 2024.11.28 |
FastAPI 애플리케이션 Docker로 배포하기 (6) | 2024.11.27 |
FastAPI 미들웨어와 CORS 설정 (0) | 2024.11.26 |