콘텐츠로 바로가기

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) \rightarrow 승인(Accepted) \rightarrow 폐기(Deprecated) \rightarrow 대체됨(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 및 구조도 그리기: 시스템의 현재 '상태(구조)'를 그리는 다이어그램 기법 \rightarrow 09-01-03 Architecture Documentation 영역으로 분리 (ADR은 상태가 아니라 '결정의 이유'를 다룸).
  • 버전 관리 도구(Git) 사용법: ADR 문서를 커밋하고 PR(Pull Request)을 올리는 법 \rightarrow 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

Sequence Core Cluster Objective & Description Evidence (BoK)
1 Context is King 코드만으로는 절대 알 수 없는 "당시 회사의 예산, 일정, 트래픽 한계"라는 보이지 않는 유령(Context)을 소환해 냅니다. P1
2 The Anatomy of ADR 제목, 상태, 배경, 결정, 그리고 우리가 짊어질 '긍정적/부정적 대가'를 잔인하게 기록하는 MADR 템플릿의 해부학을 쥡니다. P5
3 The Y-Statement "A 환경에서 B 문제 때문에 C를 골라 D 이점을 얻지만 E를 포기한다"는 단 한 줄의 궁극의 아키텍처 명언을 뜯어봅니다. Industry
4 Immutable Lifecycle 한 번 승인된 ADR은 절대 지우거나 고치지 않고, 오직 새로운 ADR로 '덮어쓰기(Supersede)'만 하는 숭고한 역사학자의 태도를 장악합니다. Industry

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번 다운됨." \rightarrow 문서를 읽은 주니어가 즉시 주장을 철회하고 캐시 동기화 버그 수정으로 방향을 트는 리소스 낭비 0% 시각화.

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)가 비어있음 \rightarrow [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를 작성합니다. 왜 우리가 이 삽질의 루프를 탔는지, 조직의 아키텍처적 삽질과 진화의 역사를 완벽히 박제하는 위대한 생명주기 통제술을 뜯어봅니다.
  • Implement: ADR Git Lifecycle 그래프 추적기. Action 1: 005-use-mysql.md (2020년, Accepted). Action 2: 012-use-mongodb.md (2022년, Accepted). \rightarrow 005Superseded by 012로 변경됨. Action 3 (금지된 조작): 개발자가 005 문서의 텍스트를 "우리는 원래 Mongo를 쓰려 했다"로 git commit --amend 하려 시도. \rightarrow Git Hook이 변경 감지 및 Push 차단 ([Error] Accepted ADR은 불변입니다). 문서의 위변조를 막는 시스템적 방어선 렌더링.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
ADR (Architecture Decision Record) "그때 왜 그따위로 짰어?"라는 미래의 욕설을 방어하기 위해, 결정 당시의 처절했던 맥락(Context)과 대가(Consequences)를 마크다운 1장으로 박제해 두는 기술적 유서입니다. 기본 아키텍처 결정의 이력 보존 및 지식 공유 Context / Chesterton's Fence Code Comments 시스템의 현재 '상태'를 설명하는 문서가 아님. "A 대신 B를 선택한 '이유'"에 집중하는 의사결정의 스냅샷임 P1:CS2023 core
Chesterton's Fence (체스터튼의 울타리) "길 한가운데 있는 낡은 울타리를 부수기 전에, 그걸 처음 세운 사람이 '왜' 세웠는지 알아내기 전까진 절대 건드리지 마라"는 레거시 시스템을 대하는 최고의 철학적 경구입니다. 권장 레거시 코드 철거 전 맥락(Context) 파악의 중요성 Context / Legacy Code Tech Debt (기술 부채) 레거시를 영원히 남겨두라는 뜻이 아님. 부수더라도 '원래의 목적'을 파악한 뒤에 안전망을 깔고 부수라는 뜻임 P5:SFIA core
Consequences (결과/대가) 모든 기술 결정에는 은탄환(Silver bullet)이 없으므로, 어떤 아키텍처를 도입할 때 긍정적인 이점뿐만 아니라 반드시 우리가 치러야 할 뼈아픈 부작용(단점)까지 명시하는 ADR의 핵심 항목입니다. 실무 트레이드오프(Trade-off)의 투명한 공개 Trade-off / Y-Statement Silver Bullet 이 항목에 장점만 잔뜩 적혀 있다면 그 ADR은 기술 문서가 아니라 특정 프레임워크를 도입하고 싶은 개발자의 '영업/홍보 자료'에 불과함 Industry core
Superseded (대체됨) 과거의 ADR을 절대 지우거나 텍스트를 수정하지 않고(불변성), 새로운 결정을 내린 새 ADR 문서를 발행한 뒤 과거 문서의 상태만 "00번 문서로 대체됨"이라고 마킹하는 생명주기 통제술입니다. 심화 결정 역사의 불변성(Immutability) 유지 Immutable / Lifecycle Updated (수정됨) 문서가 틀렸거나 상황이 바뀌었다고 옛날 문서를 열어 Update 하는 것은 역사 왜곡이며, 문서 부패(Decay)를 가속화하는 최악의 안티 패턴임 Industry core

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) 파이프라인을 설계할 수 있는가?

Architecture & Documentation

3 / 5