init: document-haness 하네스 설계
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"title": "API 재시도는 횟수가 아니라 부하 예산으로 설계한다",
|
||||
"document_type": "technical_blog",
|
||||
"language": "ko-KR",
|
||||
"audience": {
|
||||
"roles": [
|
||||
"백엔드 개발자",
|
||||
"플랫폼 엔지니어"
|
||||
],
|
||||
"prior_knowledge": [
|
||||
"HTTP 요청과 타임아웃의 기본 개념",
|
||||
"분산 시스템의 부분 실패 경험"
|
||||
],
|
||||
"needs": [
|
||||
"재시도 정책을 설계할 때 확인할 판단 기준",
|
||||
"운영 환경에서 검증할 지표"
|
||||
]
|
||||
},
|
||||
"reader_goal": "재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다",
|
||||
"core_message": "재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.",
|
||||
"scope": [
|
||||
"서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책",
|
||||
"정책을 검증하는 운영 지표와 실패 실험"
|
||||
],
|
||||
"non_scope": [
|
||||
"메시지 큐의 전달 보장 전체 설계",
|
||||
"특정 클라우드 SDK의 모든 기본값",
|
||||
"정확히 한 번 처리 보장"
|
||||
],
|
||||
"prerequisites": [
|
||||
"HTTP 상태 코드와 타임아웃을 이해함",
|
||||
"로그와 지표를 조회할 수 있음"
|
||||
],
|
||||
"required_topics": [
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"constraints": {
|
||||
"target_words": 1200,
|
||||
"tone": "운영 경험이 있는 엔지니어에게 설명하는 직접적이고 검증 가능한 문체",
|
||||
"version_context": "HTTP 의미론은 RFC 9110, 예시는 2026-07-23 기준",
|
||||
"max_heading_depth": 3,
|
||||
"require_citations": true,
|
||||
"allow_external_knowledge": false
|
||||
},
|
||||
"forbidden_claims": [
|
||||
"재시도는 항상 안전하다"
|
||||
],
|
||||
"metadata": {
|
||||
"owner": "platform-engineering",
|
||||
"risk": "high",
|
||||
"review_cycle": "quarterly"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
# API 재시도는 횟수가 아니라 부하 예산으로 설계한다
|
||||
|
||||
## 먼저 결론: 무엇을 해결하는가
|
||||
|
||||
이 글의 독자는 백엔드 개발자, 플랫폼 엔지니어이다. 읽고 나면 **재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다**할 수 있어야 한다. 먼저 결론부터 말하면, 재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.
|
||||
범위는 서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책, 정책을 검증하는 운영 지표와 실패 실험이다. 합리적으로 기대할 수 있지만 이 글에서 다루지 않는 범위는 메시지 큐의 전달 보장 전체 설계, 특정 클라우드 SDK의 모든 기본값, 정확히 한 번 처리 보장이다. 적용 맥락은 HTTP 의미론은 RFC 9110, 예시는 2026-07-23 기준이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 문제가 생기는 맥락과 제약
|
||||
|
||||
이 절은 ‘왜 이 문제가 실제 시스템에서 어려워지는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 현상, 원인 후보, 제약, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
현실의 문제는 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준가 독립적으로 움직이지 않는다는 점이다. 입력, 상태, 시간, 실패 복구가 연결되므로 한 요소만 최적화하면 다른 경로에서 비용이 나타날 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 핵심 판단 기준과 멘털 모델
|
||||
|
||||
이 절은 ‘뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 용어 정의, 인과 관계, 판단 기준이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
멘털 모델은 ‘입력 → 판단 기준 → 상태 변화 → 관측 결과’의 네 칸으로 잡는다. 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준를 이 흐름에 배치하면 구현 세부사항이 바뀌어도 인과 관계를 추적할 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
|
||||
## 해결 방식이 동작하는 과정
|
||||
|
||||
이 절은 ‘구성요소와 데이터 흐름은 어떻게 연결되는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 구성요소, 데이터 또는 제어 흐름, 불변조건, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
동작은 다음 인과 순서로 이해할 수 있다.
|
||||
1. 입력과 사전 조건을 검증하고 처리 가능한 상태인지 확인한다.
|
||||
2. 명시된 판단 기준으로 경로를 선택하고 상태 변경 범위를 제한한다.
|
||||
3. 결과를 기록한 뒤 성공 기준과 비교해 다음 행동을 결정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 끝까지 따라가는 구현 예시
|
||||
|
||||
이 절은 ‘구체적인 입력이 어떻게 결과로 바뀌는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 초기 조건, 단계별 변화, 최종 결과, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
아래는 특정 제품의 실제 측정값이 아니라 판단 흐름을 드러내기 위한 예시다.
|
||||
```text
|
||||
입력: 변경 요청과 현재 상태
|
||||
판단: 사전 조건 충족 여부 → 안전한 실행 경로 선택
|
||||
실행: 최소 범위 변경
|
||||
관측: 예상 상태와 실제 상태 비교
|
||||
결과: 성공이면 확정, 불일치면 중단 후 복구
|
||||
```
|
||||
예시의 핵심은 명령 자체가 아니라 각 단계의 입력, 판단, 관측이 끊기지 않는다는 점이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A request method is idempotent when multiple identical requests have the same intended effect as one request. [S2]
|
||||
|
||||
## 어떻게 검증할 것인가
|
||||
|
||||
이 절은 ‘주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 검증 절차, 성공 기준, 관측 지표, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
검증 계획은 주장과 관측을 일대일로 연결한다.
|
||||
1. 핵심 주장마다 확인 가능한 로그, 테스트, 상태 또는 출처를 지정한다.
|
||||
2. 정상 경로뿐 아니라 실패 경로와 복구 경로를 실행한다.
|
||||
3. 성공 기준과 중단 기준을 실행 전에 고정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Exponential backoff increases the delay between retry attempts and should use bounded limits. [S3]
|
||||
|
||||
## 대안, 트레이드오프, 실패 조건
|
||||
|
||||
이 절은 ‘언제 이 접근법을 선택하지 말아야 하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 대안, 얻는 것과 잃는 것, 적용 한계이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
이 접근은 구조와 검증 가능성을 얻는 대신 초기 설계와 근거 정리에 비용이 든다. 빠른 초안만 필요한 상황에서는 과할 수 있고, 규제·운영 위험이 큰 문서에서는 더 강한 사실 검증이 필요하다.
|
||||
대안은 더 자유로운 서술, 단일 모델 작성, 수동 리뷰다. 선택 기준은 문서의 위험도, 변경 빈도, 독자의 숙련도, 검증 비용이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 실무 적용 체크리스트
|
||||
|
||||
실무 적용 전 다음을 확인한다.
|
||||
- 독자 목표와 비범위를 한 문장으로 고정했는가?
|
||||
- 판단 기준과 근거가 연결되어 있는가?
|
||||
- 예시가 시작 상태부터 검증 결과까지 이어지는가?
|
||||
- 실패 조건, 중단 기준, 롤백이 있는가?
|
||||
- 버전 또는 시점이 드러나는가?
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 결론
|
||||
|
||||
기억해야 할 판단은 하나다. **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.** 독자의 다음 행동은 자신의 환경에서 재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다을 검증 가능한 기준으로 바꾸는 것이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
@@ -0,0 +1,83 @@
|
||||
# ClariDoc quality report
|
||||
|
||||
- Document: **API 재시도는 횟수가 아니라 부하 예산으로 설계한다**
|
||||
- Type: `technical_blog`
|
||||
- Language: `ko-KR`
|
||||
- Gate: **PASS**
|
||||
- Final composite score: **89.3/100**
|
||||
- Rounds: **1**
|
||||
|
||||
## Provider topology
|
||||
|
||||
- Planner: `mock`
|
||||
- Writer: `mock`
|
||||
- Reviser: `mock`
|
||||
- Reviewers: `logic` → `mock`, `reader` → `mock`, `evidence` → `mock`, `operations` → `mock`
|
||||
|
||||
## Quality-gate configuration
|
||||
|
||||
- Minimum score: 82.0
|
||||
- Maximum blockers: 0
|
||||
- Maximum errors: 2
|
||||
- Maximum revisions: 2
|
||||
- Weights: deterministic 40%, model reviews 60%
|
||||
|
||||
## Round history
|
||||
|
||||
| Round | Deterministic | Model mean | Composite | Blockers | Errors | Gate |
|
||||
|---:|---:|---:|---:|---:|---:|---|
|
||||
| 1 | 87.5 | 90.5 | 89.3 | 0 | 0 | PASS |
|
||||
|
||||
## Final deterministic findings
|
||||
|
||||
blocker: 0, error: 0, warning: 5, info: 0
|
||||
|
||||
| Severity | Code | Location | Finding |
|
||||
|---|---|---|---|
|
||||
| warning | `READ002` | line 5 | Paragraph contains 8 sentences. |
|
||||
| warning | `READ002` | line 11 | Paragraph contains 8 sentences. |
|
||||
| warning | `READ002` | line 17 | Paragraph contains 8 sentences. |
|
||||
| warning | `READ002` | line 23 | Paragraph contains 13 sentences. |
|
||||
| warning | `READ002` | line 40 | Paragraph contains 13 sentences. |
|
||||
|
||||
## Final independent reviews
|
||||
|
||||
### logic — mock
|
||||
|
||||
Score: **90.5/100**
|
||||
|
||||
Strengths: The logic review found the document contract explicit and inspectable.
|
||||
|
||||
No material issues reported.
|
||||
|
||||
### reader — mock
|
||||
|
||||
Score: **90.5/100**
|
||||
|
||||
Strengths: The reader review found the document contract explicit and inspectable.
|
||||
|
||||
No material issues reported.
|
||||
|
||||
### evidence — mock
|
||||
|
||||
Score: **90.5/100**
|
||||
|
||||
Strengths: The evidence review found the document contract explicit and inspectable.
|
||||
|
||||
No material issues reported.
|
||||
|
||||
### operations — mock
|
||||
|
||||
Score: **90.5/100**
|
||||
|
||||
Strengths: The operations review found the document contract explicit and inspectable.
|
||||
|
||||
No material issues reported.
|
||||
|
||||
## Harness warnings
|
||||
|
||||
- All providers are deterministic mocks. This run validates pipeline mechanics only; model-review scores are synthetic and must not be used as evidence of document quality.
|
||||
|
||||
## Interpretation
|
||||
|
||||
A PASS means this run met the configured structural, lint, and model-review gate. It does not replace domain-owner verification, executable code testing, legal review, security review, or independent validation of source truth.
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"title": "API 재시도는 횟수가 아니라 부하 예산으로 설계한다",
|
||||
"document_type": "technical_blog",
|
||||
"language": "ko-KR",
|
||||
"audience": {
|
||||
"roles": [
|
||||
"백엔드 개발자",
|
||||
"플랫폼 엔지니어"
|
||||
],
|
||||
"prior_knowledge": [
|
||||
"HTTP 요청과 타임아웃의 기본 개념",
|
||||
"분산 시스템의 부분 실패 경험"
|
||||
],
|
||||
"needs": [
|
||||
"재시도 정책을 설계할 때 확인할 판단 기준",
|
||||
"운영 환경에서 검증할 지표"
|
||||
]
|
||||
},
|
||||
"reader_goal": "재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다",
|
||||
"core_message": "재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.",
|
||||
"scope": [
|
||||
"서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책",
|
||||
"정책을 검증하는 운영 지표와 실패 실험"
|
||||
],
|
||||
"non_scope": [
|
||||
"메시지 큐의 전달 보장 전체 설계",
|
||||
"특정 클라우드 SDK의 모든 기본값",
|
||||
"정확히 한 번 처리 보장"
|
||||
],
|
||||
"prerequisites": [
|
||||
"HTTP 상태 코드와 타임아웃을 이해함",
|
||||
"로그와 지표를 조회할 수 있음"
|
||||
],
|
||||
"required_topics": [
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"constraints": {
|
||||
"target_words": 1200,
|
||||
"tone": "운영 경험이 있는 엔지니어에게 설명하는 직접적이고 검증 가능한 문체",
|
||||
"version_context": "HTTP 의미론은 RFC 9110, 예시는 2026-07-23 기준",
|
||||
"max_heading_depth": 3,
|
||||
"require_citations": true,
|
||||
"allow_external_knowledge": false
|
||||
},
|
||||
"forbidden_claims": [
|
||||
"재시도는 항상 안전하다"
|
||||
],
|
||||
"metadata": {
|
||||
"owner": "platform-engineering",
|
||||
"risk": "high",
|
||||
"review_cycle": "quarterly"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"planner": {
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
"writer": {
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
"reviewers": [
|
||||
{
|
||||
"role": "logic",
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"role": "reader",
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"role": "evidence",
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"role": "operations",
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"reviser": {
|
||||
"provider": "mock",
|
||||
"model": "",
|
||||
"timeout_seconds": 300,
|
||||
"options": {}
|
||||
},
|
||||
"quality_gate": {
|
||||
"minimum_score": 82.0,
|
||||
"max_blockers": 0,
|
||||
"max_errors": 2,
|
||||
"max_revisions": 2,
|
||||
"deterministic_weight": 0.4,
|
||||
"model_weight": 0.6
|
||||
},
|
||||
"fail_on_reviewer_error": true
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"sources": [
|
||||
{
|
||||
"id": "S1",
|
||||
"title": "Timeouts, retries, and backoff with jitter",
|
||||
"url": "https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/",
|
||||
"publisher": "Amazon Web Services Builders’ Library",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"Retries can increase load on a dependency that is already failing.",
|
||||
"Exponential backoff limits retry frequency, and jitter spreads retry timing across clients.",
|
||||
"Retry behavior should be bounded rather than continuing indefinitely."
|
||||
],
|
||||
"notes": "Use for retry-load, backoff, jitter, and bounded-retry claims."
|
||||
},
|
||||
{
|
||||
"id": "S2",
|
||||
"title": "RFC 9110, HTTP Semantics — Idempotent Methods",
|
||||
"url": "https://datatracker.ietf.org/doc/html/rfc9110#section-9.2.2",
|
||||
"publisher": "IETF",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"A request method is idempotent when multiple identical requests have the same intended effect as one request.",
|
||||
"A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions."
|
||||
],
|
||||
"notes": "Use for the definition and retry implications of HTTP method idempotency."
|
||||
},
|
||||
{
|
||||
"id": "S3",
|
||||
"title": "Retry strategy",
|
||||
"url": "https://cloud.google.com/storage/docs/retry-strategy",
|
||||
"publisher": "Google Cloud",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"Retry behavior should consider whether the operation is idempotent.",
|
||||
"Exponential backoff increases the delay between retry attempts and should use bounded limits."
|
||||
],
|
||||
"notes": "Use as a second implementation-oriented source for bounded backoff and idempotency checks."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"created_at": "2026-07-23T09:01:54+00:00",
|
||||
"files": [
|
||||
{
|
||||
"path": "final/document.md",
|
||||
"bytes": 9917,
|
||||
"sha256": "922164daa07926f5cfedf225c1ff68eb38d83cc2441100720ddd1037d6b49bdc"
|
||||
},
|
||||
{
|
||||
"path": "final/quality-report.md",
|
||||
"bytes": 2332,
|
||||
"sha256": "fb77d719cdb0faec6cdaab581d73ad8476a6a4278a2c772ad912343fa8dec2f0"
|
||||
},
|
||||
{
|
||||
"path": "inputs/brief.normalized.json",
|
||||
"bytes": 2054,
|
||||
"sha256": "c1b6905ceb2366b2eb3a1a2b0fb162d10f8f08fad1ff67fdc307d27a2dc3ad13"
|
||||
},
|
||||
{
|
||||
"path": "inputs/pipeline.normalized.json",
|
||||
"bytes": 1088,
|
||||
"sha256": "8dda422b88ed8917ee39729bec6ad496809b365a457feb82785b644239593431"
|
||||
},
|
||||
{
|
||||
"path": "inputs/sources.normalized.json",
|
||||
"bytes": 1827,
|
||||
"sha256": "2c86c8841d0f60d0cc936d93a1d43c2cb69f37dbac683ee94109cce9cbc9f24b"
|
||||
},
|
||||
{
|
||||
"path": "provider-events.jsonl",
|
||||
"bytes": 2090,
|
||||
"sha256": "c3e0518db33b86f02db9537642511c68972cae0412e698e7ef70eaea9045802f"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/draft.md",
|
||||
"bytes": 9917,
|
||||
"sha256": "922164daa07926f5cfedf225c1ff68eb38d83cc2441100720ddd1037d6b49bdc"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/lint.json",
|
||||
"bytes": 1402,
|
||||
"sha256": "988f3f5d25b9dbc74ea347f816c3fc595a076bf3cf39156a8d7513b413a7b476"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/lint.md",
|
||||
"bytes": 718,
|
||||
"sha256": "e61e2fba316d517dac13138d4c56133e8fc5e74cf2f4cc545d58244fd18d8222"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/quality-gate.json",
|
||||
"bytes": 153,
|
||||
"sha256": "49e30867fbac6c40dce49f9932a3f49febc995856facf17096e4a73ec0b860cf"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-01-logic.json",
|
||||
"bytes": 1058,
|
||||
"sha256": "86404de091d2315de172d08eb1698fdc8d172c3ab0c3130149e9b43e33ad25fe"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-01-logic.raw.txt",
|
||||
"bytes": 474,
|
||||
"sha256": "1ab77971a9b88198fb17d9df7f836d322d6574e6d23b2d3dda3231b759d60709"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-02-reader.json",
|
||||
"bytes": 1061,
|
||||
"sha256": "83653fefc4282d0d4c5b0d1bef10c40d2dba8ece0e6d146073e3c7ec7cd94a05"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-02-reader.raw.txt",
|
||||
"bytes": 475,
|
||||
"sha256": "b01fc7ee460134cb6de9e9d512f723bf0114f8f2719f16743e3ab4ab0e8b41a3"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-03-evidence.json",
|
||||
"bytes": 1067,
|
||||
"sha256": "e4beff451d7cca049a7fb6890b4f60f81851305d316ffaf70ef6a110803509dc"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-03-evidence.raw.txt",
|
||||
"bytes": 477,
|
||||
"sha256": "8f3f7409d78e9104b405950475d2866cc748b7be9ae854b8b6f2441e386e6150"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-04-operations.json",
|
||||
"bytes": 1073,
|
||||
"sha256": "d7d967137032a5808d097bff8fd2e6616a1fc52f4eb7caf5509b7304714dc067"
|
||||
},
|
||||
{
|
||||
"path": "rounds/round-01/review-04-operations.raw.txt",
|
||||
"bytes": 479,
|
||||
"sha256": "f4ef635c6c5b70265be78fdf21387ec094af43febce25ec4d3f50f3725c56d57"
|
||||
},
|
||||
{
|
||||
"path": "run.json",
|
||||
"bytes": 974,
|
||||
"sha256": "9ecf601c4fafc8e92a7f7dae9e4ac2e0905d883dd8bf867ff488153fd61e4705"
|
||||
},
|
||||
{
|
||||
"path": "stages/01-planner.raw.txt",
|
||||
"bytes": 6980,
|
||||
"sha256": "1ac11b79232508fdc37be09f7de0299e87f26ec544ed12503a90d2b2a643a41d"
|
||||
},
|
||||
{
|
||||
"path": "stages/02-outline.json",
|
||||
"bytes": 6980,
|
||||
"sha256": "1ac11b79232508fdc37be09f7de0299e87f26ec544ed12503a90d2b2a643a41d"
|
||||
},
|
||||
{
|
||||
"path": "stages/02-outline.md",
|
||||
"bytes": 4817,
|
||||
"sha256": "e9518d24d7248f2add8b6ebb5d63fb49b4655b6ce602320780ec13697af6c468"
|
||||
},
|
||||
{
|
||||
"path": "stages/03-writer.raw.txt",
|
||||
"bytes": 9918,
|
||||
"sha256": "4898ba141e9492b9b52030e1363ccfae43e00b31f7daf7191708a3e4617d113c"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "plan", "provider": "mock", "model": "", "metadata": {"document_type": "technical_blog"}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "plan", "provider": "mock", "model": "", "metadata": {"document_type": "technical_blog"}, "status": "completed", "duration_ms": 0.4, "response_characters": 4771, "command": []}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "draft", "provider": "mock", "model": "", "metadata": {}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "draft", "provider": "mock", "model": "", "metadata": {}, "status": "completed", "duration_ms": 0.6, "response_characters": 4722, "command": []}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "logic"}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "logic"}, "status": "completed", "duration_ms": 0.3, "response_characters": 473, "command": []}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "reader"}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "reader"}, "status": "completed", "duration_ms": 0.3, "response_characters": 474, "command": []}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "evidence"}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "evidence"}, "status": "completed", "duration_ms": 0.3, "response_characters": 476, "command": []}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "operations"}, "status": "started"}
|
||||
{"at": "2026-07-23T09:01:54+00:00", "stage": "review", "provider": "mock", "model": "", "metadata": {"role": "operations"}, "status": "completed", "duration_ms": 0.3, "response_characters": 478, "command": []}
|
||||
@@ -0,0 +1,73 @@
|
||||
# API 재시도는 횟수가 아니라 부하 예산으로 설계한다
|
||||
|
||||
## 먼저 결론: 무엇을 해결하는가
|
||||
|
||||
이 글의 독자는 백엔드 개발자, 플랫폼 엔지니어이다. 읽고 나면 **재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다**할 수 있어야 한다. 먼저 결론부터 말하면, 재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.
|
||||
범위는 서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책, 정책을 검증하는 운영 지표와 실패 실험이다. 합리적으로 기대할 수 있지만 이 글에서 다루지 않는 범위는 메시지 큐의 전달 보장 전체 설계, 특정 클라우드 SDK의 모든 기본값, 정확히 한 번 처리 보장이다. 적용 맥락은 HTTP 의미론은 RFC 9110, 예시는 2026-07-23 기준이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 문제가 생기는 맥락과 제약
|
||||
|
||||
이 절은 ‘왜 이 문제가 실제 시스템에서 어려워지는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 현상, 원인 후보, 제약, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
현실의 문제는 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준가 독립적으로 움직이지 않는다는 점이다. 입력, 상태, 시간, 실패 복구가 연결되므로 한 요소만 최적화하면 다른 경로에서 비용이 나타날 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 핵심 판단 기준과 멘털 모델
|
||||
|
||||
이 절은 ‘뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 용어 정의, 인과 관계, 판단 기준이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
멘털 모델은 ‘입력 → 판단 기준 → 상태 변화 → 관측 결과’의 네 칸으로 잡는다. 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준를 이 흐름에 배치하면 구현 세부사항이 바뀌어도 인과 관계를 추적할 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
|
||||
## 해결 방식이 동작하는 과정
|
||||
|
||||
이 절은 ‘구성요소와 데이터 흐름은 어떻게 연결되는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 구성요소, 데이터 또는 제어 흐름, 불변조건, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
동작은 다음 인과 순서로 이해할 수 있다.
|
||||
1. 입력과 사전 조건을 검증하고 처리 가능한 상태인지 확인한다.
|
||||
2. 명시된 판단 기준으로 경로를 선택하고 상태 변경 범위를 제한한다.
|
||||
3. 결과를 기록한 뒤 성공 기준과 비교해 다음 행동을 결정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 끝까지 따라가는 구현 예시
|
||||
|
||||
이 절은 ‘구체적인 입력이 어떻게 결과로 바뀌는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 초기 조건, 단계별 변화, 최종 결과, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
아래는 특정 제품의 실제 측정값이 아니라 판단 흐름을 드러내기 위한 예시다.
|
||||
```text
|
||||
입력: 변경 요청과 현재 상태
|
||||
판단: 사전 조건 충족 여부 → 안전한 실행 경로 선택
|
||||
실행: 최소 범위 변경
|
||||
관측: 예상 상태와 실제 상태 비교
|
||||
결과: 성공이면 확정, 불일치면 중단 후 복구
|
||||
```
|
||||
예시의 핵심은 명령 자체가 아니라 각 단계의 입력, 판단, 관측이 끊기지 않는다는 점이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A request method is idempotent when multiple identical requests have the same intended effect as one request. [S2]
|
||||
|
||||
## 어떻게 검증할 것인가
|
||||
|
||||
이 절은 ‘주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 검증 절차, 성공 기준, 관측 지표, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
검증 계획은 주장과 관측을 일대일로 연결한다.
|
||||
1. 핵심 주장마다 확인 가능한 로그, 테스트, 상태 또는 출처를 지정한다.
|
||||
2. 정상 경로뿐 아니라 실패 경로와 복구 경로를 실행한다.
|
||||
3. 성공 기준과 중단 기준을 실행 전에 고정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Exponential backoff increases the delay between retry attempts and should use bounded limits. [S3]
|
||||
|
||||
## 대안, 트레이드오프, 실패 조건
|
||||
|
||||
이 절은 ‘언제 이 접근법을 선택하지 말아야 하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 대안, 얻는 것과 잃는 것, 적용 한계이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
이 접근은 구조와 검증 가능성을 얻는 대신 초기 설계와 근거 정리에 비용이 든다. 빠른 초안만 필요한 상황에서는 과할 수 있고, 규제·운영 위험이 큰 문서에서는 더 강한 사실 검증이 필요하다.
|
||||
대안은 더 자유로운 서술, 단일 모델 작성, 수동 리뷰다. 선택 기준은 문서의 위험도, 변경 빈도, 독자의 숙련도, 검증 비용이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 실무 적용 체크리스트
|
||||
|
||||
실무 적용 전 다음을 확인한다.
|
||||
- 독자 목표와 비범위를 한 문장으로 고정했는가?
|
||||
- 판단 기준과 근거가 연결되어 있는가?
|
||||
- 예시가 시작 상태부터 검증 결과까지 이어지는가?
|
||||
- 실패 조건, 중단 기준, 롤백이 있는가?
|
||||
- 버전 또는 시점이 드러나는가?
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 결론
|
||||
|
||||
기억해야 할 판단은 하나다. **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.** 독자의 다음 행동은 자신의 환경에서 재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다을 검증 가능한 기준으로 바꾸는 것이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"score": 87.5,
|
||||
"word_count": 1040,
|
||||
"issues": [
|
||||
{
|
||||
"code": "READ002",
|
||||
"severity": "warning",
|
||||
"message": "Paragraph contains 8 sentences.",
|
||||
"line": 5,
|
||||
"section": "",
|
||||
"suggestion": "Keep one central point per paragraph."
|
||||
},
|
||||
{
|
||||
"code": "READ002",
|
||||
"severity": "warning",
|
||||
"message": "Paragraph contains 8 sentences.",
|
||||
"line": 11,
|
||||
"section": "",
|
||||
"suggestion": "Keep one central point per paragraph."
|
||||
},
|
||||
{
|
||||
"code": "READ002",
|
||||
"severity": "warning",
|
||||
"message": "Paragraph contains 8 sentences.",
|
||||
"line": 17,
|
||||
"section": "",
|
||||
"suggestion": "Keep one central point per paragraph."
|
||||
},
|
||||
{
|
||||
"code": "READ002",
|
||||
"severity": "warning",
|
||||
"message": "Paragraph contains 13 sentences.",
|
||||
"line": 23,
|
||||
"section": "",
|
||||
"suggestion": "Keep one central point per paragraph."
|
||||
},
|
||||
{
|
||||
"code": "READ002",
|
||||
"severity": "warning",
|
||||
"message": "Paragraph contains 13 sentences.",
|
||||
"line": 40,
|
||||
"section": "",
|
||||
"suggestion": "Keep one central point per paragraph."
|
||||
}
|
||||
],
|
||||
"metrics": {
|
||||
"heading_count": 10,
|
||||
"h2_count": 9,
|
||||
"source_count": 3,
|
||||
"cited_source_count": 3,
|
||||
"numbered_steps": true,
|
||||
"has_verification": true,
|
||||
"has_tradeoffs": true,
|
||||
"severity_counts": {
|
||||
"warning": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# Deterministic lint report
|
||||
|
||||
- Score: **87.5/100**
|
||||
- Word count: **1040**
|
||||
- Issues: **5**
|
||||
|
||||
| Severity | Code | Location | Finding | Suggested correction |
|
||||
|---|---|---|---|---|
|
||||
| warning | `READ002` | line 5 | Paragraph contains 8 sentences. | Keep one central point per paragraph. |
|
||||
| warning | `READ002` | line 11 | Paragraph contains 8 sentences. | Keep one central point per paragraph. |
|
||||
| warning | `READ002` | line 17 | Paragraph contains 8 sentences. | Keep one central point per paragraph. |
|
||||
| warning | `READ002` | line 23 | Paragraph contains 13 sentences. | Keep one central point per paragraph. |
|
||||
| warning | `READ002` | line 40 | Paragraph contains 13 sentences. | Keep one central point per paragraph. |
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"round": 1,
|
||||
"deterministic_score": 87.5,
|
||||
"model_mean_score": 90.5,
|
||||
"composite_score": 89.3,
|
||||
"blockers": 0,
|
||||
"errors": 0,
|
||||
"passed": true
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"role": "logic",
|
||||
"provider": "mock",
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The logic review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": [],
|
||||
"raw_response": "{\n \"score\": 90.5,\n \"dimension_scores\": {\n \"reader_goal_alignment\": 90.5,\n \"information_architecture\": 90.5,\n \"logical_flow\": 90.5,\n \"cognitive_load\": 91.5,\n \"evidence_traceability\": 90.5,\n \"example_verifiability\": 90.5,\n \"scannability\": 91.5,\n \"operational_safety\": 90.5,\n \"completeness_and_limits\": 90.5\n },\n \"issues\": [],\n \"strengths\": [\n \"The logic review found the document contract explicit and inspectable.\"\n ],\n \"questions\": []\n}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The logic review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"role": "reader",
|
||||
"provider": "mock",
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The reader review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": [],
|
||||
"raw_response": "{\n \"score\": 90.5,\n \"dimension_scores\": {\n \"reader_goal_alignment\": 90.5,\n \"information_architecture\": 90.5,\n \"logical_flow\": 90.5,\n \"cognitive_load\": 91.5,\n \"evidence_traceability\": 90.5,\n \"example_verifiability\": 90.5,\n \"scannability\": 91.5,\n \"operational_safety\": 90.5,\n \"completeness_and_limits\": 90.5\n },\n \"issues\": [],\n \"strengths\": [\n \"The reader review found the document contract explicit and inspectable.\"\n ],\n \"questions\": []\n}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The reader review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"role": "evidence",
|
||||
"provider": "mock",
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The evidence review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": [],
|
||||
"raw_response": "{\n \"score\": 90.5,\n \"dimension_scores\": {\n \"reader_goal_alignment\": 90.5,\n \"information_architecture\": 90.5,\n \"logical_flow\": 90.5,\n \"cognitive_load\": 91.5,\n \"evidence_traceability\": 90.5,\n \"example_verifiability\": 90.5,\n \"scannability\": 91.5,\n \"operational_safety\": 90.5,\n \"completeness_and_limits\": 90.5\n },\n \"issues\": [],\n \"strengths\": [\n \"The evidence review found the document contract explicit and inspectable.\"\n ],\n \"questions\": []\n}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The evidence review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"role": "operations",
|
||||
"provider": "mock",
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The operations review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": [],
|
||||
"raw_response": "{\n \"score\": 90.5,\n \"dimension_scores\": {\n \"reader_goal_alignment\": 90.5,\n \"information_architecture\": 90.5,\n \"logical_flow\": 90.5,\n \"cognitive_load\": 91.5,\n \"evidence_traceability\": 90.5,\n \"example_verifiability\": 90.5,\n \"scannability\": 91.5,\n \"operational_safety\": 90.5,\n \"completeness_and_limits\": 90.5\n },\n \"issues\": [],\n \"strengths\": [\n \"The operations review found the document contract explicit and inspectable.\"\n ],\n \"questions\": []\n}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"score": 90.5,
|
||||
"dimension_scores": {
|
||||
"reader_goal_alignment": 90.5,
|
||||
"information_architecture": 90.5,
|
||||
"logical_flow": 90.5,
|
||||
"cognitive_load": 91.5,
|
||||
"evidence_traceability": 90.5,
|
||||
"example_verifiability": 90.5,
|
||||
"scannability": 91.5,
|
||||
"operational_safety": 90.5,
|
||||
"completeness_and_limits": 90.5
|
||||
},
|
||||
"issues": [],
|
||||
"strengths": [
|
||||
"The operations review found the document contract explicit and inspectable."
|
||||
],
|
||||
"questions": []
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"created_at": "2026-07-23T09:01:54+00:00",
|
||||
"document": "API 재시도는 횟수가 아니라 부하 예산으로 설계한다",
|
||||
"document_type": "technical_blog",
|
||||
"passed": true,
|
||||
"final_score": 89.3,
|
||||
"rounds": [
|
||||
{
|
||||
"round": 1,
|
||||
"draft": "rounds/round-01/draft.md",
|
||||
"deterministic_score": 87.5,
|
||||
"review_scores": {
|
||||
"logic": 90.5,
|
||||
"reader": 90.5,
|
||||
"evidence": 90.5,
|
||||
"operations": 90.5
|
||||
},
|
||||
"composite_score": 89.3,
|
||||
"blockers": 0,
|
||||
"errors": 0,
|
||||
"passed": true
|
||||
}
|
||||
],
|
||||
"warnings": [
|
||||
"All providers are deterministic mocks. This run validates pipeline mechanics only; model-review scores are synthetic and must not be used as evidence of document quality."
|
||||
],
|
||||
"artifacts": {
|
||||
"document": "final/document.md",
|
||||
"quality_report": "final/quality-report.md",
|
||||
"outline": "stages/02-outline.json",
|
||||
"events": "provider-events.jsonl"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"title": "API 재시도는 횟수가 아니라 부하 예산으로 설계한다",
|
||||
"document_type": "technical_blog",
|
||||
"sections": [
|
||||
{
|
||||
"id": "01-reader-promise",
|
||||
"intent": "reader_promise",
|
||||
"title": "먼저 결론: 무엇을 해결하는가",
|
||||
"reader_question": "이 글을 읽으면 무엇을 이해하거나 결정할 수 있는가?",
|
||||
"purpose": "독자의 문제, 글의 범위, 핵심 결론을 첫 화면에서 약속한다.",
|
||||
"must_include": [
|
||||
"독자 목표",
|
||||
"핵심 메시지",
|
||||
"범위와 비범위",
|
||||
"재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다",
|
||||
"재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.",
|
||||
"서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책",
|
||||
"정책을 검증하는 운영 지표와 실패 실험",
|
||||
"메시지 큐의 전달 보장 전체 설계",
|
||||
"특정 클라우드 SDK의 모든 기본값",
|
||||
"정확히 한 번 처리 보장"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "02-context-problem",
|
||||
"intent": "context_problem",
|
||||
"title": "문제가 생기는 맥락과 제약",
|
||||
"reader_question": "왜 이 문제가 실제 시스템에서 어려워지는가?",
|
||||
"purpose": "문제의 배경, 실패 양상, 제약을 구체화한다.",
|
||||
"must_include": [
|
||||
"현상",
|
||||
"원인 후보",
|
||||
"제약",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S2"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "03-mental-model",
|
||||
"intent": "mental_model",
|
||||
"title": "핵심 판단 기준과 멘털 모델",
|
||||
"reader_question": "뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?",
|
||||
"purpose": "낯선 개념을 익숙한 개념과 연결하고 판단 기준을 제시한다.",
|
||||
"must_include": [
|
||||
"용어 정의",
|
||||
"인과 관계",
|
||||
"판단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S3"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "04-mechanism",
|
||||
"intent": "mechanism",
|
||||
"title": "해결 방식이 동작하는 과정",
|
||||
"reader_question": "구성요소와 데이터 흐름은 어떻게 연결되는가?",
|
||||
"purpose": "선택한 접근법의 메커니즘을 단계적 인과 사슬로 설명한다.",
|
||||
"must_include": [
|
||||
"구성요소",
|
||||
"데이터 또는 제어 흐름",
|
||||
"불변조건",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "05-worked-example",
|
||||
"intent": "worked_example",
|
||||
"title": "끝까지 따라가는 구현 예시",
|
||||
"reader_question": "구체적인 입력이 어떻게 결과로 바뀌는가?",
|
||||
"purpose": "시작 상태부터 검증 가능한 결과까지 하나의 예시를 완주한다.",
|
||||
"must_include": [
|
||||
"초기 조건",
|
||||
"단계별 변화",
|
||||
"최종 결과",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S2"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "06-evidence-verification",
|
||||
"intent": "evidence_verification",
|
||||
"title": "어떻게 검증할 것인가",
|
||||
"reader_question": "주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?",
|
||||
"purpose": "관측값, 테스트, 성공 기준을 명시한다.",
|
||||
"must_include": [
|
||||
"검증 절차",
|
||||
"성공 기준",
|
||||
"관측 지표",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S3"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "07-tradeoffs",
|
||||
"intent": "tradeoffs",
|
||||
"title": "대안, 트레이드오프, 실패 조건",
|
||||
"reader_question": "언제 이 접근법을 선택하지 말아야 하는가?",
|
||||
"purpose": "대안과 비용, 한계, 실패 조건을 함께 제시한다.",
|
||||
"must_include": [
|
||||
"대안",
|
||||
"얻는 것과 잃는 것",
|
||||
"적용 한계"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "08-action",
|
||||
"intent": "action",
|
||||
"title": "실무 적용 체크리스트",
|
||||
"reader_question": "독자가 자신의 환경에서 무엇부터 확인해야 하는가?",
|
||||
"purpose": "결정을 실제 행동으로 전환하는 짧은 체크리스트를 제공한다.",
|
||||
"must_include": [
|
||||
"사전 점검",
|
||||
"점진적 적용",
|
||||
"중단 또는 롤백 기준"
|
||||
],
|
||||
"evidence_ids": [],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "09-conclusion",
|
||||
"intent": "conclusion",
|
||||
"title": "결론",
|
||||
"reader_question": "독자가 기억해야 할 하나의 판단은 무엇인가?",
|
||||
"purpose": "핵심 메시지를 반복이 아닌 압축된 판단으로 마무리한다.",
|
||||
"must_include": [
|
||||
"핵심 판단",
|
||||
"다음 행동"
|
||||
],
|
||||
"evidence_ids": [],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
}
|
||||
],
|
||||
"planning_notes": [
|
||||
"Each section answers one reader question.",
|
||||
"The order moves from reader goal to context, model, mechanism, evidence, limits, and action as applicable.",
|
||||
"Required section intents are a contract; a model may refine wording but must not remove or reorder them."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"title": "API 재시도는 횟수가 아니라 부하 예산으로 설계한다",
|
||||
"document_type": "technical_blog",
|
||||
"sections": [
|
||||
{
|
||||
"id": "01-reader-promise",
|
||||
"intent": "reader_promise",
|
||||
"title": "먼저 결론: 무엇을 해결하는가",
|
||||
"reader_question": "이 글을 읽으면 무엇을 이해하거나 결정할 수 있는가?",
|
||||
"purpose": "독자의 문제, 글의 범위, 핵심 결론을 첫 화면에서 약속한다.",
|
||||
"must_include": [
|
||||
"독자 목표",
|
||||
"핵심 메시지",
|
||||
"범위와 비범위",
|
||||
"재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다",
|
||||
"재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.",
|
||||
"서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책",
|
||||
"정책을 검증하는 운영 지표와 실패 실험",
|
||||
"메시지 큐의 전달 보장 전체 설계",
|
||||
"특정 클라우드 SDK의 모든 기본값",
|
||||
"정확히 한 번 처리 보장"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "02-context-problem",
|
||||
"intent": "context_problem",
|
||||
"title": "문제가 생기는 맥락과 제약",
|
||||
"reader_question": "왜 이 문제가 실제 시스템에서 어려워지는가?",
|
||||
"purpose": "문제의 배경, 실패 양상, 제약을 구체화한다.",
|
||||
"must_include": [
|
||||
"현상",
|
||||
"원인 후보",
|
||||
"제약",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S2"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "03-mental-model",
|
||||
"intent": "mental_model",
|
||||
"title": "핵심 판단 기준과 멘털 모델",
|
||||
"reader_question": "뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?",
|
||||
"purpose": "낯선 개념을 익숙한 개념과 연결하고 판단 기준을 제시한다.",
|
||||
"must_include": [
|
||||
"용어 정의",
|
||||
"인과 관계",
|
||||
"판단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S3"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "04-mechanism",
|
||||
"intent": "mechanism",
|
||||
"title": "해결 방식이 동작하는 과정",
|
||||
"reader_question": "구성요소와 데이터 흐름은 어떻게 연결되는가?",
|
||||
"purpose": "선택한 접근법의 메커니즘을 단계적 인과 사슬로 설명한다.",
|
||||
"must_include": [
|
||||
"구성요소",
|
||||
"데이터 또는 제어 흐름",
|
||||
"불변조건",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "05-worked-example",
|
||||
"intent": "worked_example",
|
||||
"title": "끝까지 따라가는 구현 예시",
|
||||
"reader_question": "구체적인 입력이 어떻게 결과로 바뀌는가?",
|
||||
"purpose": "시작 상태부터 검증 가능한 결과까지 하나의 예시를 완주한다.",
|
||||
"must_include": [
|
||||
"초기 조건",
|
||||
"단계별 변화",
|
||||
"최종 결과",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S2"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "06-evidence-verification",
|
||||
"intent": "evidence_verification",
|
||||
"title": "어떻게 검증할 것인가",
|
||||
"reader_question": "주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?",
|
||||
"purpose": "관측값, 테스트, 성공 기준을 명시한다.",
|
||||
"must_include": [
|
||||
"검증 절차",
|
||||
"성공 기준",
|
||||
"관측 지표",
|
||||
"재시도의 부하 증폭",
|
||||
"멱등성",
|
||||
"지수 백오프",
|
||||
"지터",
|
||||
"재시도 한도",
|
||||
"성공 및 중단 기준"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S3"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "07-tradeoffs",
|
||||
"intent": "tradeoffs",
|
||||
"title": "대안, 트레이드오프, 실패 조건",
|
||||
"reader_question": "언제 이 접근법을 선택하지 말아야 하는가?",
|
||||
"purpose": "대안과 비용, 한계, 실패 조건을 함께 제시한다.",
|
||||
"must_include": [
|
||||
"대안",
|
||||
"얻는 것과 잃는 것",
|
||||
"적용 한계"
|
||||
],
|
||||
"evidence_ids": [
|
||||
"S1"
|
||||
],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "08-action",
|
||||
"intent": "action",
|
||||
"title": "실무 적용 체크리스트",
|
||||
"reader_question": "독자가 자신의 환경에서 무엇부터 확인해야 하는가?",
|
||||
"purpose": "결정을 실제 행동으로 전환하는 짧은 체크리스트를 제공한다.",
|
||||
"must_include": [
|
||||
"사전 점검",
|
||||
"점진적 적용",
|
||||
"중단 또는 롤백 기준"
|
||||
],
|
||||
"evidence_ids": [],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
},
|
||||
{
|
||||
"id": "09-conclusion",
|
||||
"intent": "conclusion",
|
||||
"title": "결론",
|
||||
"reader_question": "독자가 기억해야 할 하나의 판단은 무엇인가?",
|
||||
"purpose": "핵심 메시지를 반복이 아닌 압축된 판단으로 마무리한다.",
|
||||
"must_include": [
|
||||
"핵심 판단",
|
||||
"다음 행동"
|
||||
],
|
||||
"evidence_ids": [],
|
||||
"transition_to_next": "이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다."
|
||||
}
|
||||
],
|
||||
"planning_notes": [
|
||||
"Each section answers one reader question.",
|
||||
"The order moves from reader goal to context, model, mechanism, evidence, limits, and action as applicable.",
|
||||
"Required section intents are a contract; a model may refine wording but must not remove or reorder them."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
# Outline contract: API 재시도는 횟수가 아니라 부하 예산으로 설계한다
|
||||
|
||||
## 먼저 결론: 무엇을 해결하는가
|
||||
|
||||
- Intent: `reader_promise`
|
||||
- Reader question: 이 글을 읽으면 무엇을 이해하거나 결정할 수 있는가?
|
||||
- Purpose: 독자의 문제, 글의 범위, 핵심 결론을 첫 화면에서 약속한다.
|
||||
- Must include: 독자 목표, 핵심 메시지, 범위와 비범위, 재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다, 재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다., 서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책, 정책을 검증하는 운영 지표와 실패 실험, 메시지 큐의 전달 보장 전체 설계, 특정 클라우드 SDK의 모든 기본값, 정확히 한 번 처리 보장
|
||||
- Evidence IDs: S1
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 문제가 생기는 맥락과 제약
|
||||
|
||||
- Intent: `context_problem`
|
||||
- Reader question: 왜 이 문제가 실제 시스템에서 어려워지는가?
|
||||
- Purpose: 문제의 배경, 실패 양상, 제약을 구체화한다.
|
||||
- Must include: 현상, 원인 후보, 제약, 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준
|
||||
- Evidence IDs: S2
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 핵심 판단 기준과 멘털 모델
|
||||
|
||||
- Intent: `mental_model`
|
||||
- Reader question: 뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?
|
||||
- Purpose: 낯선 개념을 익숙한 개념과 연결하고 판단 기준을 제시한다.
|
||||
- Must include: 용어 정의, 인과 관계, 판단 기준
|
||||
- Evidence IDs: S3
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 해결 방식이 동작하는 과정
|
||||
|
||||
- Intent: `mechanism`
|
||||
- Reader question: 구성요소와 데이터 흐름은 어떻게 연결되는가?
|
||||
- Purpose: 선택한 접근법의 메커니즘을 단계적 인과 사슬로 설명한다.
|
||||
- Must include: 구성요소, 데이터 또는 제어 흐름, 불변조건, 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준
|
||||
- Evidence IDs: S1
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 끝까지 따라가는 구현 예시
|
||||
|
||||
- Intent: `worked_example`
|
||||
- Reader question: 구체적인 입력이 어떻게 결과로 바뀌는가?
|
||||
- Purpose: 시작 상태부터 검증 가능한 결과까지 하나의 예시를 완주한다.
|
||||
- Must include: 초기 조건, 단계별 변화, 최종 결과, 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준
|
||||
- Evidence IDs: S2
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 어떻게 검증할 것인가
|
||||
|
||||
- Intent: `evidence_verification`
|
||||
- Reader question: 주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?
|
||||
- Purpose: 관측값, 테스트, 성공 기준을 명시한다.
|
||||
- Must include: 검증 절차, 성공 기준, 관측 지표, 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준
|
||||
- Evidence IDs: S3
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 대안, 트레이드오프, 실패 조건
|
||||
|
||||
- Intent: `tradeoffs`
|
||||
- Reader question: 언제 이 접근법을 선택하지 말아야 하는가?
|
||||
- Purpose: 대안과 비용, 한계, 실패 조건을 함께 제시한다.
|
||||
- Must include: 대안, 얻는 것과 잃는 것, 적용 한계
|
||||
- Evidence IDs: S1
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 실무 적용 체크리스트
|
||||
|
||||
- Intent: `action`
|
||||
- Reader question: 독자가 자신의 환경에서 무엇부터 확인해야 하는가?
|
||||
- Purpose: 결정을 실제 행동으로 전환하는 짧은 체크리스트를 제공한다.
|
||||
- Must include: 사전 점검, 점진적 적용, 중단 또는 롤백 기준
|
||||
- Evidence IDs: —
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
|
||||
## 결론
|
||||
|
||||
- Intent: `conclusion`
|
||||
- Reader question: 독자가 기억해야 할 하나의 판단은 무엇인가?
|
||||
- Purpose: 핵심 메시지를 반복이 아닌 압축된 판단으로 마무리한다.
|
||||
- Must include: 핵심 판단, 다음 행동
|
||||
- Evidence IDs: —
|
||||
- Transition: 이 답을 바탕으로 다음 독자 질문으로 자연스럽게 연결한다.
|
||||
@@ -0,0 +1,74 @@
|
||||
# API 재시도는 횟수가 아니라 부하 예산으로 설계한다
|
||||
|
||||
## 먼저 결론: 무엇을 해결하는가
|
||||
|
||||
이 글의 독자는 백엔드 개발자, 플랫폼 엔지니어이다. 읽고 나면 **재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다**할 수 있어야 한다. 먼저 결론부터 말하면, 재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.
|
||||
범위는 서비스 간 동기 HTTP 호출의 클라이언트 재시도 정책, 정책을 검증하는 운영 지표와 실패 실험이다. 합리적으로 기대할 수 있지만 이 글에서 다루지 않는 범위는 메시지 큐의 전달 보장 전체 설계, 특정 클라우드 SDK의 모든 기본값, 정확히 한 번 처리 보장이다. 적용 맥락은 HTTP 의미론은 RFC 9110, 예시는 2026-07-23 기준이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 문제가 생기는 맥락과 제약
|
||||
|
||||
이 절은 ‘왜 이 문제가 실제 시스템에서 어려워지는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 현상, 원인 후보, 제약, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
현실의 문제는 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준가 독립적으로 움직이지 않는다는 점이다. 입력, 상태, 시간, 실패 복구가 연결되므로 한 요소만 최적화하면 다른 경로에서 비용이 나타날 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 핵심 판단 기준과 멘털 모델
|
||||
|
||||
이 절은 ‘뒤의 세부사항을 이해하려면 어떤 모델이 필요한가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 용어 정의, 인과 관계, 판단 기준이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
멘털 모델은 ‘입력 → 판단 기준 → 상태 변화 → 관측 결과’의 네 칸으로 잡는다. 재시도의 부하 증폭, 멱등성, 지수 백오프, 지터, 재시도 한도, 성공 및 중단 기준를 이 흐름에 배치하면 구현 세부사항이 바뀌어도 인과 관계를 추적할 수 있다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
|
||||
## 해결 방식이 동작하는 과정
|
||||
|
||||
이 절은 ‘구성요소와 데이터 흐름은 어떻게 연결되는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 구성요소, 데이터 또는 제어 흐름, 불변조건, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
동작은 다음 인과 순서로 이해할 수 있다.
|
||||
1. 입력과 사전 조건을 검증하고 처리 가능한 상태인지 확인한다.
|
||||
2. 명시된 판단 기준으로 경로를 선택하고 상태 변경 범위를 제한한다.
|
||||
3. 결과를 기록한 뒤 성공 기준과 비교해 다음 행동을 결정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 끝까지 따라가는 구현 예시
|
||||
|
||||
이 절은 ‘구체적인 입력이 어떻게 결과로 바뀌는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 초기 조건, 단계별 변화, 최종 결과, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
아래는 특정 제품의 실제 측정값이 아니라 판단 흐름을 드러내기 위한 예시다.
|
||||
```text
|
||||
입력: 변경 요청과 현재 상태
|
||||
판단: 사전 조건 충족 여부 → 안전한 실행 경로 선택
|
||||
실행: 최소 범위 변경
|
||||
관측: 예상 상태와 실제 상태 비교
|
||||
결과: 성공이면 확정, 불일치면 중단 후 복구
|
||||
```
|
||||
예시의 핵심은 명령 자체가 아니라 각 단계의 입력, 판단, 관측이 끊기지 않는다는 점이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A request method is idempotent when multiple identical requests have the same intended effect as one request. [S2]
|
||||
|
||||
## 어떻게 검증할 것인가
|
||||
|
||||
이 절은 ‘주장이 맞고 구현이 동작한다는 것을 어떻게 확인하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 검증 절차, 성공 기준, 관측 지표, 재시도의 부하 증폭, 멱등성이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
검증 계획은 주장과 관측을 일대일로 연결한다.
|
||||
1. 핵심 주장마다 확인 가능한 로그, 테스트, 상태 또는 출처를 지정한다.
|
||||
2. 정상 경로뿐 아니라 실패 경로와 복구 경로를 실행한다.
|
||||
3. 성공 기준과 중단 기준을 실행 전에 고정한다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Exponential backoff increases the delay between retry attempts and should use bounded limits. [S3]
|
||||
|
||||
## 대안, 트레이드오프, 실패 조건
|
||||
|
||||
이 절은 ‘언제 이 접근법을 선택하지 말아야 하는가?’에 답한다. 판단의 기준은 **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.**이다. 다룰 핵심 항목은 대안, 얻는 것과 잃는 것, 적용 한계이며, 설명은 독자의 목표인 “재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다”에 필요한 범위로 제한한다.
|
||||
이 접근은 구조와 검증 가능성을 얻는 대신 초기 설계와 근거 정리에 비용이 든다. 빠른 초안만 필요한 상황에서는 과할 수 있고, 규제·운영 위험이 큰 문서에서는 더 강한 사실 검증이 필요하다.
|
||||
대안은 더 자유로운 서술, 단일 모델 작성, 수동 리뷰다. 선택 기준은 문서의 위험도, 변경 빈도, 독자의 숙련도, 검증 비용이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retries can increase load on a dependency that is already failing. [S1]
|
||||
|
||||
## 실무 적용 체크리스트
|
||||
|
||||
실무 적용 전 다음을 확인한다.
|
||||
- 독자 목표와 비범위를 한 문장으로 고정했는가?
|
||||
- 판단 기준과 근거가 연결되어 있는가?
|
||||
- 예시가 시작 상태부터 검증 결과까지 이어지는가?
|
||||
- 실패 조건, 중단 기준, 롤백이 있는가?
|
||||
- 버전 또는 시점이 드러나는가?
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions. [S2]
|
||||
|
||||
## 결론
|
||||
|
||||
기억해야 할 판단은 하나다. **재시도는 성공 확률을 높이는 무료 기능이 아니라 실패 중인 의존성에 추가 부하를 보내는 예산이므로, 멱등성·한도·백오프·지터·관측성을 하나의 정책으로 묶어야 한다.** 독자의 다음 행동은 자신의 환경에서 재시도가 장애를 증폭하지 않도록 타임아웃, 재시도 횟수, 백오프, 지터, 멱등성을 함께 설계한다을 검증 가능한 기준으로 바꾸는 것이다.
|
||||
제공된 근거 팩은 다음 사실을 확인 대상으로 제시한다: Retry behavior should consider whether the operation is idempotent. [S3]
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"sources": [
|
||||
{
|
||||
"id": "S1",
|
||||
"title": "Timeouts, retries, and backoff with jitter",
|
||||
"url": "https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/",
|
||||
"publisher": "Amazon Web Services Builders’ Library",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"Retries can increase load on a dependency that is already failing.",
|
||||
"Exponential backoff limits retry frequency, and jitter spreads retry timing across clients.",
|
||||
"Retry behavior should be bounded rather than continuing indefinitely."
|
||||
],
|
||||
"notes": "Use for retry-load, backoff, jitter, and bounded-retry claims."
|
||||
},
|
||||
{
|
||||
"id": "S2",
|
||||
"title": "RFC 9110, HTTP Semantics — Idempotent Methods",
|
||||
"url": "https://datatracker.ietf.org/doc/html/rfc9110#section-9.2.2",
|
||||
"publisher": "IETF",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"A request method is idempotent when multiple identical requests have the same intended effect as one request.",
|
||||
"A client can automatically retry an idempotent request after a communication failure before reading the response, subject to the specification's conditions."
|
||||
],
|
||||
"notes": "Use for the definition and retry implications of HTTP method idempotency."
|
||||
},
|
||||
{
|
||||
"id": "S3",
|
||||
"title": "Retry strategy",
|
||||
"url": "https://cloud.google.com/storage/docs/retry-strategy",
|
||||
"publisher": "Google Cloud",
|
||||
"accessed": "2026-07-23",
|
||||
"facts": [
|
||||
"Retry behavior should consider whether the operation is idempotent.",
|
||||
"Exponential backoff increases the delay between retry attempts and should use bounded limits."
|
||||
],
|
||||
"notes": "Use as a second implementation-oriented source for bounded backoff and idempotency checks."
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user