Skip to content

3.6장: 오류 처리 및 유효성 검사

학습 시간: 50분


1. 오류 처리: 우주선의 "비상 방어막"

가장 완벽한 우주선에도 예상치 못한 상황이 발생할 수 있습니다:

  • 관제 센터로부터의 잘못된 명령: 클라이언트가 올바르지 않은 데이터를 보냈습니다.
  • 모듈과의 연결 끊김: 데이터베이스에서 리소스를 찾을 수 없습니다.
  • 반응기 고장: 내부 서버 오류.

올바른 오류 처리는 "비상 방어막" 시스템과 같습니다. 이는 우주선이 무너지지 않도록 하고, 대신 관제 센터에 무엇이 잘못되었는지에 대한 명확한 신호를 보냅니다.

💡 우주 비유:

단순히 관제 센터에 "비상 사태!" 신호를 보내는 대신, 좋은 온보드 컴퓨터는 구조화된 보고서를 보낼 것입니다:

{
  "error_code": "ENGINE_OVERHEAT",
  "message": "2번 엔진 온도가 정상 범위를 초과했습니다.",
  "suggested_action": "냉각 시스템을 시작하십시오."
}
이것은 지구의 엔지니어들이 문제를 빠르게 이해하고 조치를 취할 수 있도록 합니다.


2. Pydantic 유효성 검사: 내장된 "온보드 컴퓨터"

우리는 이미 Pydantic의 마법을 경험했습니다. 잘못된 데이터 타입(예: launch_year를 문자열로)으로 우주선을 생성하려고 하면, FastAPI는 자동으로 422 Unprocessable Entity 오류를 반환하며 어떤 필드가 왜 검증에 실패했는지에 대한 자세한 설명을 제공합니다.

POST /spaceships에 대한 요청 예시:

{
  "name": "X-Wing",
  "type": "이동 전투기",
  "launch_year": "오래전",  // <-- 잘못된 타입!
  "status": "운용 중"
}

FastAPI의 자동 응답:

