소프트웨어 아키텍처

ADR 실전

meellon 2026. 7. 10. 05:20

학습 목표

ADR 작성법 워크플로(PR·리뷰·합의)에 연결할 수 있다.

Supersede·Deprecated 절차양방향 링크운영할 수 있다.

docs/adr/ 저장소·인덱스·도구설계할 수 있다.

평가·구현 결과Proposed ADR을 Accepted승격하는 흐름을 설명할 수 있다.

문제 상황

  • ADR 템플릿만 있고 PR 붙음구현 잊음
  • Accepted 40개인데 어느현재 진실인지 모름Supersede 없음
  • 아키텍트 1명만 씀 — 은 " 문서 행정"으로 인식
  • Confluence 복사본repo 불일치어느 쪽이 맞는지 분쟁
  • 평가에서 ADR-0004 액션 나왔는데 티켓만 있고 ADR 파일 없음
  • Rejected ADR 삭제 — 6개월 뒤 같은 논쟁 재개

앞서 ADR 형식·평가 연동을 봤다. 이번 편은 조직계속 쓰게 만드는 운영이다.

1. 작성법 vs 운영

21편 (작성법) 23편 (운영)
섹션·Status 정의 누가 언제 갱신하는가
예제 ADR PR·리뷰·인덱스
개인 습관 규칙·도구
  • ADR 가치 = 검색 가능한 결정 역사 + 현재 준수 목록
  • 가벼울수록 좋음운영 부담커지면 포기

2. PR 워크플로

구조·통합·데이터 소유 변경 PR에는 ADR같은 브랜치포함한다.

단계 행동
1 Draft docs/adr/0004-....md Status: Proposed
2 PR C4·계약·코드 diff함께
3 Review 대안·트레이드오프 질문구현 세부 아님
4 Merge 합의Accepted갱신
5 Follow-up 구현 티켓·계약 버전 링크
PR 라벨 ADR
architecture 필수 검토
breaking-api 관련 ADR·계약
infra 배포·런타임 결정
PR checklist
[ ] Boundary or integration change?
[ ] ADR added or supersede link updated?
[ ] docs/adr/README.md index row added?
[ ] C4 / OpenAPI updated if structure changed?
  • Proposed먼저 올리면 리뷰결정 중심
  • Merge Accepted합의 시점 명확

3. 리뷰·합의

참석 역할
제안 리드 Context·제약 설명
영향 받는 Consequences 검증
아키텍트 대안·트레이드오프 촉진
SRE (해당 시) 가용성·운영 비용
리뷰 질문 나쁜 토론
지금? 프레임워크 취향
거절한 대안 충분? 코드 스타일
측정·롤백? 이름 짓기
누가 소유?  
  • 비동기 리뷰Context·Alternatives 먼저 읽게 안내
  • Rejectedmerge 함, 파일 남김 (재논의 방지)
  • 2주 Proposed 방치월간 스캔 대상

4. Supersede·폐기 실무

결정 전제깨지면 삭제 대신 Superseded·Deprecated.

동작 절차
Supersede 신 ADR Accepted → 구 ADR Superseded by NNNN → 신 ADR에 Supersedes NNNN
Deprecated 대체 없이 중단이유
Reject Proposed 유지 또는 Rejected대안 Accepted 링크
ADR-0005  sync Payment PG     (Superseded by 0004)
ADR-0004  async PaymentIntent (Accepted, supersedes 0005)
  • 양방향 링크 필수인덱스고치면 끊김
  • 코드 롤아웃 완료 Supersede 경로 아직 돌면 혼란
  • 앞서 평가 액션 ADR-00040005 대체 후보

예제 — 평가에서 나온 Proposed ADR

# ADR-0004: Async payment handoff via PaymentIntent event

- **Status:** Proposed
- **Date:** 2026-07-10
- **Deciders:** payment-team, order-team, platform-architecture
- **Related:** evaluation finding `perf-order-peak`, C4 Container (Order API, Payment API, Payment PG)
- **Supersedes:** ADR-0005 (on acceptance)

## Context

Architecture evaluation for flash-sale scenario (`perf-order-peak`) showed Order API p99 above 800ms under 10k concurrent checkouts.

Sensitivity analysis:

- Payment API thread pool and PG HTTPS timeout dominate tail latency
- Order API waits on synchronous payment confirmation in the place-order path

ADR-0005 chose synchronous PG calls for simpler reconciliation and faster MVP delivery. Constraints have changed:

- Checkout SLO now requires p99 <= 500ms at peak
- Payment team exposes idempotent `PaymentIntent` API and `PaymentCompleted` event
- Reconciliation job already runs nightly for PG settlement files

## Decision

Move payment authorization off the Order API critical path:

1. Order API publishes `PlaceOrder` and returns `orderId` with status `PAYMENT_PENDING`
2. Payment API consumes intent, calls PG asynchronously, emits `PaymentCompleted` or `PaymentFailed`
3. Order API transitions order state on payment events (idempotent consumer)
4. Client polls or subscribes via WebSocket for final status

Keep PG integration owned by Payment API only (same external boundary as ADR-0005).

## Consequences

### Positive

- Shorter Order API critical path; improved flash-sale latency
- Payment retries and PG outages isolated from order accept path
- Aligns with evaluation action item and load-test plan

