FastAPI에서 라우팅 순서로 발생한 ObjectId 오류 해결기

haazz·2025년 4월 19일

FastAPI를 사용하면서 간단한 API 업데이트 작업을 진행하던 중, 예상치 못한 500 Internal Server Error를 마주하게 되었습니다. 로그를 살펴보니 bson.errors.InvalidId 오류가 원인이었습니다. 이 글에서는 해당 문제의 원인과 해결 방법을 공유합니다.


🧩 문제 상황

FastAPI에서 다음과 같은 두 개의 PATCH 메서드를 정의하고 있었습니다.

@app.patch("/news/update/{item_id}")
async def update_news_item(item_id: str):
    ...

@app.patch("/news/update/all")
async def update_all_news_items():
    ...

이 상태에서 /news/update/all로 PATCH 요청을 보내면 다음과 같은 오류가 발생했습니다:

bson.errors.InvalidId: 'all' is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string

❓ 왜 이런 일이 발생했을까?

FastAPI는 라우팅 시 URL 패턴을 위에서부터 아래로 순차적으로 검사합니다. 따라서 /news/update/{item_id}가 먼저 정의되어 있으면, /news/update/all 요청도 {item_id} = 'all'로 인식됩니다. 이 값은 MongoDB의 ObjectId로 변환될 수 없는 문자열이기 때문에 오류가 발생한 것입니다.

즉, FastAPI가 "all"이라는 문자열을 동적으로 받아들일 수 있는 item_id 값으로 착각한 것이죠.


✅ 해결 방법: 라우트 순서 변경

문제는 간단하게 라우트 순서를 변경하는 것만으로 해결할 수 있었습니다.

@app.patch("/news/update/all")
async def update_all_news_items():
    ...

@app.patch("/news/update/{item_id}")
async def update_news_item(item_id: str):
    ...

/news/update/all과 같이 고정된 문자열이 들어가는 경로는, 동적 파라미터 (/{item_id}) 경로보다 먼저 정의해야 FastAPI가 정확하게 매칭할 수 있습니다.


💡 정리

  • FastAPI는 라우트 선언 순서에 따라 URL 경로를 매칭합니다.
  • 고정 경로 (/all)는 가변 경로 (/{item_id})보다 위쪽에 선언해야 합니다.
  • MongoDB ObjectId로 변환할 수 없는 값이 들어오면 bson.errors.InvalidId 예외가 발생합니다.

🧠 배운점

FastAPI처럼 선언형 라우팅을 사용하는 프레임워크에서는 라우팅 순서도 코드의 일부분이라는 사실을 다시 한 번 느낄 수 있었던 경험이었습니다. 앞으로 유사한 API 구조를 설계할 때 고정 경로와 동적 경로의 위치를 더욱 신경 써야겠습니다.

profile
Developers who create benefit social values

0개의 댓글