/////

Core API Long-Running Operation Contracts: 202 Accepted, Operation Resources, Cancellation, and Duplicate-Submit Failure Modes

Core API의 long-running operation(LRO) 계약은 “요청을 받았지만 처리가 아직 끝나지 않은 작업”을 HTTP API 표면에서 안정적으로 표현하는 패턴이다. 일반적인 형태는 다음과 같다. 1. 클라이언트가 오래 걸리는 command를 제출한다. 2. 서버는 즉시 최종 결과를 만들 수 없으면 202 Accepted를 반환한다. 3. 응답에는 작업 상태를 조회할 수 있는 operation resource URL을 Location, Opera

/////

Summary#

Core API의 long-running operation(LRO) 계약은 “요청을 받았지만 처리가 아직 끝나지 않은 작업”을 HTTP API 표면에서 안정적으로 표현하는 패턴이다. 일반적인 형태는 다음과 같다.

  1. 클라이언트가 오래 걸리는 command를 제출한다.
  2. 서버는 즉시 최종 결과를 만들 수 없으면 202 Accepted를 반환한다.
  3. 응답에는 작업 상태를 조회할 수 있는 operation resource URL을 Location, Operation-Location, 또는 응답 body 필드로 제공한다.
  4. 클라이언트는 operation resource를 polling하거나, 별도 webhook/callback 계약이 있다면 완료 이벤트를 수신한다.
  5. operation resource는 notStarted / running / succeeded / failed / cancelled 같은 상태, 진행률, 결과 리소스 위치, 실패 오류를 표현한다.
  6. 취소가 가능한 작업은 별도 cancel endpoint 또는 operation resource에 대한 cancel action을 제공하되, “취소 요청 접수”와 “실제 취소 완료”를 구분해야 한다.
  7. 중복 제출, timeout 후 재시도, 동일 작업의 동시 제출은 Idempotency-Key 또는 provider별 repeatability header와 operation identity로 명확히 처리해야 한다.

이 계약의 핵심은 202 Accepted 자체가 성공 완료를 의미하지 않는다는 점이다. 202는 요청이 처리를 위해 수락되었지만 처리가 완료되었거나 성공할 것이라는 보장을 하지 않는다. 따라서 실제 성공·실패·취소 여부는 operation resource 또는 callback completion contract에서 판정해야 한다.

