ADR (Architecture Decision Records)
[Placeholder for technical implementation]
Article
M
Me
hyunyoun's Blog
software-engineering-devopssoftware-engineeringdev-opsarchitecturedesignadr-architecture-decision-recordsdocumentationlearning10 min read
1. Overview
아키텍처 결정 기록(Architecture Decision Records, ADR)은 퇴사자의 뇌 속에 묻혀버리는 시스템 설계의 맥락을 종이 위로 끄집어내어, "우리는 왜 그 당시에 이따위로 짤 수밖에 없었는가?"를 증명하는 기술적 유서이자 불변의 역사책을 해부합니다.
학습자는 코드를 보며 "이거 짠 사람 바보 아냐?"라며 무작정 시스템을 엎어버렸다가 3년 전과 똑같은 엣지 케이스에 부딪혀 시스템을 폭파시키는 레거시 붕괴의 공포를 뜯어봅니다. 나아가 결정을 내릴 당시의 비즈니스적 압박(Context)과 우리가 짊어지기로 한 대가(Consequences)를 마크다운 1장으로 박제하는 MADR(Markdown ADR) 템플릿을 장악합니다. 마지막으로, 한 번 내려진 결정을 절대로 수정(Update)하지 않고 오직 덮어쓰기(Supersede)만 허용하는 불변의 생명주기(Lifecycle) 통제 역량을 확보합니다.
2. Scope & Boundaries
In-Scope
- ADR Lifecycle: 제안(Proposed) 승인(Accepted) 폐기(Deprecated) 대체됨(Superseded).
- ADR Anatomy (MADR): Title, Status, Context, Decision, Consequences(Positive/Negative).
- Y-Statement: "In the context of [C], facing [P], we decided for [S] to achieve [V], accepting [D]"라는 강력한 결정 서술 공식.
- Architectural Fitness: ADR이 시간의 흐름에 따라 조직의 아키텍처 진화 방향을 증명하는 지표 역할.
Out-of-Scope
- C4 Model 및 구조도 그리기: 시스템의 현재 '상태(구조)'를 그리는 다이어그램 기법 09-01-03 Architecture Documentation 영역으로 분리 (ADR은 상태가 아니라 '결정의 이유'를 다룸).
- 버전 관리 도구(Git) 사용법: ADR 문서를 커밋하고 PR(Pull Request)을 올리는 법 09-01-04 Software Construction 영역으로 위임.
Boundaries
- 코드 주석(Comment) vs ADR: 주석은 특정 함수의
if문이 "왜 이렇게 도는지" 설명하는 '미시적(Micro)' 단서입니다. ADR은 "왜 우리가 RDBMS 대신 NoSQL을 메인 DB로 채택했는지" 설명하는 '거시적(Macro)' 전략입니다. 주석에 써야 할 변수의 이유를 ADR에 쓰거나, 반대로 시스템의 존망이 걸린 프레임워크 선택의 이유를 코드 귀퉁이 주석에 써놓고 잊어버리는 스코프 혼동(Scope Confusion)에 명확한 선을 긋습니다.
3. Counterexample
- 체스터튼의 울타리(Chesterton's Fence) 파괴: 새로 입사한 시니어 개발자가 코드를 봅니다. "왜 멀쩡한 외부 결제망을 놔두고 이렇게 복잡한 자체 큐(Queue)를 만들어놨지? 다 지우고 외부 API 직결로 바꿉시다!" 1주일 뒤, 블랙프라이데이 트래픽이 몰리자 결제망이 터졌고 회사 매출이 증발했습니다. 3년 전 과거의 팀원들이 '블랙프라이데이 타임아웃 방어'를 위해 큐를 만들었다는 '맥락(Context)'을 기록(ADR)해 두지 않아, 후임자가 무지성으로 울타리를 부숴버린 참사입니다.
- 거짓말하는 과거의 문서 (Mutable Records): 2021년에 쓴 문서를 2024년에 누군가 열어서 내용을 수정(Update)해 버렸습니다. "우리는 2021년에 A를 선택했다"라는 문서가 "우리는 2021년에 B를 선택했다"로 역사 왜곡이 일어났습니다. 나중에 장애 원인을 추적할 때, 왜 2022년 코드들이 A를 바라보고 짜여 있는지 그 누구도 설명하지 못하는 혼돈에 빠집니다. 문서의 불변성(Immutability)을 어긴 끔찍한 결말입니다.
4. Prerequisites
- 시스템 아키텍처 (Basic): 데이터베이스, 메시지 큐 등 기술 스택 선택의 트레이드오프 이해.
- 문서화 프레임워크 (Basic): Docs as Code 철학과 Git의 불변성. (09-01-03 Diátaxis)
5. Learning Map
6. Learning Topics
Basic
Core Topic 01: 잃어버린 맥락의 저주 (Context is King)
- Why to Learn: 신입사원이 "이 레거시 코드 개판이네요"라고 욕할 때, "그땐 그렇게 안 짜면 회사가 망하는 상황이었어"라는 기술적 채무의 정당성을 증명하기 위함입니다.
- What to Learn:
- Concepts: Chesterton's Fence, Tacit Knowledge (암묵지), Technical Debt Justification, Architectural Context.
- Skills: 특정 아키텍처(예: 마이크로서비스)를 도입했을 당시의 팀 규모(3명), 예산(0원), 시장 출시 압박(1달 내 런칭)이라는 '외적 요인'을 발굴하여 비효율적 설계의 당위성 증명하기.
- How to Learn:
- 1단계: 코드는 '왜'를 말하지 않는다: 소스코드는 기계에게 내리는 명령(How/What)입니다. "왜(Why)" 이 명령을 내렸는지는 코드에 없습니다.
- 2단계: 체스터튼의 울타리: 길을 가다 뜬금없이 세워진 울타리를 발견했습니다. 바보는 "방해되니까 부수자!"라고 합니다. 지혜로운 자는 "이 울타리를 처음 세운 사람이 '왜' 세웠는지 알아내기 전까진 부수지 마라"라고 합니다. 울타리 너머에 절벽이 있을지 모르기 때문입니다.
- 3단계: 맥락의 문서화: 3년 전 스타트업 초기에 RDBMS 대신 몽고DB를 쓴 이유는 "스키마 설계할 시간도 없이 매일 기획이 바뀌었기 때문"이었습니다. 이 맥락(Context)을 모르는 3년 뒤의 시니어는 "조인(Join)도 안 되는 쓰레기 DB!"라며 RDBMS로 마이그레이션하다가 개발 일정을 다 까먹습니다. 맥락이 왕(King)임을 해부합니다.
- Implement: 아키텍처 롤백 방어 모사.
Junior: "캐시(Redis) 로직이 너무 복잡합니다. 캐시 지우고 그냥 DB 직접 찌르죠."Senior:ADR-005: 2022년 트래픽 스파이크 대응문서를 던짐.Context: "DB CPU가 100%를 치며 서버가 3번 다운됨." 문서를 읽은 주니어가 즉시 주장을 철회하고 캐시 동기화 버그 수정으로 방향을 트는 리소스 낭비 0% 시각화.
Recommended
Core Topic 02: 잔인한 대가의 기록, MADR 템플릿 (The Anatomy of ADR)
- Why to Learn: 기술 결정에는 은탄환(Silver Bullet)이 없으며, 무언가를 얻으면 반드시 무언가를 잃는다는 엔지니어링의 진리를 서식(Template)으로 강제하기 위함입니다.
- What to Learn:
- Concepts: MADR (Markdown Any Decision Records), Title, Status, Context, Decision, Consequences (Positive/Negative).
- Skills: "Kafka 도입"을 결정할 때, "비동기 처리량이 10배 늘어난다(Positive)"는 찬양 뒤에 "사내에 Zookeeper/Kafka 클러스터를 운영할 수 있는 인프라 인력이 없다(Negative)"는 끔찍한 부작용을 숨기지 않고 명시하기.
- How to Learn:
- 1단계: Context (배경): 우리는 지금 초당 1만 건의 주문을 처리해야 하는데 기존 RabbitMQ가 자꾸 터집니다.
- 2단계: Decision (결정): 우리는 RabbitMQ를 버리고 Apache Kafka로 메시지 브로커를 교체합니다.
- 3단계: Consequences (대가): 이게 핵심입니다. 긍정적 대가(높은 처리량, 디스크 영속성)만 적으면 이건 기술 홍보 자료입니다. 부정적 대가(운영 난이도 극상승, 기존 코드 전면 재작성, 최소 3대의 브로커 서버 비용 추가)를 잔인하게 적어 넣어야 합니다. 우리가 이 고통을 알면서도 선택했다는 것을 미래의 나에게 고해성사하는 템플릿을 뜯어봅니다.
- Implement: MADR 생성기 컴파일.
Input: "GraphQL 씁시다! 프론트엔드가 편하대요!"Linter Check:Consequences항목에 부정적 대가(Negative)가 비어있음[Error] No Silver Bullet. 은탄환은 없습니다. N+1 쿼리 문제나 캐싱의 어려움 등 트레이드오프를 명시하세요.엔지니어의 편향(Confirmation Bias)을 시스템적으로 차단하는 렌더링.
Practical
Core Topic 03: 궁극의 한 줄 요약, Y-Statement (The Y-Statement)
- Why to Learn: 바쁜 임원이나 다른 팀 개발자가 긴 ADR 문서를 다 읽기 전에, 단 한 줄의 포맷팅된 문장만으로 아키텍처 결정의 본질을 10초 만에 뇌에 꽂아 넣기 위함입니다.
- What to Learn:
- Concepts: Y-Statement, Elevator Pitch for Architecture.
- Skills: "In the context of [C], facing [P], we decided for [S], to achieve [V], accepting [D]" 공식을 외우고 모든 기술 결정 회의의 결론을 이 한 줄로 요약하는 테크니컬 라이팅.
- How to Learn:
- 1단계: 장황함의 죽음: "어... 우리가 MSA를 하려다 보니까 트랜잭션이 꼬여서요... 그래서 사가 패턴을 도입했는데..." 듣는 사람은 1분 만에 하품을 합니다.
- 2단계: Y-Statement 공식: 빈칸을 채웁니다. "**[분산 DB 환경(Context)]**에서, **[데이터 불일치 문제(Problem)]**에 직면하여, 우리는 **[Saga Pattern(Solution)]**을 선택했다. 이를 통해 **[서비스 간 결합도 저하(Value)]**를 얻고, **[디버깅의 극악한 난이도와 보상 트랜잭션 개발 공수(Downside)]**를 감당하기로 한다."
- 3단계: 의사결정의 쐐기: 이 한 줄을 ADR의 맨 위에 박아넣으면, 프로젝트 스폰서(결정권자)가 "디버깅 난이도가 올라간다고? 안 돼, 리젝!" 하고 빠른 피드백(Shift-Left)을 줄 수 있는 가공할 폭발력을 해부합니다.
- Implement: Y-Statement 생성 및 리뷰 모사.
Draft: "Redis 캐시를 써서 DB 부하를 줄이기로 함. 근데 메모리 관리 잘해야 됨."Refactoring to Y-Statement: "In the context of [초당 5만 Read 트래픽], facing [DB CPU 100% 병목], we decided for [Redis Look-aside Caching] to achieve [응답 속도 90% 단축], accepting [데이터 정합성(Stale Data) 불일치 리스크 및 OOM 가능성]." 추상적인 수다를 공학적인 칼날로 벼려내는 시각화.
Advanced
Core Topic 04: 역사의 불변성, ADR 생명주기 통제 (Immutable Lifecycle)
- Why to Learn: 역사를 잊은 민족에게 미래가 없듯, 한 번 내려진 결정을 몰래 지우거나 수정하여 기술 부채의 원인을 은폐하려는 조직의 비겁함을 버전 관리로 원천 차단하기 위함입니다.
- What to Learn:
- Concepts: Immutable History, ADR Status (Proposed, Accepted, Deprecated, Superseded), Timestamp, RFC (Request for Comments).
- Skills: 2021년에 쓴
004-use-mongodb.md (Accepted)문서를 절대 지우지 않고, 2024년에045-migrate-to-postgresql.md를 새로 작성하며004문서를Superseded by 045상태로 변경하는 역사의 꼬리물기 구축.
- How to Learn:
- 1단계: Proposed (제안): 누군가
001-use-grpc.md를 올립니다(PR). 팀원들이 댓글로 치고받고 싸웁니다. - 2단계: Accepted (승인): 아키텍트가 머지(Merge)를 누릅니다. 이때부터 이 문서는 '불변(Immutable)의 돌판'이 됩니다. 오타 수정 정도를 제외하곤 핵심 내용을 절대 바꿀 수 없습니다.
- 3단계: Superseded (대체됨): 2년 뒤, gRPC가 너무 오버스펙이라 다시 REST로 돌아가기로 합니다.
001번 문서를 열어서 내용을 지우는 게(Update) 아닙니다!001번 문서는 그대로 두고 Status만Superseded by 008로 바꿉니다. 그리고 새로운008-revert-to-rest.md를 작성합니다. 왜 우리가 이 삽질의 루프를 탔는지, 조직의 아키텍처적 삽질과 진화의 역사를 완벽히 박제하는 위대한 생명주기 통제술을 뜯어봅니다.
- 1단계: Proposed (제안): 누군가
- Implement: ADR Git Lifecycle 그래프 추적기.
Action 1:005-use-mysql.md(2020년, Accepted).Action 2:012-use-mongodb.md(2022년, Accepted).005는Superseded by 012로 변경됨.Action 3 (금지된 조작): 개발자가005문서의 텍스트를 "우리는 원래 Mongo를 쓰려 했다"로git commit --amend하려 시도. Git Hook이 변경 감지 및 Push 차단 ([Error] Accepted ADR은 불변입니다). 문서의 위변조를 막는 시스템적 방어선 렌더링.
7. Terminology
8. References
Primary
- [P1] CS2023 - Software Engineering (SE) - Software Architecture (Architectural Documentation and ADRs)
- [P5] SFIA - Systems Design (SYSD) - Architectural Decision Making
Secondary
- [Documenting Software Architectures] Paul Clements - Decision documentation
- [Fundamentals of Software Architecture] Mark Richards - Architecture Decisions (ADRs, Y-Statements)
Industry
- [AWS Prescriptive Guidance] - Architecture Decision Records (ADRs)
- [Michael Nygard's Blog] - Documenting Architecture Decisions (The original MADR template)
9. Final Checklist
Primary
- 신규 입사자가 5년 된 레거시 코드를 보고 비효율적이라며 즉각적인 리팩터링을 주장할 때, ADR에 기록된 과거의 '맥락(Context: 예산 부족, 런칭 압박)'을 제시하여 시스템 붕괴(Chesterton's Fence 위반)를 막을 수 있는가?
- MADR 템플릿을 작성할 때, 'Decision' 항목에 프레임워크 도입 사실을 적는 것에 그치지 않고, 반드시 'Consequences' 항목에 부정적 대가(예: 학습 곡선 상승, 서버 비용 증가)를 정량적으로 적시할 수 있는가?
Secondary
- 1시간짜리 지루한 아키텍처 토론 결과를 "In the context of [C], facing [P], we decided for [S] to achieve [V], accepting [D]"라는 Y-Statement 한 줄로 요약하여 의사결정권자의 3초 컷 승인을 받아낼 수 있는가?
- "모놀리식 서버 분리"라는 거대한 안건을 하나의 ADR에 때려 넣으려 할 때, 이를 쪼개어 "1. DB 분리 결정", "2. API Gateway 도입 결정" 등 구체적이고 단일한 책임을 가지는 여러 개의 ADR로 분할(Granularity)할 수 있는가?
Industry
- 2022년에
Accepted된 ADR 005번(MySQL 도입)의 내용이 현재 비즈니스 상황과 맞지 않게 되었을 때, 005번 문서를 수정하는 대신 042번 문서(PostgreSQL 전환)를 새로 만들고 005번의 상태를Superseded by 042로 엮어내는 역사의 꼬리물기를 시연할 수 있는가? - 수백 개의 마크다운 ADR 파일 더미에서, 문서의 헤더(Frontmatter)에 박힌 태그(예:
#database,#security)를 파싱하여 신규 개발자가 특정 도메인의 의사결정 역사만 모아서 조회할 수 있는 문서 정적 생성기(Static Site Generator) 파이프라인을 설계할 수 있는가?