소프트웨어 아키텍처

ADR과 의사결정 기록

meellon 2026. 7. 8. 05:20

학습 목표

ADR(Architecture Decision Record)가 무엇을·언제 남기는지 설명할 수 있다.

Context·Decision·Consequences·Alternatives 섹션을 실무 템플릿으로 작성할 수 있다.

Status(Proposed / Accepted / Superseded 등) 라이프사이클을 관리할 수 있다.

C4·API 계약ADR역할을 나누는 방식을 설명할 수 있다.

문제 상황

  • 2년 전 Kafka 도입 — "왜 RabbitMQ가 아닌가?" 슬랙 400줄 스크롤 후 포기
  • Outbox 테이블 추가 PR — 리뷰어 "이거 ?" — ADR 없음, 작성자 퇴사
  • Confluence "아키텍처 원칙" 12페이지현재 코드와 불일치, 누가 갱신할지 모름
  • MSA 전환 롤백 논의 — "당시 제약이 뭐였지?" — 회의록만 있고 결정 근거 없음
  • Supersede 없이 세 번째 API Gateway 도입 — 이전 결정이 Accepted남아 혼란
  • C4 Container는 있는데 Payment가 동기 PG 호출인지 문서 없음

앞서 구조(C4)·계약(OpenAPI)을 정리했다. 왜 그렇게 했는지는 별도 기록이 필요하다.

1. ADR이란

ADR아키텍처에 영향 있는 결정짧은 문서로 영구 보존.

C4 / API 계약 ADR
무엇이 연결되는가 그렇게 연결했는가
현재 구조 스냅샷 당시 맥락·대안·트레이드오프
변경 시 다이어그램 diff 결정 역사·폐기 이유
  • Michael Nygard — "Documenting Architecture Decisions" (2011)에서 가볍게 한 장 권장
  • Living documentation — ADR도 repo docs/adr/버전 관리
  • 코드 = 진실이지만 의도·거절한 길은 코드만으로 복구 어렵다

2. 언제 ADR을 쓰는가

쓴다 안 쓴다 (과도)
서비스 분해 경계·통합 방식 (REST vs 이벤트) 변수명·한 메서드 리팩터
데이터 소유·일관성 모델 (outbox, CDC) 프레임워크 기본 convention
브로커·캐시·DB 도입·교체 이미 합의한 코딩 스타일
품질 속성 트레이드오프 (latency vs consistency) 버그 fix 한 건
보안·규제 아키텍처 (PII 경계, 암호화)  
되돌리기 어려운 결정  
  • 비용이 큰 결정일수록 먼저 — 구현 쓰면 맥락 소실
  • 앞서 스타일 선택 플로우 마지막 단계 "Record ADR"와 동일 습관

3. ADR 구조 (Nygard / MADR)

섹션 내용
Title 결정 한 줄Use transactional outbox for order events
Status Proposed → Accepted / Rejected / Deprecated / Superseded
Date 결정일 (Accepted 기준)
Deciders 책임 팀·역할
Context 문제·제약·품질 속성가장 길게
Decision 선택한 것 — 명령형 한두 문단
Consequences 긍정 / 부정 / 중립
Alternatives 검토했으나 채택 안 한 옵션·이유
  • Context 없이 Decision만 — "" 재현 불가
  • Alternatives 없으면 — 나중에 "처음부터 이거밖에 없었나?" 의심
  • MADR 등 메타 필드(related, tags)는 규모에 맞게 추가

4. Status 라이프사이클

Status 의미
Proposed 리뷰 중 — 아직 합의 전
Accepted 적용·준수 기준
Rejected 검토채택 안 함이유 남김
Deprecated 더 이상 권장하지 않음 — 대체 없이 사라짐
Superseded 새 ADR대체Superseded by ADR-0007 링크
ADR-0003 Accepted  (modular monolith)
        │
        ▼ superseded
ADR-0012 Accepted  (split Order service)
  • 삭제하지 않는다 — 역사자산
  • Supersede양방향 링크 — 구 ADR에 by, 신 ADR에 replaces
  • 분기마다 Accepted ADR 목록 점검현재 구조와 불일치 찾기

5. 대안 비교를 ADR에 넣기

결정 ·다이어그램으로 대안짧게 비교한다.

기준 Dual write Outbox CDC primary
DB·이벤트 원자성 △ (지연)
운영 복잡도 낮음 중간 높음
도메인 이벤트 표현 △ (row change)
앞서 incident 회피
  • 정답 표가 아니라 당시 우선순위 반영
  • C4 Container에 Kafka가 있어도 outbox vs CDC는 ADR 없으면 재논의 반복

6. 예제 ADR

주문·이벤트 전파 — 앞서 dual write·outbox·CDC 맥락을 한 장으로.

# ADR-0001: Use transactional outbox for order events

