FastAPI에서 Pydantic 모델 검증 에러 커스터마이징

문제 상황

프론트엔드 팀에서 API 에러 응답 형식을 통일해달라는 요청이 들어왔다. Pydantic의 기본 검증 에러는 상세하지만 필드명이나 에러 타입이 그대로 노출되어 사용자에게 보여주기 적합하지 않았다.

# 기본 에러 응답
{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}

해결 방법

@app.exception_handler를 사용해 RequestValidationError를 처리하는 핸들러를 추가했다.

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    errors = {}
    for error in exc.errors():
        field = error['loc'][-1]
        errors[field] = {
            "message": error['msg'],
            "type": error['type']
        }
    
    return JSONResponse(
        status_code=422,
        content={
            "success": False,
            "errors": errors
        }
    )

메시지 매핑

더 나아가 에러 타입별로 한글 메시지를 매핑하는 딕셔너리를 추가했다.

ERROR_MESSAGES = {
    "value_error.email": "올바른 이메일 형식이 아닙니다",
    "value_error.missing": "필수 항목입니다",
    "type_error.integer": "숫자를 입력해주세요"
}

message = ERROR_MESSAGES.get(error['type'], error['msg'])

이렇게 수정한 후 프론트엔드에서 일관된 형식으로 에러를 처리할 수 있게 되었다. FastAPI의 유연한 예외 처리 덕분에 비교적 간단하게 해결할 수 있었다.

FastAPI에서 Pydantic 모델 검증 에러 커스터마이징