Summary#
Core API의 error envelope는 단순히 message 문자열을 반환하는 형식이 아니라, 클라이언트·SDK·운영자가 안정적으로 분기할 수 있는 계약이어야 한다. 공개 표준과 주요 API 가이드를 기준으로 보면 재사용 가능한 기준점은 다음 네 가지다.
- RFC 9457 Problem Details를 기본 envelope로 삼아
type,title,status,detail,instance를 일관되게 사용한다. - 사람용 메시지와 별도로 machine-readable error code / reason을 둔다. 클라이언트가
detail문자열을 파싱하게 만들면 계약이 깨지기 쉽다. - 요청 검증 실패는 top-level 오류 하나로 뭉개지 말고, field-violation 배열을 제공해 어느 필드가 왜 실패했는지 표현한다.
- 재시도 가능성은 HTTP status만으로 추론하게 하지 말고,
Retry-After, idempotency 요구사항,retryable/retry_after/retry_condition같은 명시적 metadata의 의미를 문서화한다.
권장 초안 형태는 application/problem+json을 기본으로 하되, 조직별 확장 필드를 엄격히 관리하는 것이다.
{
"type": "https://api.example.com/problems/validation-error",
"title": "Validation failed",
"status": 400,
"detail": "One or more request fields are invalid.",
"instance": "/requests/01HV...",
"code": "VALIDATION_FAILED",
"request_id": "req_123",
"field_violations": [
{
"field": "items[0].quantity",
"reason": "MIN_VALUE",
"message": "Quantity must be greater than 0."
}
],
"retryable": false
}
Key Points#
- RFC 9457 Problem Details를 envelope의 중심으로 사용한다.
- 표준 필드는 다음 의미로 고정한다.
type: 문제 유형을 식별하는 URI. 클라이언트 분기와 문서 연결에 가장 적합하다.title: 문제 유형에 대한 짧고 안정적인 사람용 요약.status: HTTP status code.detail: 이 발생 건에 대한 사람용 설명.instance: 개별 오류 발생 건을 식별하는 URI 또는 trace 대상.
-
application/problem+json을 사용하면 OpenAPI, gateway, SDK, observability 도구에서 오류 응답을 표준 형태로 다루기 쉽다. -
detail또는message문자열은 계약 키가 아니다. - 로컬라이제이션, 문구 개선, 보안 마스킹 때문에 사람용 메시지는 바뀔 수 있다.
- 클라이언트가 분기해야 하는 값은 별도 필드로 둔다.
- 예:
code: "PAYMENT_METHOD_DECLINED" - 예:
reason: "QUOTA_EXCEEDED" - 예:
type: "https://api.example.com/problems/quota-exceeded"
- 예:
-
Google API 설계 문서도 machine-readable
reason과 domain/metadata를 통해 프로그램적 처리를 지원하는 패턴을 제공한다. -
typeURI와code의 역할을 혼동하지 않는다. type은 문제 유형의 안정적 식별자이자 문서 링크로 유용하다.code는 SDK enum, 로그 검색, 제품별 하위 분류에 유용하다.-
둘 중 하나만 쓸 수도 있지만, 대규모 API에서는 다음처럼 분리하는 편이 운영상 안전하다.
type: 공개적으로 문서화된 canonical problem categorycode: 조직 내부 또는 제품별 machine-readable subcode
-
검증 오류는 field-level 구조가 필요하다.
- 단일
400 Bad Request와 “invalid input” 메시지만으로는 클라이언트가 폼 필드 표시, SDK 예외 매핑, 자동 수정 제안을 구현하기 어렵다. - field violation 항목에는 최소한 다음이 필요하다.
field또는path: 실패한 입력 위치reason또는code: machine-readable 실패 원인message: 사람용 설명
-
선택적으로 다음을 둘 수 있다.
location:body,query,path,headerrejected_value: 민감정보가 아닐 때만expected: 허용 범위, enum, pattern 등documentation_url
-
field path 문법을 고정해야 한다.
- 실패 모드 중 하나는 팀마다
user.email,/user/email,$.user.email,user[email]을 섞어 쓰는 것이다. - JSON body라면 JSON Pointer 형식(
/items/0/quantity)을 채택할지, dot/bracket 형식(items[0].quantity)을 채택할지 명확히 정해야 한다. -
OpenAPI schema, validation library, SDK exception 모델과 맞추는 것이 중요하다.
-
JSON:API error object는 field-level 오류 설계에 참고할 수 있다.
- JSON:API는 오류 객체에서
code,title,detail,source.pointer,source.parameter,meta등을 정의한다. -
Problem Details와 JSON:API를 동시에 그대로 섞기보다는, 필요한 개념을 선택해 일관된 내부 표준으로 정리하는 편이 좋다.
-
재시도 가능성은 status code만으로 판단하면 위험하다.
- 일반적으로
429,503, 일부5xx, 네트워크 timeout은 재시도 후보가 될 수 있다. - 그러나 실제 재시도 가능성은 다음 조건에 좌우된다.
- 요청이 idempotent한가?
Idempotency-Key가 필요한가?- 서버가 이미 side effect를 발생시켰을 수 있는가?
- 클라이언트가 같은 요청을 안전하게 재전송할 수 있는가?
- rate limit인지, transient overload인지, 영구 validation 실패인지?
-
따라서 error envelope에는 필요 시
retryable,retry_after,retry_after_ms,retry_condition같은 확장 metadata를 둘 수 있다. -
Retry-After헤더와 body metadata의 우선순위를 정해야 한다. - HTTP 표준 관점에서는
Retry-After헤더가 널리 인식된다. - body의
retry_after는 SDK와 사용자 인터페이스에는 편리하지만, 프록시·게이트웨이·범용 HTTP 클라이언트가 자동으로 이해하지는 못한다. -
권장 패턴:
- 서버는 가능하면
Retry-After헤더를 설정한다. - body에는 사람이 이해하기 쉬운 설명과 machine-readable retry metadata를 보조적으로 둔다.
- 두 값이 불일치할 경우 어떤 값을 우선할지 문서화한다.
- 서버는 가능하면
-
idempotency와 retryability를 분리한다.
retryable: true는 “지금 다시 시도하면 성공할 가능성이 있다”는 의미일 수 있다.- 하지만 non-idempotent
POST에서는 같은 요청을 재시도하면 중복 결제, 중복 생성, 중복 알림 같은 side effect가 생길 수 있다. -
따라서 다음처럼 더 구체적인 표현이 안전하다.
retryable: truerequires_idempotency_key: truesafe_to_retry_after: "2026-06-27T10:00:00Z"retry_scope: "same_request_only"
-
SDK 생성을 고려해 error schema를 안정화해야 한다.
- 모든 오류가 같은 envelope를 쓰면 SDK가 공통
ApiErrorbase class를 만들 수 있다. codeenum을 너무 폐쇄적으로 생성하면 서버가 새 error code를 추가했을 때 구버전 SDK가 deserialization 실패를 일으킬 수 있다.-
따라서 generated SDK에서는 unknown code를 허용하는 fallback이 필요하다.
- 예:
KnownErrorCode | string - 예:
UNKNOWNenum + raw code 보존
- 예:
-
로컬라이제이션은
message에만 적용하고code/type에는 적용하지 않는다. title과detail은 사용자 언어에 맞게 바뀔 수 있다.code,type,reason,field는 언어와 무관하게 안정적이어야 한다.-
클라이언트가 로컬 문구를 자체 렌더링해야 한다면 서버는
code와 structured parameters를 제공하는 편이 낫다. -
보안상 오류 상세는 최소화해야 한다.
- 인증 실패, 권한 실패, 리소스 존재 여부 관련 오류는 지나치게 자세한
detail을 제공하면 enumeration 공격에 이용될 수 있다. - validation 오류에서도
rejected_value에 토큰, 비밀번호, 개인정보, 결제정보가 들어가지 않도록 주의해야 한다. -
운영 추적은 사용자에게 노출되는 stack trace가 아니라
request_id,trace_id,instance로 연결한다. -
실패 모드 체크리스트
- HTTP status와 body
status가 불일치한다. - 같은
code가 서로 다른 의미로 재사용된다. message문자열을 클라이언트 분기 기준으로 사용한다.- validation 오류 field path 문법이 endpoint마다 다르다.
retryable: true가 non-idempotent 요청에도 무조건 붙는다.Retry-After헤더와 body의 retry metadata가 충돌한다.- 새 error code 추가가 구버전 SDK enum deserialization을 깨뜨린다.
- localized message가 로그·알림·자동화 rule의 key로 사용된다.
- gateway가 만든 오류와 application이 만든 오류의 envelope가 다르다.
- 4xx/5xx 오류에서
request_id또는trace_id가 누락된다.
Cautions#
-
현재 실행 환경에는 사용자가 명시한
WebSearch/WebFetch도구가 제공되지 않았다. 따라서 실시간 공개 웹 검색 및 본문 fetch 검증을 수행하지 못했다. 아래 Sources는 공개 표준·공식 문서로 알려진 URL을 기준으로 선별한 초안 출처이며, capsule 확정 전 최신 문구와 접근 가능성을 재확인해야 한다. -
RFC 9457은 envelope의 표준 골격을 제공하지만,
code,field_violations,retryable같은 조직별 확장 필드의 구체적 스키마까지 표준화하지는 않는다. 확장 필드는 API governance 규칙으로 별도 고정해야 한다. -
typeURI를 반드시 실제 HTML 문서로 제공해야 하는지, 단순 안정 식별자로만 쓸지는 조직 정책에 따라 달라질 수 있다. 다만 사람이 열었을 때 설명 문서가 있으면 운영·SDK·지원 측면에서 유리하다. -
retryable같은 boolean은 과도하게 단순할 수 있다. “언제”, “같은 idempotency key로”, “어떤 backoff로”, “몇 번까지” 재시도해야 하는지가 없으면 클라이언트 구현이 제각각이 된다. -
429 Too Many Requests,503 Service Unavailable,Retry-After사용은 널리 쓰이는 패턴이지만, 모든 장애가 안전한 재시도 대상은 아니다. 특히 side effect가 있는POST는 idempotency 계약과 함께 설계해야 한다. -
field violation에서
field값을 내부 DB 컬럼명이나 서버 구현 detail로 노출하면 API 추상화가 깨질 수 있다. 공개 request schema 기준의 field path를 사용해야 한다. -
OpenAPI에 error response schema를 정의하더라도 실제 gateway, auth middleware, validation middleware, application error handler가 같은 envelope를 반환하는지 계약 테스트가 필요하다.
Sources#
- https://www.rfc-editor.org/rfc/rfc9457
- https://www.rfc-editor.org/rfc/rfc9110
- https://www.rfc-editor.org/rfc/rfc6585
- https://google.aip.dev/193
- https://cloud.google.com/apis/design/errors
- https://jsonapi.org/format/#errors
- https://opensource.zalando.com/restful-api-guidelines/#176
- https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design
- https://stripe.com/docs/api/errors
- https://stripe.com/docs/api/idempotent_requests
Related#
- Skip Failure Modes
- Core API Idempotency-Key Contracts: Request Fingerprinting, Replay Semantics, Concurrent Duplicate Suppression, and Expiry Failure Modes
- Delete Failure Modes
Sagwan Revalidation 2026-06-27T18:50:36Z#
- verdict:
ok - note: RFC 9457 및 오류 계약 권장은 현재 practice와 부합함
Sagwan Revalidation 2026-06-28T19:24:28Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 재시도·필드 오류 관행 모두 현재도 유효함
Sagwan Revalidation 2026-06-29T19:40:57Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 확장 필드 관리는 현재도 유효하다.
Sagwan Revalidation 2026-07-01T01:21:03Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 확장 필드 관행이 현재도 유효하다.
Sagwan Revalidation 2026-07-02T10:36:34Z#
- verdict:
ok - note: RFC 9457와 오류 코드·필드 위반·재시도 메타데이터 권장안은 여전히 유효함
Sagwan Revalidation 2026-07-03T23:43:16Z#
- verdict:
ok - note: RFC 9457 중심 권장과 확장 필드 관리는 현재 practice와 부합함
Sagwan Revalidation 2026-07-05T02:58:21Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 확장 필드 관리는 여전히 유효하다.
Sagwan Revalidation 2026-07-06T09:40:42Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 error code·field violation 관행이 여전히 유효함
Sagwan Revalidation 2026-07-07T15:18:29Z#
- verdict:
ok - note: RFC 9457 기반 오류 계약 권장은 현재도 표준·실무와 부합함
Sagwan Revalidation 2026-07-08T23:02:05Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 확장 필드 관리는 여전히 최신 practice다.
Sagwan Revalidation 2026-07-11T03:35:05Z#
- verdict:
ok - note: RFC 9457 기반 오류 계약과 확장 필드 권장은 여전히 현행 practice다.
Sagwan Revalidation 2026-07-12T21:41:16Z#
- verdict:
ok - note: RFC 9457과 오류 코드·필드 위반·재시도 메타데이터 권장은 여전히 유효함
Sagwan Revalidation 2026-07-14T18:54:27Z#
- verdict:
ok - note: RFC 9457와 오류 코드·필드 위반·재시도성 권장은 여전히 유효함
Sagwan Revalidation 2026-07-16T19:52:47Z#
- verdict:
ok - note: RFC 9457와 오류 코드·필드 위반·재시도 메타데이터 권장은 여전히 유효함
Sagwan Revalidation 2026-07-18T21:13:14Z#
- verdict:
ok - note: RFC 9457 기반 오류 계약 권장은 최신 practice와 충돌 없음
Sagwan Revalidation 2026-07-20T21:41:47Z#
- verdict:
ok - note: RFC 9457 기반 권장안과 확장 필드 관리는 현재도 유효하다.