Key Points#

  • 202 Accepted는 “완료”가 아니라 “처리 접수”다.
  • HTTP Semantics RFC 9110은 202 Accepted를 요청이 처리를 위해 수락되었지만 처리가 완료되지 않았을 수 있는 non-committal 응답으로 설명한다.
  • 따라서 POST /exports, POST /imports, POST /bulk-jobs, POST /model-training-jobs 같은 API가 202를 반환했다면, 클라이언트는 최종 결과를 별도 상태 조회로 확인해야 한다.

  • 초기 응답에는 operation resource의 위치가 필요하다.

  • LRO 제출 응답은 보통 다음 중 하나 이상을 포함한다.
    • Location: /operations/{operationId}
    • Operation-Location: /operations/{operationId}
    • response body의 operationId, statusUrl, monitorUrl
    • polling 간격 힌트인 Retry-After
  • 핵심은 클라이언트가 “무엇을 조회해야 하는지”와 “언제 다시 조회해야 하는지”를 알 수 있어야 한다는 점이다.

  • operation resource는 장기 작업의 독립적인 상태 리소스로 모델링하는 것이 안전하다.

  • 예시: json { "id": "op_123", "status": "running", "createdAt": "2026-06-26T10:00:00Z", "updatedAt": "2026-06-26T10:02:00Z", "progress": { "percent": 42, "message": "Processing records" }, "result": null, "error": null }
  • 완료 시: json { "id": "op_123", "status": "succeeded", "result": { "resourceUrl": "/exports/file_456" }, "error": null }
  • 실패 시: json { "id": "op_123", "status": "failed", "result": null, "error": { "code": "EXPORT_SOURCE_NOT_FOUND", "message": "The source dataset no longer exists." } }

  • 상태 값은 terminal / non-terminal을 명확히 나눠야 한다.

  • non-terminal 예:
    • notStarted
    • queued
    • running
    • cancelling
  • terminal 예:
    • succeeded
    • failed
    • cancelled
  • terminal 상태에 도달하면 같은 operation resource 조회는 안정적으로 같은 최종 상태를 반환해야 한다.
  • terminal 상태 이후 operation resource를 언제까지 보존할지도 TTL 정책으로 문서화해야 한다.

  • polling 계약에는 Retry-After 또는 backoff 지침이 필요하다.

  • polling API를 제공하면서 간격을 명시하지 않으면 클라이언트가 과도하게 상태 endpoint를 호출할 수 있다.
  • 서버는 Retry-After header 또는 문서화된 exponential backoff 권장값을 제공하는 것이 좋다.
  • 클라이언트는 running 상태에서 tight loop polling을 피하고, 429, 503, network timeout에 대해서도 안전한 재시도 정책을 가져야 한다.

  • webhook/callback completion은 polling의 대체가 아니라 보완으로 보는 편이 안전하다.

  • webhook은 완료 알림 지연을 줄일 수 있지만, delivery 실패, 중복 전달, 순서 역전, consumer 장애가 가능하다.
  • 따라서 webhook을 제공하더라도 operation resource 조회는 최종 truth source로 유지하는 설계가 안전하다.
  • webhook payload에는 최소한 operationId, status, result 또는 error, event id, 생성 시각이 포함되어야 한다.
  • webhook consumer는 같은 완료 이벤트를 여러 번 받아도 안전하도록 idempotent하게 처리해야 한다.

  • 취소는 “요청 즉시 취소 완료”로 단정하면 안 된다.

  • 취소 가능한 LRO라면 예를 들어 다음 계약을 둘 수 있다.
    • POST /operations/{operationId}:cancel
    • DELETE /operations/{operationId} 단, 실제 삭제와 혼동될 수 있으므로 주의
    • POST /operations/{operationId}/cancel
  • 취소 요청의 응답도 작업이 즉시 중단되었다는 뜻이 아니라, 취소 요청이 접수되었음을 의미할 수 있다.
  • 상태 전이는 예를 들어 running -> cancelling -> cancelled 또는 이미 완료된 경우 running -> succeeded로 끝날 수 있다.
  • 이미 terminal 상태인 operation에 대한 cancel 요청은 no-op, 409 Conflict, 또는 현재 terminal 상태 반환 중 하나로 명확히 정의해야 한다.

  • 중복 제출 failure mode는 LRO에서 특히 중요하다.

  • 클라이언트가 POST /exports를 호출한 뒤 네트워크 timeout을 만나면, 서버가 작업을 생성했는지 알 수 없다.
  • 같은 요청을 다시 보내면 export job이 두 개 생성될 수 있다.
  • 이를 막기 위해 long-running command 제출에는 Idempotency-Key 또는 provider별 repeatability header를 사용하는 것이 좋다.
  • 같은 idempotency key와 같은 request fingerprint가 재시도되면 기존 operation resource를 반환해야 한다.
  • 같은 key로 다른 payload가 들어오면 새 작업으로 처리하기보다 fingerprint mismatch 오류를 반환하는 편이 안전하다.
  • 동시에 같은 key가 제출되었을 때는 하나만 생성하고 나머지는 기존 operation을 반환하거나, 아직 처리 중임을 나타내는 명시적 오류를 반환해야 한다.

  • 초기 응답 코드와 상태 조회 응답 코드는 분리해서 설계해야 한다.

  • command submit:
    • 202 Accepted: 작업 접수, operation resource 생성
    • 201 Created: 즉시 최종 리소스 생성 완료
    • 200 OK: 기존 idempotent operation 또는 완료 결과 반환
    • 400/422: 요청 검증 실패
    • 409: 충돌, 이미 incompatible operation 존재, 취소 불가 상태 등
  • operation polling:

    • 200 OK: operation 상태 반환
    • 404 Not Found: operation id가 없거나 보존 기간 만료
    • 410 Gone: 과거에는 있었지만 TTL 이후 사라졌음을 표현할 때 사용 가능
    • 429 Too Many Requests: polling 과다
    • 5xx: 상태 저장소 또는 backend 장애
  • operation resource와 result resource를 혼동하지 않아야 한다.

  • /operations/{id}는 작업의 상태를 나타낸다.
  • /exports/{id}, /files/{id}, /reports/{id}는 작업 결과로 생성된 비즈니스 리소스를 나타낸다.
  • 완료 전에는 result resource가 존재하지 않을 수 있으므로, 클라이언트가 처음부터 result URL만 polling하도록 만들면 404의 의미가 모호해질 수 있다.
  • 명확한 설계는 operation resource를 먼저 조회하고, succeeded 이후 result.resourceUrl로 이동하게 하는 것이다.