{
  "detail": [
    {
      "loc": [
        "body",
        "launch_year"
      ],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ]
}
이것은 믿을 수 없을 정도로 강력합니다! 타입 검사를 위한 코드를 작성할 필요가 없습니다. FastAPI와 Pydantic이 당신을 위해 처리합니다.


3. "리소스를 찾을 수 없음" 처리: HTTPException 예외

우리는 CRUD 작업에서 이미 이것을 사용했습니다. HTTPException은 FastAPI가 요청 실행을 중단하고 클라이언트에게 즉시 오류 응답을 반환하는 표준적인 방법입니다.

GET /spaceships/{ship_id}의 코드를 상기해 봅시다:

# main.py
from fastapi import FastAPI, HTTPException # HTTPException이 임포트되었는지 확인하십시오

# ...

@app.get("/spaceships/{ship_id}", response_model=Spaceship, tags=["우주선"])
def get_spaceship(ship_id: int):
    ship = db_spaceships.get(ship_id)
    if not ship:
        # 우주선을 찾을 수 없으면 404 예외를 "발생"시킵니다.
        raise HTTPException(status_code=404, detail=f"ID {ship_id}를 가진 우주선을 찾을 수 없습니다.")
    return ship

  • raise HTTPException(...): 이 호출은 함수 실행을 중단합니다.
  • status_code=404: HTTP 응답 상태를 설정합니다.
  • detail: JSON 응답 본문에 클라이언트에게 전송될 메시지입니다.

4. 커스텀 유효성 검사기: 실행 전 "특별 검사"

만약 우리가 더 복잡한 비즈니스 로직을 추가하고 싶다면 어떨까요? 예를 들어, "Death Star"라는 이름의 우주선 발사를 금지하는 것 말입니다.

이를 위해 Pydantic에는 강력한 도구인 유효성 검사기가 있습니다.

단계 1: SpaceshipCreate 모델에 유효성 검사기 추가

# main.py
from pydantic import BaseModel, Field, validator

class SpaceshipCreate(BaseModel):
    name: str = Field(..., min_length=3, max_length=50)
    type: str
    launch_year: int = Field(..., gt=1950)
    status: str

    @validator('name')
    def name_must_not_be_forbidden(cls, v):
        """우주선 이름이 금지된 목록에 없는지 확인합니다."""
        if 'Death Star' in v:
            raise ValueError(' "Death Star"와 같은 이름은 제국 칙령에 의해 금지되어 있습니다!')
        return v.title() # 동시에 이름을 대문자로 변경합니다.

  • @validator('name'): 이 함수를 name 필드에 "연결"하는 데코레이터입니다.
  • cls, v: 이 메서드는 클래스 자체(cls)와 필드의 값(v)을 받습니다.
  • raise ValueError(...): 검증에 실패하면 우리는 표준 Python 예외를 발생시킵니다. FastAPI는 이를 가로채서 멋진 422 오류로 변환할 것입니다.
  • return v.title(): 모든 것이 좋다면, 우리는 반드시 값을 반환해야 합니다. 심지어 즉석에서 변경할 수도 있습니다(예: 표준 형식으로 변환).

단계 2: 테스트하기 uvicorn을 재시작하고 /docs를 통해 금지된 이름으로 우주선을 생성해 보십시오. 사용자 정의 메시지와 함께 422 오류를 받게 될 것입니다!


5. 전역 오류 처리: 스테이션의 "비상 프로토콜"

때로는 예상치 못한 오류(예: 실제 데이터베이스 연결 실패)를 가로채고 단일하고 표준화된 응답 형식을 반환해야 합니다.

이를 위해 @app.exception_handler 데코레이터가 사용됩니다.

예시: 모든 ValueError 가로채기

# main.py
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

# ...

@app.exception_handler(ValueError)
async def value_error_exception_handler(request: Request, exc: ValueError):
    """
    모든 ValueError에 대한 전역 핸들러입니다.
    표준화된 JSON을 반환하기 위해.
    """
    return JSONResponse(
        status_code=400,
        content={"message": f"데이터 오류: {str(exc)}"},
    )

  • @app.exception_handler(ValueError): FastAPI에게 이 함수가 이전에 가로채지지 않은 모든 ValueError를 처리해야 한다고 알립니다.
  • async def ...: 예외 핸들러는 비동기식(async)이어야 합니다.
  • JSONResponse: 응답 본문과 상태를 완전히 제어할 수 있습니다.

이제 우리의 커스텀 유효성 검사기가 작동하면, 응답은 우리가 정의한 더 친숙한 형식을 가질 것입니다.


복습 퀴즈

1. 클라이언트가 잘못된 타입의 데이터(숫자 대신 문자열)를 보내면 FastAPI는 자동으로 다음 상태를 반환합니다...

2. `raise HTTPException(status_code=404)`는 다음을 위해 사용됩니다...

3. Pydantic의 `@validator('field_name')` 데코레이터는 다음을 위해 필요합니다:

4. 데이터가 올바른 경우 Pydantic의 유효성 검사 함수는 무엇을 해야 합니까?

5. `@app.exception_handler()`는 다음을 허용합니다...


🚀 장 요약:

API 우주선에 강력한 보호 시스템과 비상 프로토콜을 설치했습니다. 이제 다음을 수행할 수 있습니다:

  • 🛡️ Pydantic을 사용하여 "유효하지 않은 데이터" 공격을 자동으로 격퇴합니다.
  • 🚨 HTTPException을 통해 리소스 부재(404 Not Found)를 정확하게 보고합니다.
  • ⚙️ 사용자 지정 유효성 검사기를 사용하여 "특별 검사"를 수행합니다.
  • 🧯 예기치 않은 오류를 전역적으로 가로채고 표준화된 응답을 제공합니다.

귀하의 "초공간 엔진"은 빠를 뿐만 아니라 매우 안정적입니다!

📌 확인:

  • "Death Star"라는 이름으로 우주선을 생성하고 사용자 지정 메시지와 함께 400 오류를 수신하는지 확인하십시오.
  • GET /spaceships/999를 요청하고 404 오류를 수신하는지 확인하십시오.
  • launch_year를 문자열로 포함하는 POST 요청을 보내고 422 오류를 수신하는지 확인하십시오.

⚠️ 오류 발생 시:

  • 필요한 모든 모듈(HTTPException, validator, Request, JSONResponse)이 임포트되었는지 확인하십시오.
  • @validator@app.exception_handler 데코레이터가 오타 없이 작성되었는지 확인하십시오.

3장 완료를 축하드립니다! FastAPI로 강력하고 문서화되어 있으며 안전한 API를 처음부터 구축하고 실행했습니다. 이제 실제 우주 임무를 수행할 준비가 되었습니다