102 lines
4.9 KiB
Markdown
102 lines
4.9 KiB
Markdown
---
|
|
title: blog-topic / idempotency-executor-application-layer-clean-architecture-2026-06-09
|
|
source_type: blog-topic
|
|
status: raw
|
|
related_branches: [feature-rate-limit-idempotency-contract]
|
|
related_projects: [ca-tmpl]
|
|
tags: [blog-topic, ca-tmpl, idempotency, clean-architecture, rate-limit]
|
|
created: 2026-06-09
|
|
status_label: ready-for-canonical
|
|
target_audience: backend-engineer
|
|
inspiration_url:
|
|
archive_url:
|
|
---
|
|
|
|
# blog-topic: 멱등성을 application layer 실행기로 — Clean Architecture에서 rate-limit/idempotency 운영 계약
|
|
|
|
> Layer: `raw/blog-topics/` — feature-rate-limit-idempotency-contract 구현에서 나온 글감.
|
|
|
|
## Parent / 부모
|
|
|
|
- [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
|
|
|
## 글감 / Topic
|
|
|
|
운영 멱등성과 rate-limit을 "프레임워크 미들웨어"가 아니라 **계층 소유권**으로 배치한 사례.
|
|
|
|
## 글감 / Topic seed
|
|
|
|
- 한 문장 요지: idempotency는 application-layer executor가, rate-limit은 presentation interceptor가 소유하도록 나눠 Clean Architecture 경계를 명시한다.
|
|
- 예상 제목 후보:
|
|
- 멱등성을 application layer 실행기로 두기
|
|
- Clean Architecture에서 idempotency와 rate-limit 소유권 나누기
|
|
|
|
### 다룰 포인트
|
|
|
|
1. **owner_layer 분리**: idempotency 코드(409/422)는 `owner_layer: application` → `IdempotencyExecutor`
|
|
포트 + `IdempotencyStore` 포트 + DB 어댑터로 application/infra에 둠. rate-limit(429)은
|
|
`owner_layer: presentation` → adapter-web `HandlerInterceptor`. 같은 "운영 횡단 관심사"라도 코드/응답
|
|
소유 계층이 다르다.
|
|
2. **filter vs interceptor**: rate-limit key가 `IP + uri_template(normalized)`를 요구 →
|
|
servlet filter는 handler mapping 이전이라 route template(`/v1/worklogs/{id}`)을 모름.
|
|
`HandlerInterceptor`로 옮겨 `BEST_MATCHING_PATTERN_ATTRIBUTE`를 사용.
|
|
3. **명시적 실행기 vs AOP**: KEYED use case를 BeanPostProcessor/AOP로 감싸는 대신 `executor.execute(ctx, action, codec)`
|
|
명시 호출. 호출부가 약간 장황하지만 ArchUnit/테스트 단순성과 스켈레톤 투명성을 얻음.
|
|
4. **insert-or-read + unique 제약을 동시성 중재자로**: 200ms in-flight wait는 IETF 즉시-409 SHOULD의
|
|
"운영 친화적 변형"(표준 그대로 아님). fingerprint(SHA-256) mismatch는 IETF 422 권고 정합.
|
|
5. **port-codec 분리로 application의 wire-format 중립성**: 실행기는 `IdempotentResponseCodec<R>`(web JSON 소유)로
|
|
직렬화만 위임 → application은 transport/storage 중립.
|
|
6. **UNSUPPORTED_IMPL_DECISION 정직성**: 200ms·SHA-256·8KB·fixed-window·canonicalization 미적용은
|
|
외부 표준이 강제하지 않음을 코드 주석에 명시 — "표준 따름" 과장 금지.
|
|
|
|
## 관련
|
|
|
|
- [[wiki/concepts/idempotency-key-design]]
|
|
- [[raw/errors/idempotency-expired-row-reclaim-409-loop-2026-06-09]]
|
|
- [[raw/errors/scheduled-reaper-wrong-config-prefix-2026-06-09]]
|
|
|
|
## Canonical 전환 후보 / Canonical extraction candidates
|
|
|
|
- `wiki/projects/ca-tmpl/idempotency-key-design.md` 후보:
|
|
- idempotency executor의 application-layer ownership와 rate-limit presentation ownership 분리.
|
|
- 필요한 추가 검증:
|
|
- `IdempotencyExecutor`, `IdempotencyStore`, response codec, interceptor 구현 여부.
|
|
|
|
## 트리거 / Trigger
|
|
|
|
- 트리거 유형: `branch-work`
|
|
- 트리거 날짜: 2026-06-09
|
|
- 트리거 연결 노트: [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
|
|
|
## 핵심 주장 후보 / Claim candidates
|
|
|
|
- 사실 후보:
|
|
- idempotency와 rate-limit은 같은 운영 횡단 관심사처럼 보여도 owner layer가 다르다.
|
|
- idempotency executor는 application/use case 실행 경계에 놓고, rate-limit은 route template을 아는 web interceptor가 맡는 구조다.
|
|
- 의견/해석 후보:
|
|
- AOP보다 명시 실행기가 skeleton 투명성과 테스트 용이성을 준다.
|
|
|
|
## Outline seed
|
|
|
|
1. owner layer를 application과 presentation으로 나눈다.
|
|
2. filter와 interceptor가 route template을 볼 수 있는 시점 차이를 설명한다.
|
|
3. `IdempotencyExecutor`와 response codec 분리로 wire format 중립성을 유지한다.
|
|
|
|
## Sources / 근거 후보
|
|
|
|
- [[raw/branch-notes/feature-rate-limit-idempotency-contract]]
|
|
- [[wiki/concepts/idempotency-key-design]]
|
|
- [[raw/errors/idempotency-expired-row-reclaim-409-loop-2026-06-09]]
|
|
- [[raw/errors/scheduled-reaper-wrong-config-prefix-2026-06-09]]
|
|
|
|
## 미해결 / Unknown
|
|
|
|
- 아직 확인해야 할 사실: 현재 ca-tmpl 코드의 executor/storage/interceptor 구현 여부.
|
|
- 과장하면 안 되는 부분: IETF draft 준수와 ca-tmpl의 200ms wait 변형을 섞지 않는다.
|
|
|
|
## Decision / 처리 결정
|
|
|
|
- 액션: `promote-to-canonical`
|
|
- 이유: `wiki/projects/ca-tmpl/idempotency-key-design.md` 에 application-layer idempotency executor 글감으로 반영했다.
|
|
- 다음 단계: target canonical이 아직 `draft` 이므로 `blogify` 전 실제 구현 등급을 재확인한다.
|