4.9 KiB
4.9 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label, target_audience, inspiration_url, archive_url
| title | source_type | status | related_branches | related_projects | tags | created | status_label | target_audience | inspiration_url | archive_url | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| blog-topic / idempotency-executor-application-layer-clean-architecture-2026-06-09 | blog-topic | raw |
|
|
|
2026-06-09 | ready-for-canonical | backend-engineer |
blog-topic: 멱등성을 application layer 실행기로 — Clean Architecture에서 rate-limit/idempotency 운영 계약
Layer:
raw/blog-topics/— feature-rate-limit-idempotency-contract 구현에서 나온 글감.
Parent / 부모
글감 / Topic
운영 멱등성과 rate-limit을 "프레임워크 미들웨어"가 아니라 계층 소유권으로 배치한 사례.
글감 / Topic seed
- 한 문장 요지: idempotency는 application-layer executor가, rate-limit은 presentation interceptor가 소유하도록 나눠 Clean Architecture 경계를 명시한다.
- 예상 제목 후보:
- 멱등성을 application layer 실행기로 두기
- Clean Architecture에서 idempotency와 rate-limit 소유권 나누기
다룰 포인트
- owner_layer 분리: idempotency 코드(409/422)는
owner_layer: application→IdempotencyExecutor포트 +IdempotencyStore포트 + DB 어댑터로 application/infra에 둠. rate-limit(429)은owner_layer: presentation→ adapter-webHandlerInterceptor. 같은 "운영 횡단 관심사"라도 코드/응답 소유 계층이 다르다. - filter vs interceptor: rate-limit key가
IP + uri_template(normalized)를 요구 → servlet filter는 handler mapping 이전이라 route template(/v1/worklogs/{id})을 모름.HandlerInterceptor로 옮겨BEST_MATCHING_PATTERN_ATTRIBUTE를 사용. - 명시적 실행기 vs AOP: KEYED use case를 BeanPostProcessor/AOP로 감싸는 대신
executor.execute(ctx, action, codec)명시 호출. 호출부가 약간 장황하지만 ArchUnit/테스트 단순성과 스켈레톤 투명성을 얻음. - insert-or-read + unique 제약을 동시성 중재자로: 200ms in-flight wait는 IETF 즉시-409 SHOULD의 "운영 친화적 변형"(표준 그대로 아님). fingerprint(SHA-256) mismatch는 IETF 422 권고 정합.
- port-codec 분리로 application의 wire-format 중립성: 실행기는
IdempotentResponseCodec<R>(web JSON 소유)로 직렬화만 위임 → application은 transport/storage 중립. - 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
- owner layer를 application과 presentation으로 나눈다.
- filter와 interceptor가 route template을 볼 수 있는 시점 차이를 설명한다.
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전 실제 구현 등급을 재확인한다.