본문 바로가기

[FastAPI] 예외 응답도 CommonResponse로 처리하는 이유

@Jeeqong 2025. 4. 18. 12:10
반응형

서론

FastAPI에서 예외 응답도 CommonResponse로 처리하는 이유

API 개발을 하다 보면 "예외가 발생했을 때 어떤 형식으로 응답을 내려줘야 할까?" 하는 고민을 많이 하게 된다. FastAPI를 사용하면서 나는 CommonResponse라는 공통 응답 포맷을 도입했고, 처음에는 단순히 성공한 응답에만 적용했었다.

그런데 문제는 예외가 발생했을 때였다. 예외도 결국 응답인데, 이걸 CommonResponse로 감싸야 하나? 그냥 HTTPException처럼 detail만 내려줘도 되는 거 아닌가? 처음엔 나도 헷갈렸다.


본문

😵‍💫 내가 겪은 혼란

예외 처리 코드를 작성하다가 문득 이런 의문이 들었다.

"raise로 예외를 던졌는데, 이게 응답이 되면 성공인가 실패인가?"

raise NotFoundException(message_code=MessageKey.BRAND_NOT_FOUND)

예외를 던졌는데도 FastAPI는 응답을 내려준다.

그럼 이건 클라이언트 입장에서는 성공인 건가? 실패인 건가?

CommonResponse.success(...)는 쓰지 않았지만, 응답은 왔으니까 혼란이 생겼다.


🤖 구조를 다시 정의하다

결국 깨달았다.

예외는 실패다.

그리고 예외도 결국 응답이기 때문에, 클라이언트가 구조를 파악할 수 있도록 일관된 형태로 내려줘야 한다.

그래서 모든 예외 응답도 CommonResponse 구조로 내려주기로 했다.


예외 발생 흐름 예시

# 서비스 로직
if not brand:
    raise NotFoundException(message_code=MessageKey.BRAND_NOT_FOUND)
# 예외 핸들러
async def app_exception_handler(request: Request, exc: AppException):
    return JSONResponse(
        status_code=exc.status_code,
        content=CommonResponse[None](
            success=False,
            message=exc.message,
            data=None
        ).model_dump()
    )

 핵심은 CommonResponse를 경유해서 응답 구조를 통일한다는 것.

이걸 통해 클라이언트에서는 응답 구조만 보고도 성공/실패 여부를 일관되게 판단할 수 있다.


 응답 예시 비교

성공 응답

{
  "success": true,
  "message": "✅ 브랜드가 생성되었습니다.",
  "data": {
    "id": 123
  }
}

실패 (비즈니스 거절)

{
  "success": false,
  "message": "❌ 이미 존재하는 브랜드입니다.",
  "data": null
}

예외 (서버 측 문제)

json
복사편집
{
  "success": false,
  "message": "❌ 브랜드를 찾을 수 없습니다.",
  "data": null
}

 깨달음: 예외도 결국 응답이다

API에서 클라이언트가 받는 건 무조건 "응답"이다.

예외든 성공이든, 그 응답이 일관된 구조로 되어 있어야

  • 프론트엔드에서도 처리하기 편하고
  • 테스트 자동화도 쉬워지고
  • 사용자에게 보여주는 메시지도 예쁘게 만들 수 있다.

마치며

오늘 나는 FastAPI에서

  • 공통 응답 구조 CommonResponse
  • 예외 핸들링 흐름
  • success: true / false의 의미
  • 이걸 완전히 머리에 박았다.

한층 더 성장한 것 같다.

❗ 예외도 결국 응답이다.

❗ 응답은 통일된 구조여야 한다.

❗ 그래서 CommonResponse는 성공뿐 아니라 예외도 감싸야한다.

이 경험을 통해 API 설계에 대해 한층 더 성장했다.

“리팩토링 지옥이다”

반응형
Jeeqong
@Jeeqong :: JQVAULT

Jeeqong's vault : 정보/기록을 쌓아두는 공간 웹개발 포스팅 일상 리뷰를 기록하는 공간입니다.

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차