### Negative

- UX moves from synchronous to pending state (poll or push required)
- Distributed state: order may exist before payment finality (compensating cancel flow)
- More contract tests across Order and Payment events

### Neutral

- ADR-0001 outbox still applies for `OrderPlaced`; payment events use separate topic

## Alternatives considered

| Option | Why not |
|--------|---------|
| Increase Payment API pool only | Does not remove PG tail from Order path |
| Cache PG responses | Incorrect for authorize; compliance risk |
| Keep sync path for VIP only | Two code paths; operational complexity |

## Follow-up

- Load test with 10k virtual users before Accepted
- On acceptance: mark ADR-0005 Superseded, update C4 dynamic view
- Add AsyncAPI entries for `PaymentIntent` and `PaymentCompleted`
단계  
Proposed PR + 부하 테스트
Accepted SLO 달성 + 0005 Superseded
문서 C4·AsyncAPI·인덱스 동시

5. 저장소·인덱스

docs/
  adr/
    README.md              # index table (below)
    0001-use-transactional-outbox.md
    0004-async-payment-handoff.md
    0005-sync-payment-pg.md
  c4/
  evaluation/

인덱스 (docs/adr/README.md):

# Architecture Decision Records

Living index for `docs/adr/`. Regenerate or edit when status changes.

| ID | Title | Status | Date | Supersedes / Superseded by |
|----|-------|--------|------|---------------------------|
| 0001 | Use transactional outbox for order events | Accepted | 2026-07-08 | — |
| 0002 | CDC for catalog search projection | Accepted | 2026-07-15 | — |
| 0003 | Modular monolith with hexagonal packages | Superseded | 2025-11-02 | → 0012 |
| 0004 | Async payment handoff via PaymentIntent event | Proposed | 2026-07-10 | replaces 0005 |
| 0005 | Synchronous Payment PG call from Payment API | Superseded | 2025-08-19 | → 0004 |
| 0012 | Split Order as independent deployable service | Accepted | 2026-03-20 | supersedes 0003 |

## Rules

- One decision per file: `NNNN-short-slug.md`
- Never delete; use Superseded / Deprecated / Rejected
- Link both ways on supersede pairs
- Structural PRs that change boundaries require ADR in the same PR (Proposed minimum)

## Review cadence

- Monthly: scan Proposed older than 14 days
- Quarterly: Accepted list vs C4 Container and evaluation findings
규칙 이유
README 온보딩 30초
번호 순차 충돌·참조
slug 고정 링크 불변
Confluence 미러 금지 single source

6. 도구

도구 용도
Markdown in git 기본PR diff
adr-tools adr new, 번호 자동
Log4brains 정적 사이트·검색
MADR 템플릿 메타 필드 표준
CI 인덱스·깨진 링크 검사
# ci excerpt — optional link check
- name: Verify ADR index mentions all files
  run: |
    for f in docs/adr/[0-9]*.md; do
      id=$(basename "$f" | cut -d- -f1)
      grep -q "$id" docs/adr/README.md || exit 1
    done
  • 소규모 git + README 으로 충분
  • 도구 도입 PR 규칙 먼저 정착

7. 평가·부채와 연동

이벤트 ADR 행동
평가 finding Proposed ADR 생성
부하 테스트 통과 Accepted 승격
가정 깨짐 Supersede 또는 Deprecated
기술 부채 상환 관련 ADR Follow-up 닫기
  • 앞서 evaluation-scenarios.json action 필드 → ADR 파일 생성
  • 분기 평가Accepted 목록 vs C4 diff

8. 안티패턴

안티패턴 대안
사후 Confluence 정리 PRProposed
인덱스 미갱신 merge 체크리스트
Supersede 없이 덮어쓰기 체인 유지
아키텍트 단독 작성 Deciders 명시·리뷰
Accepted 영원 분기 감사
삭제 Rejected·Superseded

9. 실무 체크리스트

질문 좋은 답
언제 Proposed? 설계 PR 시작
언제 Accepted? 합의 + 검증 완료
Supersede 순서? 신규 Accepted Superseded
인덱스 누가? PR 작성자
도구? git 우선, 필요adr-tools
주기? Proposed, 분기 Accepted 감사

10. 정리

  • ADR 운영 = PR·리뷰·인덱스·supersede 규칙
  • Proposed검증Accepted평가·테스트연결
  • README 현재 유효 결정 한눈
  • 삭제 금지, 양방향 링크
  • Part 7 운영 — 다음은 팀 토폴로지

다음에 다룰 것

  • 팀 토폴로지
  • Conway's Law, stream-aligned·platform 팀, 조직과 아키텍처 정렬

해당 내용은 Fundamentals of Software Architecture (Mark Richards, Neal Ford) 및 Documenting Architecture Decisions (Michael Nygard) 의 내용을 기반으로 합니다.

'소프트웨어 아키텍처' 카테고리의 다른 글

레거시 마이그레이션  (0) 2026.07.12
팀 토폴로지  (0) 2026.07.11
아키텍처 평가  (0) 2026.07.09
ADR과 의사결정 기록  (0) 2026.07.08
아키텍처 문서화  (0) 2026.07.07