ADR 템플릿과 예제: 바로 복사해 쓰는 형식

회의는 두 시간째 이어지고 있었습니다. 새 서비스에 PostgreSQL을 쓸지 MongoDB를 쓸지 논쟁 중이었습니다. 관계형 무결성, 유연한 스키마, 팀의 숙련도, 운영 복잡도. 주장이 오갔습니다.

그때 누군가 말했습니다. "작년에 사용자 서비스 때도 똑같은 논의를 하지 않았나요?"

침묵. 했었습니다. 1년 전 우리는 같은 질문에 똑같이 긴 시간을 쏟았고 PostgreSQL을 골랐습니다. 그 이유를 기억하는 사람은 없었고, 그 논의를 이끌었던 엔지니어는 이미 회사를 떠난 뒤였습니다. 그래서 우리는 같은 논쟁을 처음부터 다시 하고 있었던 것입니다.

그때부터 우리는 아키텍처 결정 기록(ADR)을 쓰기 시작했습니다. 이 글은 복사해서 붙여 넣는 부분입니다. 템플릿 세 가지, 각각을 쓰는 경우, 그리고 우리 자신의 결정 세 가지를 채워 넣은 예제를 소개합니다.

ADR이란?

아키텍처 결정 기록은 하나의 아키텍처 결정을 기록하는 짧은 문서입니다. 시스템의 모든 것을 다루는 설계 문서가 아니라, 결정 하나만 다룹니다:

  • 무엇을 결정했는가
  • 왜 그렇게 결정했는가
  • 어떤 대안을 검토했는가
  • 어떤 결과가 따르는가

ADR은 한두 페이지에 들어가야 합니다. 그보다 길다면 아마 둘 이상의 결정을 기록하고 있는 것입니다. 언제 써야 하는지, 생명주기, 팀이 저지르는 실수는 완벽 가이드에서 다룹니다. 이 글은 형식에만 집중합니다.

최소 템플릿 (Nygard)

대부분의 팀이 아직도 쓰는 형식은 Michael Nygard가 2011년 글에서 제안한 것입니다. 다섯 부분으로 이루어집니다: 짧은 명사구로 된 제목, 상태, 컨텍스트("작용하는 힘들"), 결정("이 힘들에 대한 우리의 대응"), 그리고 결과("결정을 적용한 뒤의 컨텍스트"). 그가 정한 상태는 Proposed, Accepted, Deprecated, Superseded입니다.

# ADR-NNNN: 짧은 명사구

## 상태

Proposed | Accepted | Deprecated | Superseded by ADR-XXXX

## 컨텍스트

어떤 힘이 작용하고 있는가? 기술, 조직, 마감, 예산.
구체적으로: 숫자, 제약, 영향을 받는 사람.

## 결정

우리는 ~할 것이다.

## 결과

무엇이 쉬워지고, 무엇이 어려워지며, 앞으로 무엇을 지켜봐야 하는가.

우리는 여기에 섹션 하나를 더합니다. 결정과 결과 사이에 두는 검토한 대안입니다. 나중에 가장 많은 시간을 아껴 주는 부분입니다. 1년 뒤에 받는 질문은 "무엇을 골랐나?"가 아니라 거의 항상 "왜 X를 고르지 않았나?"이기 때문입니다.

## 검토한 대안

### 선택지 B
- 장점: ...
- 단점: ...
- 기각한 이유: ...

MADR

MADR(Markdown Architectural Decision Records)은 adr.github.io/madr에서 관리되는, 더 구조화된 템플릿입니다. 현재 버전은 2024년 9월 17일에 출시된 4.0.0입니다. 메타데이터를 YAML 프런트매터에 두고, 선택지와 그 트레이드오프를 산문이 아닌 명시적인 섹션으로 만듭니다.

---
status: proposed | rejected | accepted | deprecated | superseded by ADR-XXXX
date: YYYY-MM-DD
decision-makers: ...
consulted: ...
informed: ...
---

# 해결한 문제와 선택한 해법을 담은 짧은 제목

## 컨텍스트와 문제 정의

두세 문장, 또는 짧은 이야기. 가능하면 질문 형태로.

## 결정 요인

* 요인 1
* 요인 2

## 검토한 선택지

* 선택지 A
* 선택지 B
* 선택지 C

## 결정 결과

선택한 선택지: "선택지 A", 이유는 ...

### 결과

* 좋은 점: ~이기 때문에
* 나쁜 점: ~이기 때문에

### 확인 방법

결정이 구현되었는지 어떻게 확인할 것인가(리뷰, 테스트, 피트니스 함수).

## 선택지별 장단점

### 선택지 A

* 좋은 점: ~이기 때문에
* 나쁜 점: ~이기 때문에

## 추가 정보

링크, 관련 결정, 다시 검토할 시점.

MADR에서 검토한 선택지와 결정 결과 이후의 섹션은 모두 선택 사항입니다. 빈 제목을 남겨 두지 말고 쓰지 않는 것은 지우세요.

