3.6장: 오류 처리 및 유효성 검사
학습 시간: 50분
1. 오류 처리: 우주선의 "비상 방어막"
가장 완벽한 우주선에도 예상치 못한 상황이 발생할 수 있습니다:
- 관제 센터로부터의 잘못된 명령: 클라이언트가 올바르지 않은 데이터를 보냈습니다.
- 모듈과의 연결 끊김: 데이터베이스에서 리소스를 찾을 수 없습니다.
- 반응기 고장: 내부 서버 오류.
올바른 오류 처리는 "비상 방어막" 시스템과 같습니다. 이는 우주선이 무너지지 않도록 하고, 대신 관제 센터에 무엇이 잘못되었는지에 대한 명확한 신호를 보냅니다.
💡 우주 비유:
단순히 관제 센터에 "비상 사태!" 신호를 보내는 대신, 좋은 온보드 컴퓨터는 구조화된 보고서를 보낼 것입니다:
이것은 지구의 엔지니어들이 문제를 빠르게 이해하고 조치를 취할 수 있도록 합니다.
2. Pydantic 유효성 검사: 내장된 "온보드 컴퓨터"
우리는 이미 Pydantic의 마법을 경험했습니다. 잘못된 데이터 타입(예: launch_year
를 문자열로)으로 우주선을 생성하려고 하면, FastAPI는 자동으로 422 Unprocessable Entity
오류를 반환하며 어떤 필드가 왜 검증에 실패했는지에 대한 자세한 설명을 제공합니다.
POST /spaceships
에 대한 요청 예시:
FastAPI의 자동 응답:
{
"detail": [
{
"loc": [
"body",
"launch_year"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
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
: 응답 본문과 상태를 완전히 제어할 수 있습니다.
이제 우리의 커스텀 유효성 검사기가 작동하면, 응답은 우리가 정의한 더 친숙한 형식을 가질 것입니다.
복습 퀴즈
🚀 장 요약:
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를 처음부터 구축하고 실행했습니다. 이제 실제 우주 임무를 수행할 준비가 되었습니다