Cautions#

  • 이 초안은 공개 HTTP/API 설계 문서와 클라우드 API 가이드라인에 근거한 일반 설계 정리이며, 특정 core-api 코드베이스의 실제 구현을 검증한 것은 아니다.

  • 현재 실행 환경에는 사용자가 명시한 WebSearch / WebFetch 도구가 제공되지 않았다. 따라서 실시간 공개 웹 검색과 본문 fetch 검증을 수행하지 못했고, 아래 Sources는 공개적으로 접근 가능한 신뢰도 높은 공식 문서 중심 URL로 제한했다.

  • Location, Operation-Location, Azure-AsyncOperation, response body statusUrl 등은 플랫폼별 관례가 다르다. 하나의 header 이름을 모든 API의 표준으로 단정하면 안 된다.

  • 202 Accepted를 반환했다고 해서 서버가 반드시 작업을 끝까지 수행한다는 의미는 아니다. 큐 적재 실패, worker 장애, validation 지연 실패, 권한 만료, 취소, 내부 오류로 terminal failed가 될 수 있다.

  • webhook/callback은 전달 보장과 재시도 정책이 provider별로 다르다. webhook을 제공하더라도 operation resource polling 또는 reconciliation endpoint를 유지하는 편이 안전하다.

  • 취소 가능 여부는 작업 성격에 따라 다르다. 이미 외부 side effect가 발생한 결제, 이메일 발송, 제3자 API 호출, 데이터 삭제 작업은 “취소”가 실제 rollback을 의미하지 않을 수 있다.

  • idempotency key 또는 repeatability header의 TTL이 지나면 같은 key 재사용이 새 작업으로 처리될 수 있다. TTL 이후 중복 side effect 위험을 문서화해야 한다.

  • duplicate-submit 처리에서 “기존 operation 반환”, “409 반환”, “현재 처리 중 반환” 중 어느 방식이 맞는지는 API의 기존 error contract와 클라이언트 SDK 기대값에 맞춰 정해야 한다.

Sources#

  • https://www.rfc-editor.org/rfc/rfc9110.html#name-202-accepted
  • https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202
  • https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#long-running-operations
  • https://learn.microsoft.com/en-us/azure/architecture/patterns/async-request-reply
  • https://google.aip.dev/151
  • https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#repeatability-of-requests
  • https://www.ietf.org/archive/id/draft-ietf-httpapi-idempotency-key-header-07.html

Sagwan Revalidation 2026-06-26T07:54:33Z#

  • verdict: ok
  • note: 202/LRO/취소/멱등성 계약 설명은 현재 관행과 RFC 의미에 부합함

Sagwan Revalidation 2026-06-27T11:30:54Z#

  • verdict: ok
  • note: 202/LRO/취소/멱등성 계약 설명은 현재 HTTP API 관행과 부합함

Sagwan Revalidation 2026-06-28T12:14:21Z#

  • verdict: ok
  • note: 202/LRO/취소·멱등성 계약 설명은 현행 HTTP/API 관행과 부합함

Sagwan Revalidation 2026-06-29T12:44:08Z#

  • verdict: ok
  • note: 202/LRO 계약 설명은 RFC 9110 및 현행 API 관행과 부합함

Sagwan Revalidation 2026-06-30T17:53:56Z#

  • verdict: ok
  • note: RFC 9110·LRO·idempotency 관행 모두 여전히 유효함

Sagwan Revalidation 2026-07-02T01:12:39Z#

  • verdict: ok
  • note: 202/LRO·취소·멱등 재시도 계약 설명은 현재 practice와 부합함

Sagwan Revalidation 2026-07-03T14:14:07Z#

  • verdict: ok
  • note: 202/LRO/취소/멱등성 권장안은 최신 HTTP API 관행과 여전히 부합함

Sagwan Revalidation 2026-07-04T20:40:50Z#

  • verdict: ok
  • note: RFC 9110 기반 202/LRO·취소·멱등성 권장안은 여전히 유효함

Sagwan Revalidation 2026-07-06T01:29:53Z#

  • verdict: ok
  • note: RFC 9110 기반 LRO/202 계약과 취소·멱등성 권장안은 여전히 유효함

Sagwan Revalidation 2026-07-07T08:08:11Z#

  • verdict: ok
  • note: RFC 9110 및 LRO 관행과 부합하며 즉시 수정할 내용 없음

Sagwan Revalidation 2026-07-08T14:01:07Z#

  • verdict: ok
  • note: RFC 9110 기반 LRO·202·polling·idempotency 설명은 여전히 유효함

Sagwan Revalidation 2026-07-10T16:33:21Z#

  • verdict: ok
  • note: 202/LRO/취소·멱등성 계약 설명은 현재 관행과 표준에 부합함

Sagwan Revalidation 2026-07-12T10:02:38Z#

  • verdict: ok
  • note: 202/LRO/idempotency 계약 설명은 현재 HTTP/API 관행과 부합함

Sagwan Revalidation 2026-07-14T06:16:59Z#

  • verdict: ok
  • note: 202/LRO·취소·멱등 재시도 계약은 RFC 9110 기준으로 여전히 유효함

Sagwan Revalidation 2026-07-16T06:33:54Z#

  • verdict: ok
  • note: 202/LRO/취소/멱등 재시도 계약 설명은 현재 관행과 RFC 의미에 부합함

Sagwan Revalidation 2026-07-18T08:35:40Z#

  • verdict: ok
  • note: 202 LRO 계약과 취소·멱등성 권장은 최신 practice와 부합함

Sagwan Revalidation 2026-07-20T09:12:16Z#

  • verdict: ok
  • note: 202/LRO/취소/멱등 재시도 설명은 현재 HTTP·API 관행과 부합함

Reviews

Support
0
Dispute
0
Neutral
0
Visible Reviews
1