Y-statement

Y-statement는 결정 하나를 한 문장에 담습니다. Uwe Zdun, Olaf Zimmermann 등이 제안한 것입니다("Sustainable Architectural Design Decisions", IEEE Software, 2013):

<유스케이스 또는 컴포넌트>의 맥락에서,
<관심사 또는 요구사항>에 직면하여,
우리는 <선택지>를 택했고
(<다른 선택지>는 택하지 않았으며),
<품질 또는 이점>을 얻기 위해,
<단점>을 감수한다.

완전한 컨텍스트 섹션을 담기에는 너무 짧지만, 그게 핵심입니다. 한 페이지를 쓸 가치까지는 없는 결정, 긴 ADR 맨 위의 요약 줄, 또는 결정 로그의 기입 형식으로 사용하세요.

어떤 형식을 쓸 것인가

형식 이럴 때 쓰세요 주의할 점
Nygard (+ 대안) 이제 막 시작했거나, 대부분의 결정에 명확한 승자 하나와 기각된 선택지 몇 개가 있을 때 컨텍스트 섹션이 에세이처럼 불어나는 것
MADR 결정에 이견이 있거나, 여러 사람의 승인이 필요하거나, 선택지와 결정 요인을 ADR끼리 비교할 수 있게 하고 싶을 때 습관적으로 모든 선택 섹션을 채우는 것
Y-statement 작은 결정, 결정 로그, 또는 긴 ADR 위의 한 줄 요약 제대로 된 컨텍스트 섹션이 필요한 결정에 쓰는 것

리포지토리마다 하나를 골라 지키세요. 형식이 섞여 있으면, 어느 한 형식으로 쓰는 수고보다 훑어보는 수고가 더 큽니다.

예제 1: ADR-0042, 주문 서비스에 PostgreSQL 사용

도입부 이야기 속 결정을, Nygard 형식에 우리의 "검토한 대안" 섹션을 더해 작성한 것입니다.

# ADR-0042: 주문 서비스에 PostgreSQL 사용

## 상태

Accepted

## 컨텍스트

주문 서비스에는 주문 데이터를 위한 영구 저장소가 필요하다. 초기에는 하루 50,000건의
주문을 처리하고, 2년 안에 500,000건으로 늘어날 것으로 예상한다. 주문의 구조는 잘
정의되어 있지만 시간이 지나면서 메타데이터 필드가 추가로 필요할 수 있다. 팀은
관계형 데이터베이스와 문서형 데이터베이스 모두 경험이 있다.

## 결정

주문 서비스의 주 데이터베이스로 PostgreSQL 15를 사용한다.

PostgreSQL을 선택한 이유:

- 금융 주문 데이터에는 ACID 준수가 필수다
- JSON 컬럼으로 메타데이터의 스키마 유연성을 확보할 수 있다
- 인프라 팀에 PostgreSQL 운영 경험이 있다
- 쿼리 패턴이 관계형 모델링에 잘 맞는다

## 검토한 대안

### MongoDB

- 장점: 네이티브 JSON 저장, 더 쉬운 수평 확장, 유연한 스키마 진화
- 단점: 약한 일관성 보장, 팀의 운영 경험 부족,
  트랜잭션을 위해 추가 도구가 필요

### DynamoDB

- 장점: 완전 관리형, 최소한의 운영, 뛰어난 확장성
- 단점: AWS 종속, 쿼리 패턴이 파티션/정렬 키 접근으로
  제한됨, 대규모에서 비용 예측이 어려움

## 결과

### 긍정적

- 강력한 데이터 무결성 보장
- 팀이 기존 PostgreSQL 전문성을 재사용할 수 있음
- 운영 특성이 잘 알려져 있음

### 부정적

- 스키마 마이그레이션에 문서형 저장소보다 더 많은 계획이 필요
- 단일 노드 용량을 넘어서면 수평 확장이 더 복잡함
- 확장 한계에 도달하면 애플리케이션 수준 샤딩이 필요

### 리스크

- 주문량이 하루 100만 건을 넘으면 재검토가 필요할 수 있음
- JSON 컬럼 쿼리는 네이티브 문서형 저장소보다 비효율적

## 관련 결정

- 최종 일관성을 받아들이는 이유는 ADR-0007 참고
- MongoDB를 권장했던 ADR-0003을 대체함

컨텍스트는 구체적으로 쓰세요. "신뢰성이 필요하다"보다 "ACID 준수가 필요하다"가 다음 독자에게 훨씬 도움이 됩니다. 그리고 결과는 정직하게 쓰세요. 대가 없는 결정은 없으며, 단점을 적어 두면 미래의 팀이 언제 재검토해야 할지 알 수 있습니다.

예제 2: ADR-0007, 이벤트 기반 통신을 MADR로

Kafka 결정에는 검토한 선택지도, 관여한 사람도 더 많았습니다. MADR의 명시적인 결정 요인과 선택지가 제 몫을 하는 경우입니다.

