Skip to content

Latest commit

 

History

History
132 lines (105 loc) · 5.37 KB

File metadata and controls

132 lines (105 loc) · 5.37 KB

공통 API 응답과 전역 예외 처리 계약

상태: 구현 완료

이 문서는 곌린더 API의 JSON 성공·오류 응답 형식과 전역 예외 처리 규칙을 정의한다. /docs, /openapi.json과 body가 없는 204 No Content 응답은 envelope 대상이 아니다.

성공 응답

JSON body가 있는 모든 정상 응답은 다음 구조를 사용한다.

{
  "success": true,
  "data": {
    "id": "6b6e46da-65db-4b06-acbc-ecf4283fb03d"
  },
  "error": null
}
  • success는 항상 true다.
  • data에는 기존 endpoint의 실제 응답 객체, 배열 또는 상태값이 들어간다.
  • error는 항상 null이다.
  • 목록이 비어 있으면 data[]다. 성공 응답의 datanull로 사용하지 않는다.
  • 과제 삭제 성공은 204 No Content와 빈 body를 유지한다.

오류 응답

처리 가능한 모든 API 오류는 다음 구조를 사용한다.

{
  "success": false,
  "data": null,
  "error": {
    "code": "ASSIGNMENT_NOT_FOUND",
    "message": "과제를 찾을 수 없습니다.",
    "details": null
  }
}
  • success는 항상 false다.
  • data는 항상 null이다.
  • error.code는 클라이언트 분기용 안정적인 영문 대문자 code다.
  • error.message는 사용자에게 표시 가능한 한국어 설명이다.
  • error.details는 입력 검증 오류에만 배열이며 그 외에는 null이다.
  • stack trace, SQL, 비밀번호, JWT, 요청 body는 응답과 로그에 포함하지 않는다.

입력 검증 오류

FastAPI/Pydantic 검증 실패는 422 VALIDATION_ERROR로 변환한다.

{
  "success": false,
  "data": null,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "요청 값이 올바르지 않습니다.",
    "details": [
      {
        "field": "body.studentNumber",
        "message": "String should match pattern '^[0-9]{5}$'",
        "type": "string_pattern_mismatch"
      }
    ]
  }
}

검증 detail은 field, message, type만 제공한다. Pydantic의 입력 원문과 내부 context는 노출하지 않는다.

전역 예외 변환

발생 예외 HTTP 상태 기본 code 처리 규칙
명시적 HTTPException 원래 상태 유지 예외에 지정된 code 기존 code·message와 header 보존
라우팅 404 404 NOT_FOUND 존재하지 않는 API 경로
허용되지 않은 method 405 METHOD_NOT_ALLOWED framework 오류를 공통 형식으로 변환
RequestValidationError 422 VALIDATION_ERROR 안전한 field detail만 반환
SQLAlchemyError 503 DATABASE_UNAVAILABLE 내부 오류를 기록하고 DB 정보는 숨김
그 외 처리되지 않은 예외 500 INTERNAL_SERVER_ERROR 내부 오류를 기록하고 고정 메시지 반환

인증 오류의 WWW-Authenticate: Bearer처럼 기존 HTTP header가 있으면 전역 handler가 그대로 전달한다.

기존 업무 오류 code

Code 상태 의미
EMAIL_ALREADY_EXISTS 409 이미 사용 중인 이메일
INVALID_CREDENTIALS 401 로그인 정보 불일치
INVALID_TOKEN 401 token 없음, 위조, 만료 또는 사용자 없음
ASSIGNMENT_NOT_FOUND 404 과제가 없거나 현재 사용자 소유가 아님
INVALID_IMAGE 400 지원하지 않거나 제한을 초과한 이미지
AI_RATE_LIMITED 429 사진 분석 호출 또는 외부 사용량 제한 도달
AI_EXTRACTION_FAILED 502 외부 사진 분석 실패 또는 유효한 구조화 결과 없음
AI_EXTRACTION_DISABLED 503 사진 분석 기능 비활성화 또는 API key 미설정

업무 오류를 새로 추가할 때 endpoint에서는 HTTPExceptioncodemessage만 지정하고, JSON envelope 생성은 전역 handler에 맡긴다.

구현 경계

  • app/responses.py: 성공·오류 Pydantic model과 성공 helper
  • app/exceptions.py: HTTP, 검증, DB, 미처리 예외 handler와 등록 함수
  • app/main.py: handler를 애플리케이션에 한 번 등록
  • 기존 router: 성공 response model을 공통 generic envelope로 변경

middleware로 응답 body를 사후 변환하지 않는다. endpoint의 response_model 자체가 실제 envelope를 표현해야 OpenAPI와 런타임 응답이 일치한다.

테스트 시나리오

시나리오 기대 결과
가입·로그인·과제·대시보드 성공 success=true, 실제 값은 data, error=null
빈 과제 목록 data=[]
과제 삭제 204, 빈 body
잘못된 입력 422 VALIDATION_ERROR, 안전한 details
기존 인증·업무 오류 기존 HTTP 상태와 code 유지
존재하지 않는 경로 404 NOT_FOUND 공통 오류 응답
DB 예외 503 DATABASE_UNAVAILABLE, SQL 미노출
예상하지 못한 예외 500 INTERNAL_SERVER_ERROR, 내부 메시지 미노출
OpenAPI 성공 endpoint가 ApiResponse[...] schema를 표시

완료 조건

  • JSON body를 반환하는 모든 현재 endpoint가 성공 envelope를 사용한다.
  • framework와 애플리케이션 오류가 공통 오류 envelope를 사용한다.
  • 인증 header와 업무 오류 code가 보존된다.
  • validation 응답에 요청 입력 원문이 포함되지 않는다.
  • 204와 OpenAPI 문서 endpoint가 불필요하게 감싸지지 않는다.
  • make checkgit diff --check가 성공한다.