115 lines
9.4 KiB
Markdown
115 lines
9.4 KiB
Markdown
---
|
||
title: 토스페이먼츠 — 멱등키 가이드 (Using API / Idempotency-Key)
|
||
source_type: official-doc
|
||
url: https://docs.tosspayments.com/guides/using-api/idempotency-key
|
||
archive_url:
|
||
status: raw
|
||
confidence: high
|
||
tags: [ca-idempotency, toss-payments, korean-fintech, payment-domain]
|
||
related_projects: [ca-skeleton-operational-contract]
|
||
related_branches: [feature-rate-limit-idempotency-contract, feature-api-contract-baseline]
|
||
created: 2026-05-22
|
||
last_reviewed: 2026-05-27
|
||
---
|
||
|
||
# 토스페이먼츠 — 멱등키 가이드
|
||
|
||
> Layer: `raw/company-tech-blogs/` (디렉토리 정정 후보: 토스페이먼츠 공식 개발자 가이드이므로 `raw/official-docs/` 로 이관 적절. 본 migration 에서는 자동 mv 금지 규칙에 따라 위치 유지 — 후속 정리 권고).
|
||
> 한국 결제 도메인 표준 구현. ca-tmpl 의 idempotency contract 비교 기준.
|
||
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성.
|
||
|
||
## Parent / 활용 branch (필수)
|
||
|
||
> 이 자료가 정당화하는 결정 매핑.
|
||
|
||
| Branch | 이 자료가 정당화하는 결정 |
|
||
| -------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
||
| [[raw/branch-notes/feature-rate-limit-idempotency-contract]] | Idempotency contract 의 key scope 4-tuple vs 3-tuple 비교 + TTL 정책 (15일) 비교 + in-flight 충돌 처리 (409 vs wait) 비교 근거 |
|
||
| [[raw/branch-notes/feature-api-contract-baseline]] | API contract surface 에 `Idempotency-Key` 헤더 노출 표준 정립 시 vendor 표준 사례로 인용 |
|
||
| [[raw/project-notes/ca-skeleton-operational-contract]] | §13. API Contract Surface (Idempotency-Key) + §18. Control Plane Contract (Rate Limit/Idempotency) 의 한국 결제망 reference |
|
||
|
||
## 출처 / Source
|
||
|
||
- 원본 URL: https://docs.tosspayments.com/guides/using-api/idempotency-key
|
||
- 보조: https://docs.tosspayments.com/blog/what-is-idempotency (개념 설명 블로그)
|
||
- 참고: astor-dev "결제 도메인에서의 멱등성 보장" (개인 블로그, 사례 분석)
|
||
- 아카이브 URL: (미수집)
|
||
- 저자 / 조직: 토스페이먼츠 (TossPayments) Developer Documentation
|
||
- 발행일: rolling docs (페이지 자체에 명시 없음)
|
||
- 마지막 확인일: 2026-05-27
|
||
|
||
## 왜 저장했는지 / Why archived
|
||
|
||
한국 결제 도메인의 vendor 표준 구현. ca-tmpl 이 한국 환경에서 운영된다면 토스의 정책 (4-tuple scope, 15일 TTL, 409 in-flight) 이 직접 비교 대상.
|
||
|
||
## 핵심 인용 / Key quotes (verbatim)
|
||
|
||
> [§Idempotency-Key 사용] "요청 헤더에 `Idempotency-Key`를 추가하면 멱등한 요청을 보낼 수 있습니다"
|
||
|
||
> [§Idempotency-Key 사용] "멱등키는 UUID(/resources/glossary/uuid)와 같이 충분히 무작위적인 고유 값으로 생성해주세요"
|
||
|
||
> [§멱등성 보장 메커니즘] "토스페이먼츠 서버는 상점에서 API 요청 헤더로 보낸 멱등키와 API 키, API 주소, HTTP 메서드 조합이 같은 요청이 있는지 확인해서 멱등성을 보장합니다"
|
||
|
||
> [§TTL] "멱등키는 처음 요청에 사용한 날부터 15일간 유효합니다"
|
||
|
||
> [§에러] "HTTP `400 - INVALID_IDEMPOTENCY_KEY`"
|
||
|
||
> [§에러] "HTTP `409 - IDEMPOTENT_REQUEST_PROCESSING`"
|
||
|
||
> [§주의] "멱등한 요청에서 에러가 반환되었을 때 멱등키를 변경해서 동일한 요청을 재시도하는 것은 위험이 있습니다"
|
||
|
||
## Claims Extracted / 추출된 주장
|
||
|
||
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
||
|---|---|---|---|---|---|
|
||
| TOSS-IDEMP-C1 | 모든 POST API 에 `Idempotency-Key` 헤더를 추가하여 멱등 요청 가능, 값은 UUID 등 충분히 무작위 고유 값 권장 | [§Idempotency-Key 사용] "요청 헤더에 `Idempotency-Key`를 추가하면 멱등한 요청을 보낼 수 있습니다" + "멱등키는 UUID(/resources/glossary/uuid)와 같이 충분히 무작위적인 고유 값으로 생성해주세요" | `official-vendor-doc` | TossPayments API 의 POST endpoint | UUID 외 다른 형식 (예: 비즈니스 키, hash) 사용 시 충돌 위험은 별도 — 본 인용은 권장만 |
|
||
| TOSS-IDEMP-C2 | 멱등성 보장 범위는 **(멱등키, API 키, API 주소, HTTP 메서드) 4-tuple** 조합 | [§멱등성 보장 메커니즘] "토스페이먼츠 서버는 상점에서 API 요청 헤더로 보낸 멱등키와 API 키, API 주소, HTTP 메서드 조합이 같은 요청이 있는지 확인해서 멱등성을 보장합니다" | `official-vendor-doc` | TossPayments 가맹점 × endpoint × method 단위 | request body 가 다를 때의 처리 정책은 인용 범위에 없음 — body fingerprint 정책 부재 |
|
||
| TOSS-IDEMP-C3 | 멱등키 유효 기간은 첫 요청일로부터 **15일** | [§TTL] "멱등키는 처음 요청에 사용한 날부터 15일간 유효합니다" | `official-vendor-doc` | TossPayments idempotency store | 15일 정책이 모든 결제 도메인의 표준이라는 뜻은 아님. Stripe v1 24h / v2 30일과 다른 vendor-specific 결정 |
|
||
| TOSS-IDEMP-C4 | 잘못된 멱등키 형식 (예: 300자 초과 등) 은 `400 - INVALID_IDEMPOTENCY_KEY`, in-flight 동일 요청은 `409 - IDEMPOTENT_REQUEST_PROCESSING` | [§에러] "HTTP `400 - INVALID_IDEMPOTENCY_KEY`" + "HTTP `409 - IDEMPOTENT_REQUEST_PROCESSING`" | `official-vendor-doc` | TossPayments 의 표준 에러 매핑 | 409 가 즉시 반환되므로 클라이언트가 backoff 책임. wait/poll 동작 안 함 |
|
||
| TOSS-IDEMP-C5 | 멱등 요청 에러 시 키 변경 후 재시도는 위험이 있다 (공식적으로 권장 안 됨) | [§주의] "멱등한 요청에서 에러가 반환되었을 때 멱등키를 변경해서 동일한 요청을 재시도하는 것은 위험이 있습니다" | `official-vendor-doc` | retry 로직 설계 | 동일 키로 재시도해야 하는 정확한 조건 / 결과 코드별 분기는 본 인용에 없음 — 별도 가이드 확인 필요 |
|
||
| TOSS-IDEMP-C6 | 동일 키 + 동일 4-tuple + 다른 body 의 처리 정책은 본 인용 범위 내에 **명시 없음** | (부재 자체가 claim) | `needs-confirmation` | body fingerprint mismatch 처리 | 토스가 body diff 를 무시한다는 뜻도, 거부한다는 뜻도 아님. 문서가 직접 다루지 않음 |
|
||
|
||
## Usage Boundaries / 적용 경계
|
||
|
||
- **이 자료가 직접 증명하는 것**:
|
||
- `TOSS-IDEMP-C1` ~ `C5`: TossPayments idempotency API 의 헤더 사용법, key scope 4-tuple, TTL 15일, 에러 매핑, retry 위험 안내
|
||
- **이 자료가 증명하지 않는 것**:
|
||
- `TOSS-IDEMP-C6`: same-key + different-body 시 동작 (body fingerprint 정책)
|
||
- idempotency store 의 backend (DB vs Redis vs 그 외) — 외부 관찰 불가
|
||
- 다른 한국 결제사 (KG이니시스, 카카오페이 등) 도 동일 정책을 사용하는지
|
||
- in-flight 409 가 race condition 의 짧은 window 도 흡수하는지 (즉시 거부이므로 클라이언트 backoff 필수로 추정)
|
||
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
|
||
- ca-tmpl 의 3-tuple `(principal, key, useCaseName)` 과 토스의 4-tuple `(account, key, URL, method)` 매핑 시 `useCaseName` 이 URL+method 역할을 충분히 대체하는지 (비즈니스 식별자 일관성)
|
||
- ca-tmpl 의 15일이 아닌 24h TTL 결정의 위험 (긴 retry window 손실 vs 저장소 부하)
|
||
|
||
## 메모 / Notes
|
||
|
||
> 검증되지 않은 내 해석은 여기에 두지 말 것 — wiki source-summary 단계에서.
|
||
|
||
- **key scope**: 4-tuple = `(API 키 = 가맹점, idempotency-key, API 주소, HTTP 메서드)`. ca-tmpl 의 3-tuple `(principal, key, useCaseName)` 와 유사하나 토스는 method 까지 명시.
|
||
- **TTL**: 15일 (Stripe v1 24h 보다 길고, v2 30일보다 짧음).
|
||
- **저장소**: 명시 안됨 — 외부에서 알 수 없음. 결제 도메인 특성상 영속 저장 추정 (검증 불가).
|
||
- **duplicate 처리**:
|
||
- 완료 후 동일 키 재요청 → first 응답 그대로 replay (`C2` 의 일반적 동작).
|
||
- in-flight 동일 키 재요청 → `409 IDEMPOTENT_REQUEST_PROCESSING` (즉시 거부, ca-tmpl 처럼 wait 안 함).
|
||
- **fingerprint (same key, different body)**: 공식 문서에 명시 없음 (`C6` 참조).
|
||
- **장점 (추론)**: 가맹점 × endpoint × method 까지 분리되어 사고 범위가 좁음. 15일 긴 TTL.
|
||
- **단점 (추론)**: body fingerprint 정책 부재. in-flight 409 → 클라이언트 backoff 책임.
|
||
- **ca-tmpl 과의 차이 (대안 비교 후보, wiki/projects 추출 시 활용)**:
|
||
- 토스 4-tuple ↔ ca-tmpl 3-tuple. `useCaseName` 이 URL+method 역할 통합. 동일 사상.
|
||
- TTL: 토스 15일 ≫ ca-tmpl 24h. ca-tmpl 이 더 짧고 보수적.
|
||
- in-flight: 토스 즉시 409 vs ca-tmpl 200ms wait → ca-tmpl 이 클라이언트 친화적.
|
||
- fingerprint: 토스 미명시 vs ca-tmpl 명시적 422 → ca-tmpl 이 더 엄격.
|
||
|
||
## Related / 관련
|
||
|
||
- 같은 주제 다른 raw:
|
||
- [[raw/company-tech-blogs/idempotency-brandur-stripe-postgres]]
|
||
- [[raw/company-tech-blogs/idempotency-redis-vs-db-storage]]
|
||
- 인용하는 branch:
|
||
- [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
||
- [[raw/branch-notes/feature-api-contract-baseline]]
|
||
- 인용하는 project:
|
||
- [[raw/project-notes/ca-skeleton-operational-contract]] (§13, §18)
|
||
- 인용한 wiki 요약: (미작성)
|