---
status: accepted
---

# 서비스 간 비동기 통신에 Kafka 사용

## 컨텍스트와 문제 정의

마이크로서비스들은 HTTP로 동기 통신한다. 이 때문에 서비스들이 강하게 결합되고,
한 서비스가 사용 불가능해지면 상류로 장애가 연쇄된다.
호출자가 즉각적인 응답을 필요로 하지 않을 때, 서비스는 어떻게 통신해야 하는가?

## 결정 요인

* 복원력: 한 서비스가 다운되어도 다른 서비스를 함께 끌어내려서는 안 된다
* 서비스 간 결합 완화

## 검토한 선택지

* 동기 HTTP 유지
* Apache Kafka를 이용한 이벤트 기반 통신

## 결정 결과

선택한 선택지: "Apache Kafka를 이용한 이벤트 기반 통신", 이유는
연쇄 장애를 일으키는 런타임 결합을 제거하기 때문이다.

### 결과

* 좋은 점: 서비스들이 서로의 장애에 더 강해진다
* 나쁜 점: 강한 일관성에서 최종 일관성으로 바뀐다
* 나쁜 점: 이제 Kafka 클러스터를 운영해야 한다
* 나쁜 점: 팀이 이벤트 기반 패턴에 대한 교육을 받아야 한다

상태와 제목은 원래 기록에서 그대로 가져왔습니다. 원래 기록에 날짜와 결정권자가 남아 있지 않았기 때문에 여기서는 그 필드를 뺐습니다.

예제 3: ADR-0015, 프런트엔드 모노레포를 Y-statement로

모노레포 결정은 한 문장에 들어가며, 그 한 문장으로 "왜 전부 한 리포지토리에 있어요?"에 충분히 답할 수 있습니다.

별도의 리포지토리에 있는 프런트엔드 애플리케이션 5개의 맥락에서,
버전 불일치와 코드 공유를 위한 패키지 배포의 부담에 직면하여,
우리는 Nx로 관리하는 단일 모노레포를 택했고
(패키지 관리를 개선한 별도 리포지토리 방식과 Nx 없는 모노레포는 택하지 않았으며),
쉬운 코드 공유와, 공유 코드와 그 모든 사용처를 하나의 풀 리퀘스트로 업데이트하는 것을 얻기 위해,
더 큰 리포지토리에는 빌드 캐싱이 필요하고 애플리케이션끼리 의도치 않게 결합될 수 있다는 점을 감수한다.

기각한 선택지들의 이유는 전체 기록에 남아 있습니다. 별도 리포지토리는 조율 부담이 여전했고, Nx 없는 모노레포는 빌드 시간을 감당할 수 없게 만들었을 것입니다.

어디에 둘 것인가

ADR은 그것이 설명하는 리포지토리의 docs/adr/나 docs/decisions/에 두세요(Nygard는 doc/arch/adr-NNN.md를 제안했습니다). 코드와 함께 버전 관리되고, 코드 리뷰에 나타나며, 위키 속에서 길을 잃을 일도 없습니다.

번호는 순차적으로 매기고 절대 재사용하지 마세요. 결정이 바뀌면 이력을 고치지 말고, 이전 ADR을 대체하는 새 ADR을 쓰고 이전 ADR의 상태를 업데이트하세요.

대부분의 팀이 건너뛰는 단계는 ADR을 그것이 영향을 미치는 시스템 부분과 연결하는 것입니다. Archyl에서 ADR은 Nygard의 필드(상태, 컨텍스트, 결정, 결과)에 날짜와 대체 링크를 더해 가지며, 그것이 형성한 시스템, 컨테이너, 컴포넌트에 연결됩니다. C4 다이어그램에서 주문 서비스를 보는 사람은 그 옆에서 ADR-0042를 봅니다. "이 서비스는 왜 PostgreSQL을 쓰나요?"의 답까지 클릭 한 번입니다.

함정들(사후에 ADR을 쓰는 것, 다섯 페이지까지 늘어나게 두는 것, 처음 바쁜 분기가 지나면 관행을 버리는 것)은 완벽 가이드에서 다룹니다.

하나부터 시작하세요

PostgreSQL이냐 MongoDB냐로 두 시간을 보낸 그 회의는요? 다음에 같은 질문이 나왔을 때, 누군가 ADR-0042를 찾아냈고 회의는 10분 만에 끝났습니다. 제약, 대안, 이유가 모두 거기 있었습니다. 원래 결정이 여전히 유효한지 확인하고 넘어갔습니다.

위의 템플릿 중 하나를 골라 docs/adr/0001-record-architecture-decisions.md에 붙여 넣으세요. 첫 ADR은 ADR을 쓰기로 한 결정이어도 됩니다.


아키텍처 문서화에 대해 더 알아보기: C4 모델 가이드 | 왜 문서화가 중요한가 | 사용자 플로우 문서화하기