기술 의사결정 — ADR 작성법과 기술 선택의 기록
"이거 왜 이 기술을 쓰는 거죠?" — 프로젝트에 합류할 때마다 드는 질문인데, 그 결정의 이유를 아는 사람이 아무도 없는 경우가 있습니다.
기술 선택에는 항상 맥락과 트레이드오프가 있습니다. 그런데 코드에는 "무엇을" 했는지만 남고, "왜" 그렇게 했는지는 사라집니다. ADR(Architecture Decision Record)은 이 "왜"를 기록하는 가벼운 문서화 방법입니다.
이게 뭔가요?
ADR(Architecture Decision Record) 은 아키텍처 결정의 배경, 선택지, 결과를 짧은 문서로 기록하는 것입니다.
- 1~2페이지 분량의 간결한 문서
- 코드 저장소에 함께 보관 (보통
docs/adr/디렉토리) - 결정이 내려진 시점의 맥락을 보존
Michael Nygard가 2011년에 제안한 형식이 가장 널리 쓰입니다.
왜 필요한가요?
기록이 없으면 생기는 문제
6개월 전: "PostgreSQL 대신 MongoDB를 쓰자"
→ 그때는 타당한 이유가 있었음
오늘: "왜 MongoDB를 쓰는 거야?"
→ 결정한 사람이 퇴사함
→ 아무도 이유를 모름
→ "그냥 원래 쓰던 거니까..."
→ 기술 부채인지 의도적 선택인지 판단 불가
ADR이 해결하는 것
- 맥락 보존: 결정 당시의 제약 조건, 팀 상황, 요구사항을 기록
- 온보딩 가속: 신규 팀원이 "왜 이 기술을 쓰는가"를 문서로 파악
- 재논의 방지: 같은 주제로 반복되는 회의를 줄임
- 되돌리기 용이: 상황이 바뀌었을 때 원래 결정의 전제를 재검토 가능
어떻게 동작하나요?
ADR 기본 구조
# ADR-0001: 메시지 브로커로 Kafka 선택
## 상태
승인됨 (2027-01-15)
## 맥락
주문 서비스와 재고 서비스 간 비동기 통신이 필요합니다.
현재 일일 주문 건수는 약 50,000건이며,
향후 1년 내 500,000건으로 성장할 것으로 예상됩니다.
메시지 유실은 허용되지 않습니다.
## 고려한 선택지
### 1. Apache Kafka
- 높은 처리량 (초당 수십만 건)
- 메시지 영속성 보장 (디스크 저장)
- 파티션 기반 수평 확장
- 학습 곡선이 높고 운영 복잡도가 있음
### 2. RabbitMQ
- 라우팅 기능이 풍부 (Exchange, Binding)
- 상대적으로 학습이 쉬움
- 처리량이 Kafka 대비 낮음
- 메시지가 소비되면 삭제됨 (재처리 어려움)
### 3. AWS SQS
- 관리형 서비스로 운영 부담 없음
- AWS 인프라와 통합 용이
- 메시지 순서 보장이 FIFO 큐에서만 가능
- 처리량 제한 (FIFO: 초당 300건)
## 결정
**Apache Kafka를 선택합니다.**
이유:
- 예상 트래픽 증가를 고려하면 높은 처리량이 필요
- 메시지 재처리(replay)가 가능해야 장애 복구에 유리
- 팀 내 Kafka 운영 경험자가 2명 있음
- AWS MSK(관리형 Kafka)를 사용하여 운영 부담을 줄임
## 결과
- Kafka 클러스터 구축 대신 AWS MSK 사용
- 팀 내 Kafka 교육 세션 진행 필요
- 모니터링: Kafka Lag 모니터링 대시보드 구축
- 이 결정은 ADR-0003(이벤트 스키마 관리)과 관련됨
프로젝트 내 ADR 구조
project/
├── docs/
│ └── adr/
│ ├── 0001-메시지-브로커-kafka-선택.md
│ ├── 0002-인증-방식-jwt-선택.md
│ ├── 0003-이벤트-스키마-avro-선택.md
│ ├── 0004-api-게이트웨이-kong-선택.md
│ └── README.md # ADR 목록과 인덱스
├── src/
└── ...
ADR 상태 관리
ADR은 상태가 변할 수 있습니다:
제안됨(Proposed) → 승인됨(Accepted) → 폐기됨(Deprecated/Superseded)
# ADR-0002: 인증 방식으로 JWT 선택
## 상태
폐기됨 — ADR-0009로 대체 (2027-06-01)
## 폐기 사유
서비스 규모가 커지면서 JWT 토큰 무효화 처리가 복잡해짐.
세션 기반 인증 + Redis로 전환 (ADR-0009 참조).
상태를 업데이트하지, 원본을 삭제하지 않습니다. "왜 이전 결정을 바꿨는가"도 중요한 기록입니다.
ADR을 작성해야 하는 시점
모든 결정을 ADR로 쓸 필요는 없습니다. 기준:
ADR이 필요한 결정:
✅ 되돌리기 어려운 결정 (DB 선택, 프레임워크 교체)
✅ 팀원 간 의견이 갈리는 결정
✅ 비용이 크거나 장기적으로 영향을 미치는 결정
✅ 외부에 설명해야 하는 결정
ADR이 필요 없는 결정:
❌ 컨벤션 수준 (변수명 스타일, 들여쓰기)
❌ 쉽게 바꿀 수 있는 결정 (라이브러리 유틸 함수)
❌ 업계 표준을 따르는 결정 (HTTPS 사용 등)
기술 선택 평가 프레임워크
ADR을 쓸 때 선택지를 비교하는 체계적인 방법:
## 평가 기준 (가중치)
| 기준 | 가중치 | Kafka | RabbitMQ | SQS |
|------|--------|-------|----------|-----|
| 처리량 | 30% | 5 | 3 | 2 |
| 운영 복잡도 | 25% | 2 | 3 | 5 |
| 팀 경험 | 20% | 4 | 2 | 3 |
| 비용 | 15% | 3 | 3 | 4 |
| 확장성 | 10% | 5 | 3 | 3 |
| 가중 합계 | | 3.7 | 2.8 | 3.3 |
숫자가 절대적인 답을 주지는 않지만, 논의를 구조화하고 감에 의한 결정을 줄여줍니다.
자주 헷갈리는 포인트
ADR은 설계 문서(Design Doc)와 뭐가 다른가요?
| 측면 | ADR | 설계 문서 |
|---|---|---|
| 범위 | 하나의 결정 | 전체 시스템/기능 설계 |
| 분량 | 1~2페이지 | 5~20페이지 |
| 초점 | "왜 이것을 선택했는가" | "어떻게 구현할 것인가" |
| 수명 | 영구 보존 (폐기 시 상태만 변경) | 구현 후 낡아질 수 있음 |
둘은 보완적입니다. 큰 기능은 설계 문서를 먼저 쓰고, 그 안의 핵심 결정들을 ADR로 분리합니다.
ADR을 Confluence/Notion에 쓰면 안 되나요?
쓸 수 있지만, 코드 저장소에 함께 두는 것이 권장 됩니다:
- 코드와 결정이 같이 버전 관리됨
- PR로 ADR을 리뷰할 수 있음
- 코드를 보다가 바로 관련 ADR을 찾을 수 있음
- 위키에 넣으면 시간이 지나면서 코드와 동기화가 깨지기 쉬움
ADR을 안 쓰면 어떻게 되나요?
기술 선택의 맥락이 구전(口傳)으로만 전달됩니다:
- "그건 예전에 CTO가 결정한 건데..." → CTO 퇴사 후 미스터리
- 같은 주제로 3개월마다 회의 반복
- 결정을 되돌릴 때 원래 제약 조건을 모르니까 같은 실수를 반복
팀이 ADR을 안 쓰려고 합니다
ADR 문화를 도입하려면:
- 처음에는 템플릿을 최소화 (상태, 맥락, 결정, 결과만)
- 과거 결정을 소급해서 쓸 필요 없음 — 앞으로의 결정부터 시작
- PR 체크리스트에 "아키텍처 결정이 포함되어 있다면 ADR을 작성했는가?" 추가
- 툴링:
adr-toolsCLI를 사용하면 파일 생성을 자동화 가능
# adr-tools 사용 예시
adr new "메시지 브로커로 Kafka 선택"
# → docs/adr/0005-메시지-브로커로-kafka-선택.md 자동 생성
adr list
# 0001 - 데이터베이스로 PostgreSQL 선택
# 0002 - 인증 방식으로 JWT 선택
# ...
정리
- ADR은 아키텍처 결정의 "왜"를 기록하는 1~2페이지짜리 가벼운 문서
- 맥락(Context) → 선택지(Options) → 결정(Decision) → 결과(Consequences) 구조
- 코드 저장소의
docs/adr/에 함께 보관하면 코드와 동기화 유지 - 폐기된 ADR도 삭제하지 않고 상태만 업데이트 — "왜 바꿨는가"도 중요한 기록
- 모든 결정이 아닌, 되돌리기 어렵거나 논쟁이 있는 결정에만 작성
- 가중치 평가표를 활용하면 감에 의한 결정을 줄이고 논의를 구조화할 수 있음