//////

Core API Error Contracts: RFC 9457 Problem Details, Stable Machine Codes, Field-Validation Paths, Retryability Hints, and Correlation/Trace Failure Modes

Core API의 표준 오류 계약은 RFC 9457 Problem Details 를 기본 오류 envelope로 삼고, 그 위에 서비스 고유의 안정적인 machine-readable error code , 필드 단위 validation path , retryability hint , correlation/trace surface 를 명시적으로 확장하는 방식이 적합하다. 권장 형태는 다음과 같다. ``json { "type": "https://api.example

//////

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_FAILED
    • AUTHENTICATION_REQUIRED
    • PERMISSION_DENIED
    • RESOURCE_NOT_FOUND
    • RESOURCE_CONFLICT
    • RATE_LIMITED
    • IDEMPOTENCY_CONFLICT
    • UPSTREAM_UNAVAILABLE
  • error code는 공개 API 계약으로 보고, 제거·의미 변경은 breaking change로 취급하는 것이 안전하다.

  • HTTP status와 application code의 역할을 분리

  • HTTP status는 일반적인 실패 계층을 표현한다.
  • application code는 서비스 도메인 또는 정책상 세부 원인을 표현한다.
  • 예:
    • 400 + VALIDATION_FAILED
    • 401 + AUTHENTICATION_REQUIRED
    • 403 + PERMISSION_DENIED
    • 404 + RESOURCE_NOT_FOUND
    • 409 + RESOURCE_CONFLICT
    • 422 + SEMANTIC_VALIDATION_FAILED
    • 429 + RATE_LIMITED
    • 503 + SERVICE_UNAVAILABLE
  • 같은 status 아래 여러 code가 있을 수 있지만, 같은 code가 서로 모순되는 retry/UX 의미를 가져서는 안 된다.

  • 필드 단위 validation errors는 별도 배열로 제공

  • RFC 9457 자체는 필드 오류 배열의 표준 구조를 강제하지 않는다.
  • 실무적으로는 errors, violations, invalid_params 같은 확장 배열을 둔다.
  • 각 항목은 최소한 다음을 포함하는 것이 좋다.
    • code: 필드 오류의 machine code, 예: REQUIRED, INVALID_FORMAT, OUT_OF_RANGE
    • path: 실패한 입력 위치
    • message: 사람용 설명
  • path 형식은 반드시 표준화해야 한다.
    • JSON Pointer 형식 예: /customer/email, /items/0/quantity
    • dotted path 형식 예: customer.email, items[0].quantity
  • 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 가능”은 “즉시 무한 재시도”가 아니라 backoff, jitter, idempotency key, request safety 조건과 함께 해석되어야 한다.

  • correlation ID와 trace context를 응답에 노출

  • 운영 분석과 고객 지원을 위해 모든 오류 응답에는 요청 식별자를 제공하는 것이 좋다.
  • 일반적인 필드:
    • correlation_id: 고객 지원 또는 로그 검색용 요청 ID
    • trace_id: 분산 tracing 시스템의 trace 식별자
    • instance: RFC 9457의 problem occurrence URI 또는 request occurrence 식별자
  • W3C Trace Context는 traceparenttracestate 헤더를 정의한다. API가 이 표준을 사용한다면 응답 body의 trace_id와 헤더의 trace context 사이의 관계를 문서화해야 한다.
  • 보안상 내부 host, stack trace, SQL, secret, token, 개인정보는 error detail이나 trace surface에 포함하지 않는다.

  • localization은 사람용 필드에만 적용

  • title, detail, field-level message는 locale에 따라 바뀔 수 있다.
  • type, code, path, status, retryable은 locale과 무관하게 안정적이어야 한다.
  • 클라이언트는 localized message를 파싱하지 않아야 한다.

  • 오류 계약은 OpenAPI/JSON Schema에 명시

  • 공통 Problem schema를 만들고, 각 endpoint의 오류 응답이 이를 참조하게 한다.
  • field validation error item도 별도 schema로 고정한다.
  • 모든 공개 code 목록, retryability, HTTP status mapping, 예시 응답을 문서화한다.
  • SDK는 coderetryable을 기준으로 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 Conflict422 Unprocessable Content의 사용 경계는 조직마다 다를 수 있다. Core API는 둘의 의미를 자체적으로 고정해야 한다.

  • correlation ID와 trace ID는 디버깅에 유용하지만, 내부 인프라 구조나 민감 정보를 노출하지 않도록 형식과 보존 정책을 검토해야 한다.

  • detail이나 field message에 내부 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

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 기반 오류 계약과 확장 필드 권장은 여전히 유효하다.

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1