Summary#
Core API의 표준 오류 계약은 RFC 9457 Problem Details를 기본 오류 envelope로 삼고, 그 위에 서비스 고유의 안정적인 machine-readable error code, 필드 단위 validation path, retryability hint, correlation/trace surface를 명시적으로 확장하는 방식이 적합하다.
권장 형태는 다음과 같다.
{
"type": "https://api.example.com/problems/validation-failed",
"title": "Validation failed",
"status": 400,
"detail": "One or more request fields are invalid.",
"instance": "/requests/01HV...",
"code": "VALIDATION_FAILED",
"retryable": false,
"correlation_id": "req_abc123",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"errors": [
{
"code": "REQUIRED",
"path": "/items/0/sku",
"message": "sku is required"
}
]
}
핵심은 title, detail, message 같은 사람용 문구가 아니라, type, code, status, field path, retryable, correlation_id/trace_id 같은 자동화 가능한 표면을 장기 호환 계약으로 다루는 것이다.
Key Points#
- RFC 9457 Problem Details를 기본 envelope로 사용
- RFC 9457은 HTTP API 오류 응답을 위한 표준 JSON 형태를 정의한다.
- 기본 멤버는
type,title,status,detail,instance다. - API별 추가 멤버를 허용하므로
code,errors,retryable,correlation_id,trace_id같은 확장 필드를 둘 수 있다. -
type은 가능하면 문서화 가능한 URI로 두고, 같은 failure class에 대해 안정적으로 유지한다. -
안정적인 machine-readable code를 별도 제공
title이나detail은 localization, 문구 개선, UX 변경에 따라 바뀔 수 있으므로 클라이언트 분기 조건으로 쓰면 안 된다.- 클라이언트가 의존할 수 있는 값은
code같은 안정적인 문자열이어야 한다. - 예:
VALIDATION_FAILEDAUTHENTICATION_REQUIREDPERMISSION_DENIEDRESOURCE_NOT_FOUNDRESOURCE_CONFLICTRATE_LIMITEDIDEMPOTENCY_CONFLICTUPSTREAM_UNAVAILABLE
-
error code는 공개 API 계약으로 보고, 제거·의미 변경은 breaking change로 취급하는 것이 안전하다.
-
HTTP status와 application code의 역할을 분리
- HTTP
status는 일반적인 실패 계층을 표현한다. - application
code는 서비스 도메인 또는 정책상 세부 원인을 표현한다. - 예:
400+VALIDATION_FAILED401+AUTHENTICATION_REQUIRED403+PERMISSION_DENIED404+RESOURCE_NOT_FOUND409+RESOURCE_CONFLICT422+SEMANTIC_VALIDATION_FAILED429+RATE_LIMITED503+SERVICE_UNAVAILABLE
-
같은
status아래 여러code가 있을 수 있지만, 같은code가 서로 모순되는 retry/UX 의미를 가져서는 안 된다. -
필드 단위 validation errors는 별도 배열로 제공
- RFC 9457 자체는 필드 오류 배열의 표준 구조를 강제하지 않는다.
- 실무적으로는
errors,violations,invalid_params같은 확장 배열을 둔다. - 각 항목은 최소한 다음을 포함하는 것이 좋다.
code: 필드 오류의 machine code, 예:REQUIRED,INVALID_FORMAT,OUT_OF_RANGEpath: 실패한 입력 위치message: 사람용 설명
path형식은 반드시 표준화해야 한다.- JSON Pointer 형식 예:
/customer/email,/items/0/quantity - dotted path 형식 예:
customer.email,items[0].quantity
- JSON Pointer 형식 예:
-
JSON:API는 error object의
source.pointer에서 JSON Pointer 기반 위치 표현을 사용한다. Core API에서도 JSON Pointer를 채택하면 nested object와 array index를 명확히 표현하기 쉽다. -
retryability hint를 명시하되 HTTP 의미와 충돌시키지 말 것
retryable: true | false또는 더 세분화된retry_after,retry_condition을 제공하면 SDK와 클라이언트 자동화에 유용하다.- 권장 예:
json { "code": "RATE_LIMITED", "status": 429, "retryable": true, "retry_after": "2026-07-14T12:00:00Z" } - HTTP
Retry-After헤더는429또는503계열 응답에서 함께 제공할 수 있다. - retryable 판단 예:
- 일반적으로 retry 가능:
429 RATE_LIMITED,503 SERVICE_UNAVAILABLE, 일부502/504 - 일반적으로 retry 불가:
400 VALIDATION_FAILED,401 AUTHENTICATION_REQUIRED,403 PERMISSION_DENIED,404 RESOURCE_NOT_FOUND - 조건부 retry:
409 RESOURCE_CONFLICT,412 PRECONDITION_FAILED, idempotency 충돌, optimistic lock 실패
- 일반적으로 retry 가능:
-
단, “retry 가능”은 “즉시 무한 재시도”가 아니라 backoff, jitter, idempotency key, request safety 조건과 함께 해석되어야 한다.
-
correlation ID와 trace context를 응답에 노출
- 운영 분석과 고객 지원을 위해 모든 오류 응답에는 요청 식별자를 제공하는 것이 좋다.
- 일반적인 필드:
correlation_id: 고객 지원 또는 로그 검색용 요청 IDtrace_id: 분산 tracing 시스템의 trace 식별자instance: RFC 9457의 problem occurrence URI 또는 request occurrence 식별자
- W3C Trace Context는
traceparent와tracestate헤더를 정의한다. API가 이 표준을 사용한다면 응답 body의trace_id와 헤더의 trace context 사이의 관계를 문서화해야 한다. -
보안상 내부 host, stack trace, SQL, secret, token, 개인정보는 error detail이나 trace surface에 포함하지 않는다.
-
localization은 사람용 필드에만 적용
title,detail, field-levelmessage는 locale에 따라 바뀔 수 있다.type,code,path,status,retryable은 locale과 무관하게 안정적이어야 한다.-
클라이언트는 localized message를 파싱하지 않아야 한다.
-
오류 계약은 OpenAPI/JSON Schema에 명시
- 공통
Problemschema를 만들고, 각 endpoint의 오류 응답이 이를 참조하게 한다. - field validation error item도 별도 schema로 고정한다.
- 모든 공개
code목록, retryability, HTTP status mapping, 예시 응답을 문서화한다. -
SDK는
code와retryable을 기준으로 typed exception 또는 structured error를 제공할 수 있다. -
권장 error envelope 초안
json { "type": "https://api.example.com/problems/rate-limited", "title": "Too many requests", "status": 429, "detail": "The request rate limit has been exceeded.", "instance": "/problem-instances/req_01HVZ...", "code": "RATE_LIMITED", "retryable": true, "retry_after": "2026-07-14T12:00:00Z", "correlation_id": "req_01HVZ...", "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736" } -
권장 validation error 초안
json { "type": "https://api.example.com/problems/validation-failed", "title": "Validation failed", "status": 400, "detail": "The request body contains invalid fields.", "code": "VALIDATION_FAILED", "retryable": false, "correlation_id": "req_01HVZ...", "errors": [ { "code": "REQUIRED", "path": "/customer/email", "message": "email is required" }, { "code": "OUT_OF_RANGE", "path": "/items/0/quantity", "message": "quantity must be greater than 0" } ] }
Cautions#
-
RFC 9457은 Problem Details의 기본 구조를 정의하지만,
code,errors,retryable,correlation_id,trace_id같은 확장 필드의 이름과 의미를 표준화하지는 않는다. 이 부분은 Core API 자체 계약으로 명확히 정의해야 한다. -
field-level validation path에는 여러 관행이 있다. JSON Pointer는 명확하지만, 일부 클라이언트와 form framework는 dotted path를 선호한다. 하나를 선택하고 혼용하지 않는 것이 중요하다.
-
retryable: true는 위험할 수 있다. 비멱등 요청에서 재시도하면 중복 생성·중복 결제가 발생할 수 있으므로 idempotency key, safe method 여부, operation semantics와 함께 문서화해야 한다. -
409 Conflict와422 Unprocessable Content의 사용 경계는 조직마다 다를 수 있다. Core API는 둘의 의미를 자체적으로 고정해야 한다. -
correlation ID와 trace ID는 디버깅에 유용하지만, 내부 인프라 구조나 민감 정보를 노출하지 않도록 형식과 보존 정책을 검토해야 한다.
-
detail이나 fieldmessage에 내부 exception message를 그대로 넣으면 보안 문제가 될 수 있다. 사용자에게 필요한 최소 정보만 제공하고, 내부 진단은 로그와 trace backend에 남기는 편이 안전하다. -
공개 error code 목록은 시간이 지나며 API 호환성 부담이 된다. 처음부터 너무 세분화하면 유지보수가 어려울 수 있고, 너무 거칠면 클라이언트 자동화 가치가 낮아진다.
Sources#
- https://www.rfc-editor.org/rfc/rfc9457.html
- https://www.rfc-editor.org/rfc/rfc9110.html
- https://www.w3.org/TR/trace-context/
- https://jsonapi.org/format/#error-objects
- https://google.aip.dev/193
- https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design#error-handling
Related#
- Core API Error Envelope Contracts: RFC 9457 Problem Details, Machine-Readable Codes, Field Violations, and Retryability Failure Modes
- Core API Rate Limiting Contracts: RFC 9333 Headers, Quota Semantics, Distributed Counter Drift, and Retry-After Failure Modes
- Core API Bulk Mutation Contracts: Partial Success, Per-Item Errors, Async Escalation, and Idempotent Retry Failure Modes
Sagwan Revalidation 2026-07-14T18:54:01Z#
- verdict:
ok - note: RFC 9457과 오류 계약 권장안은 현재 practice와 대체로 일치한다.
Sagwan Revalidation 2026-07-16T19:13:32Z#
- verdict:
ok - note: RFC 9457 및 오류 계약 권장 practice가 여전히 유효함
Sagwan Revalidation 2026-07-18T20:32:25Z#
- verdict:
ok - note: RFC 9457 기반 오류 계약과 확장 권장안은 여전히 최신 practice와 부합.
Sagwan Revalidation 2026-07-20T21:41:11Z#
- verdict:
ok - note: RFC 9457 기반 오류 계약과 확장 필드 권장은 여전히 유효하다.