에러 처리와 예외 관리
1. FastAPI에서의 에러 처리 소개
웹 애플리케이션 개발에서 에러 처리는 매우 중요합니다. 사용자에게 적절한 에러 메시지를 제공하고, 예상치 못한 상황을 안전하게 처리하는 것은 좋은 사용자 경험을 제공하는 데 필수적입니다. FastAPI는 이러한 에러 처리를 쉽고 효과적으로 할 수 있는 여러 도구를 제공합니다.
2. HTTP 예외 발생시키기
FastAPI에서는 HTTPException
을 사용하여 HTTP 에러를 발생시킬 수 있습니다.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 42:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id == 42:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
이 예제에서는 item_id
가 42일 때 404 Not Found 에러를 발생시킵니다.
3. 커스텀 예외 응답
때로는 더 자세한 에러 정보를 제공하고 싶을 수 있습니다. FastAPI는 이를 위해 HTTPException
에 추가 매개변수를 제공합니다.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/users/{user_id}")
async def read_user(user_id: int):
if user_id < 1:
raise HTTPException(
status_code=400,
detail="User ID must be positive",
headers={"X-Error": "Invalid User ID"},
)
return {"user_id": user_id}
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/users/{user_id}")
async def read_user(user_id: int):
if user_id < 1:
raise HTTPException(
status_code=400,
detail="User ID must be positive",
headers={"X-Error": "Invalid User ID"},
)
return {"user_id": user_id}
이 예제에서는 사용자 ID가 양수가 아닐 때 400 Bad Request 에러를 발생시키고, 추가적인 헤더 정보를 포함시킵니다.
4. 전역 예외 핸들러 사용하기
애플리케이션 전체에서 일관된 방식으로 특정 예외를 처리하고 싶다면, 전역 예외 핸들러를 사용할 수 있습니다.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
class UnicornException(Exception):
def __init__(self, name: str):
self.name = name
@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
)
@app.get("/unicorns/{name}")
async def read_unicorn(name: str):
if name == "yolo":
raise UnicornException(name=name)
return {"unicorn_name": name}
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
class UnicornException(Exception):
def __init__(self, name: str):
self.name = name
@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={"message": f"Oops! {exc.name} did something. There goes a rainbow..."},
)
@app.get("/unicorns/{name}")
async def read_unicorn(name: str):
if name == "yolo":
raise UnicornException(name=name)
return {"unicorn_name": name}
이 예제에서는 커스텀 UnicornException
을 정의하고, 이를 처리하는 전역 예외 핸들러를 등록합니다. 이제 애플리케이션 어디에서든 이 예외가 발생하면 일관된 방식으로 처리됩니다.
5. 유효성 검사 에러 처리
Pydantic 모델을 사용할 때 자동으로 수행되는 유효성 검사 에러도 커스터마이즈할 수 있습니다.
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={"detail": exc.errors(), "message": "Oops! You sent invalid data."},
)
# 이후의 라우트 정의...
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={"detail": exc.errors(), "message": "Oops! You sent invalid data."},
)
# 이후의 라우트 정의...
이 핸들러는 유효성 검사 에러가 발생했을 때 더 친숙한 메시지를 포함한 응답을 반환합니다.
연습문제
-
"items" 리스트가 있다고 가정하고, 존재하지 않는 아이템에 접근하려 할 때 적절한 HTTP 예외를 발생시키는 엔드포인트를 만들어보세요.
-
사용자의 나이를 입력받는 엔드포인트를 만들고, 나이가 0보다 작거나 150보다 큰 경우 커스텀 예외를 발생시켜보세요.
-
애플리케이션에서 발생할 수 있는 모든
ValueError
를 잡아서 500 Internal Server Error로 변환하는 전역 예외 핸들러를 구현해보세요. -
Pydantic 모델을 사용하여 사용자 정보를 입력받는 엔드포인트를 만들고, 유효성 검사 에러 시 사용자 친화적인 메시지를 반환하도록 구현해보세요.