이 글에선느 다음 네가지 핵심 기능을 중심으로 FastAPI + Pydantic v2 조합을 정리
@field_validator@model_validator@field_serializer@model_serializerproject/
├── main.py
├── schemas.py
├── services.py
└── requirements.txt
from pydantic import BaseModel, Field, model_validator, field_validator, model_serializer
class UserCreate(BaseModel):
name: str = Field(default="익명", max_length=20)
password: str = Field(..., min_length=4)
@model_validator(mode="before")
@classmethod
def set_default_name(cls, values):
values.setdefault("name", "익명")
return values
@model_validator(mode="after")
def check_password(self):
if len(self.password) < 4:
raise ValueError("비밀번호는 4자 이상이어야 합니다")
return self
class UserResponse(BaseModel):
id: int
name: str
@model_serializer
def serialize(self):
return {
"id": self.id,
"name": self.name.upper()
}
from schemas import UserCreate, UserResponse
# 임시 DB 대용
_fake_db = []
def create_user(user_data: UserCreate) -> UserResponse:
new_id = len(_fake_db) + 1
new_user = {"id": new_id, "name": user_data.name, "password": user_data.password}
_fake_db.append(new_user)
return UserResponse(id=new_id, name=user_data.name)
def get_user_by_id(user_id: int) -> UserResponse:
user = next((u for u in _fake_db if u["id"] == user_id), None)
if not user:
raise ValueError("사용자를 찾을 수 없습니다")
return UserResponse(id=user["id"], name=user["name"])
from fastapi import FastAPI, HTTPException
from pydantic import ValidationError
from schemas import UserCreate
from services import create_user, get_user_by_id
app = FastAPI()
@app.post("/users")
def create_user_api(user: UserCreate):
try:
result = create_user(user)
return result
except ValidationError as e:
raise HTTPException(status_code=400, detail=e.errors())
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
@app.get("/users/{user_id}")
def get_user_api(user_id: int):
try:
result = get_user_by_id(user_id)
return result
except ValueError as e:
raise HTTPException(status_code=404, detail=str(e))
POST /users → UserCreate로 검증
UserCreate 모델로 입력 값 검증
↳ model_validator로 기본값 설정 및 비밀번호 검증
서비스 로직에서 임시 DB 저장
UserResponse 모델로 직렬화
↳ model_serializer에서 name을 대문자로 변환
model_dump_json()으로 JSON 응답 반환
GET /users/{id}
임시 DB에서 사용자 정보 조회
UserResponse 모델로 직렬화
model_dump_json()으로 JSON 응답 반환
요청
{
"name": "lee",
"password": "1234"
}
응답
{
"id": 1,
"name": "LEE"
}
응답
{
"id": 1,
"name": "LEE"
}
검증 실패 시
요청
{
"name": "min",
"password": "12"
}
응답
{
"detail": [
{
"type": "value_error",
"msg": "비밀번호는 4자 이상이어야 합니다",
"loc": ["password"]
}
]
}