- **Status:** Accepted
- **Date:** 2026-07-08
- **Deciders:** order-team, platform-architecture
- **Related:** C4 Container (Order API, Kafka), event catalog `order.events`

## Context

Order API must persist an order and publish `OrderPlaced` to Kafka so inventory and notification can react.

Dual write (DB commit then Kafka publish in application code) caused production incidents:

- DB committed, publish failed → inventory never reserved
- Publish succeeded, DB rolled back → ghost events in downstream projections

We need atomicity between the order row and the outbox row in the same PostgreSQL transaction. CDC from WAL is viable for read-model sync but does not replace an explicit domain event at write time for this flow.

Constraints:

- Team already runs PostgreSQL and Kafka
- Target at-least-once delivery with idempotent consumers
- No XA / 2PC across services

## Decision

Use the **transactional outbox** pattern in Order API:

1. In the same DB transaction: `INSERT orders` + `INSERT outbox_events`
2. A relay process polls `outbox_events` with `FOR UPDATE SKIP LOCKED` and publishes to Kafka
3. Mark outbox row `published` after broker ack (or rely on idempotent publish + status column)

Event schema and topic ownership stay in the provider contract (`order.events`, AsyncAPI).

## Consequences

### Positive

- Atomicity without distributed transactions
- Replay from outbox table on relay failure
- Aligns with DB-as-source-of-truth and eventual consistency SLO

### Negative

- Extra table, relay job, and monitoring
- Slight publish latency (poll interval, typically sub-second to few seconds)
- Consumers must be idempotent (at-least-once)

### Neutral

- CDC can still feed search/analytics from `orders` table later; not mutually exclusive

## Alternatives considered

| Option | Why not (for now) |
|--------|-------------------|
| Dual write in service | No atomicity; already caused incidents |
| Kafka EOS transaction only | Does not tie DB commit to event; scope limited |
| CDC as primary publish | Row-level change, not domain `OrderPlaced`; schema coupling to table |
| 2PC / XA | Ops and availability cost; avoided in MSA |

## Follow-up

- Add outbox relay dashboard (lag, failed rows)
- Document `OrderPlaced` in event catalog and ADR-0002 if we add CDC for catalog search
작성 팁  
Context숫자 "publish 실패 월 3건", "p99 800ms"
Decision짧게 구현 세부링크 (PR, RFC)
Follow-up 미완 액션 — 다음 ADR·티켓

7. 저장소·워크플로

docs/
  c4/
    02-containers.md
  adr/
    0001-use-transactional-outbox.md
    0002-cdc-for-catalog-search.md
    README.md          # index + status table
  api/
    openapi-order-snippet.yaml
습관 효과
번호 0001 순차 충돌·참조 쉬움
구조 변경 PR에 ADR 필수 리뷰
docs/adr/README.md Accepted 한눈
Confluence 복사 금지 reposingle source

PR 체크

질문  
통합·데이터 소유 변경? ADR 필요
기존 ADR과 모순? Supersede 또는 수정
C4·계약 갱신? ADR Related 링크

8. 안티패턴

안티패턴 대안
Wiki 장문 한 편 결정당 짧은 ADR
Accepted 영원 Superseded·Deprecated 관리
대안 생략 최소 2개 거절 이유
구현 기억 작성 Proposed먼저
ADR = 설계 승인 Rejected남김재논의 절약
영문/한글 혼재 무질서 한 언어 고정 (예제는 영문 라벨 유지)

9. C4·계약·ADR 함께 쓰기

산출물 답하는 질문
C4 Context 누가 무엇연동?
C4 Container 어떤 배포 단위·데이터?
OpenAPI / AsyncAPI 표면 스키마·버전?
ADR 경계·패턴·기술?
  • Container 다이어그램 캡션See ADR-0001탐색 용이
  • 장애 RCA 후 "결정 가정틀렸다" → 신규 ADR 또는 Supersede

10. 실무 체크리스트

질문 좋은 답
몇 장? 1~2 페이지, Context 밀도 높게
누가 씀? 제안자 + 아키텍트 리뷰
언어? 합의 (코드·계약과 동일 권장)
도구? Markdown in git, adr-tools·Log4brains 선택
운영·합의 프로세스? 본 편은 작성법심화후속 주제

11. 정리

  • ADR맥락·대안·결과설계 의도 보존
  • Status — Proposed → Accepted → Superseded 역사 유지
  • C4·계약분업구조 vs 이유
  • repo docs/adr/PR·리뷰연동
  • Part 6 업무 — 다음은 아키텍처 평가

다음에 다룰 것

  • 아키텍처 평가
  • ATAM, 품질 시나리오, 기술 부채 관리

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

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

ADR 실전  (0) 2026.07.10
아키텍처 평가  (0) 2026.07.09
아키텍처 문서화  (0) 2026.07.07
이벤트 스트리밍과 CDC  (0) 2026.07.06
캐싱 전략  (0) 2026.07.05