ADR(Architecture Decision Record)

mmmn0616·2026년 8월 5일

개발자는 프로젝트를 진행하면서 컴퓨터 자원, 기술 스택, 데이터 저장 방식, 시스템 구성, 컴포넌트 간 통신 방식 등 다양한 결정을 마주한다.

시스템 구조와 장기적인 개발 방향에 중요한 영향을 주는 결정을 아키텍처 결정(Architecture Decision)이라고 한다.

이러한 결정을 내리게 된 배경과 근거, 그 결정으로 인해 발생하는 결과를 문서로 기록하는데, 이 문서를 ADR(Architecture Decision Record)이라고 한다.

모든 사소한 구현 결정을 ADR로 기록할 필요는 없다. 주로 나중에 변경하기 어렵거나, 여러 개발자 및 시스템 구성요소에 영향을 주거나, 비용과 일정에 큰 영향을 미치는 중요한 결정을 ADR로 기록하면 된다.

용어 정리

  • AD(Architecture Decision): 시스템의 중요한 요구사항을 해결하기 위해 내리는 소프트웨어 설계 선택
  • ADR(Architecture Decision Record): 하나의 중요한 아키텍처 결정과 그 배경, 근거 및 결과를 기록한 문서
  • ADL(Architecture Decision Log): 특정 프로젝트에서 작성된 ADR의 모음
  • ASR(Architecturally Significant Requirement): 시스템 아키텍처에 중요한 영향을 미치는 요구사항

AD는 ‘결정 그 자체’, ADR은 ‘그 결정을 기록한 문서’, ADL은 ‘ADR을 모아놓은 기록’으로 설명할 수 있겠다.


ADR이 필요한 이유

ADR의 핵심은 '해당 선택을 왜 했는가'에 있다.

선택의 근거를 명시하면 의사결정 과정의 투명성과 추적 가능성을 높일 수 있다. 다만 근거를 기록한다고 해서 결정의 합리성이나 정확성이 자동으로 보장되는 것은 아니다.

대신 당시 어떤 상황과 제약조건에서 결정이 내려졌는지를 확인할 수 있기 때문에, 이후 그 결정이 적절했는지를 검토하기가 쉬워질 수 있다.

예를 들어 프로젝트에서 특정 데이터베이스를 선택했다고 하자. 시간이 지나면 팀원들은 해당 데이터베이스를 사용하고 있다는 사실은 알고 있어도, 왜 다른 데이터베이스가 아닌 그것을 선택했는지는 기억하지 못할 수 있다.

ADR에 다음과 같은 내용이 남아 있다면 결정의 맥락을 쉽게 이해할 수 있다.

  • 당시 예상한 데이터 규모
  • 필요한 읽기 및 쓰기 성능
  • 팀원의 기술 숙련도
  • 운영 비용
  • 검토한 다른 데이터베이스
  • 다른 대안을 제외한 이유

더 나아가, 새로운 팀원이나 미래의 유지보수 담당자가 ADR을 읽게 된다면 현재 시스템의 아키텍처가 어떤 이유로 구성되었는지 쉽게 파악할 수 있을 것이다.

즉, 이미 논의했던 문제를 새로운 팀원이 다시 처음부터 검토하는 일을 줄일 수 있고, 과거의 결정을 무의식적으로 되돌리는 것도 방지할 수 있다는 장점이 있다.

<ADR 장점>

  • 결정의 배경과 근거를 보존할 수 있다.
  • 새로운 팀원이 시스템 구조를 이해하기 쉬워진다.
  • 같은 논의를 반복하는 일을 줄일 수 있다.
  • 상황이나 요구사항이 변경되었을 때 결정을 재검토하기 쉽다.
  • 설계 결정과 요구사항, 코드, 문서 사이의 관계를 추적할 수 있다.
  • 결정으로 인한 장점뿐만 아니라 위험과 단점도 공유할 수 있다.

Git과 함께 사용하는 방법

프로젝트 저장소에 ADR 폴더를 만들고, 그 안에 Markdown 형식의 파일을 만들어 Git에 함께 커밋할 수 있다.

일반적으로 docs/adr와 같은 경로를 사용한다.

project/
├── src/
├── tests/
└── docs/
    └── adr/
        ├── 0001-use-ros2.md
        ├── 0002-use-px4.md
        └── 0003-use-state-machine.md

ADR에 번호를 붙이는 방식은 필수는 아니지만, 문서를 작성된 순서대로 관리하고 관련 ADR을 서로 참조할 때 유용하다.

번호를 붙이지 않는다면 다음처럼 결정의 내용을 나타내는 파일명을 사용할 수도 있다.

choose-database.md
use-message-queue.md
manage-passwords.md
handle-exceptions.md

파일명은 문서의 내용을 쉽게 알 수 있도록 간결하게 작성하는 것이 좋다. 소문자와 하이픈을 사용하면 운영체제나 개발 환경에 따른 파일명 차이도 줄일 수 있다.

ADR을 Git에 함께 관리하면 다음과 같은 장점이 있다.

  • 코드와 설계 결정의 변경 이력을 함께 확인할 수 있다.
  • Pull Request를 통해 ADR을 검토할 수 있다.
  • 누가 언제 결정을 추가하거나 변경했는지 확인할 수 있다.
  • 특정 코드 변경과 관련된 ADR을 연결할 수 있다.
  • 이전 버전의 결정 기록을 확인할 수 있다.

ADR 템플릿

Michael Nygard 형식

Michael Nygard의 ADR 템플릿은 구조가 간단하여 소규모 프로젝트나 ADR을 처음 도입하는 팀에서 사용하기 좋다.

# 제목

## Status

## Context

## Decision

## Consequences

제목

어떤 결정을 다루는 문서인지 명확하게 나타낸다.

제목은 단순한 주제보다 결정의 내용을 드러내는 문장으로 작성하는 것이 좋다.

데이터베이스 선택(X) --> 사용자 데이터 저장소로 PostgreSQL을 사용한다(O)

Status

현재 ADR의 상태를 나타낸다.

일반적으로 다음과 같은 상태를 사용한다.

  • Proposed: 제안됨
  • Accepted: 채택됨
  • Rejected: 거절됨
  • Deprecated: 더 이상 권장되거나 사용되지 않음
  • Superseded: 새로운 ADR에 의해 대체됨

조직이나 프로젝트의 운영 방식에 따라 Draft, Under Review, Approved 등의 상태를 추가해서 사용하기도 한다.

예:

## Status

Accepted — 2026-08-05

Context

어떤 문제와 상황 때문에 이 결정을 내려야 하는지를 작성한다.

문제의 배경과 더불어, 결정에 영향을 미치는 기술적·조직적 제약조건과 요구사항을 함께 기록한다.

Context에서는 다음 질문에 답할 수 있어야 한다.

  • 현재 어떤 문제가 있는가?
  • 왜 이 결정을 내려야 하는가?
  • 결정을 미루면 어떤 문제가 생기는가?
  • 어떤 요구사항을 만족해야 하는가?
  • 예산, 일정, 인력, 기술 환경에는 어떤 제약이 있는가?
  • 현실적으로 고려할 수 있는 대안은 무엇인가?

예:

## Context

드론의 임무는 Takeoff, Search, ConfirmTarget,
ApproachTarget, Hold, RTL의 여러 단계로 구성된다.

각 단계의 완료 조건과 실패 조건이 서로 다르기 때문에
현재 임무 상태를 명확하게 관리할 수 있는 구조가 필요하다.

검토한 대안은 다음과 같다.

- 단순한 if-else 조건문
- 유한 상태 머신
- Behavior Tree

Decision

최종적으로 어떤 설계 방식이나 변경 사항을 선택했는지 명확하게 작성한다. Decision의 핵심은 ‘무엇을 선택했는가’를 선언하는 것이다.

검토한 모든 대안의 상세한 장단점을 Decision에 전부 작성하기보다는, Context 또는 별도의 대안 비교 항목에 정리하도록 한다.

예:

## Decision

초기 버전의 드론 임무 제어 구조로
유한 상태 머신을 사용한다.

현재 임무 단계가 명확하게 정의되어 있고,
상태별 실패 조건과 안전 동작을 분리해 테스트할 수 있기 때문이다.

Decision은 모호한 표현보다 현재형의 단정적인 문장으로 작성하는 것이 좋다.

유한 상태 머신을 사용할 예정이다.

보다는

임무 제어에 유한 상태 머신을 사용한다.

와 같이 작성한다.

Consequences

이 선택으로 인해 발생하는 영향을 분석한다.

결정이 도입되었을 때 무엇이 쉬워지고 무엇이 어려워지는지, 긍정적인 영향과 부정적인 영향은 무엇인지를 포함한다.

다음과 같은 내용을 함께 기록할 수 있다.

  • 결정으로 얻는 장점
  • 새롭게 발생하는 단점과 위험
  • 추가로 발생하는 기술적 제약
  • 운영 및 유지보수에 미치는 영향
  • 비용과 일정에 미치는 영향
  • 팀원 교육이나 기술 학습의 필요성
  • 추가로 수행해야 하는 후속 작업
  • 새롭게 작성해야 하는 ADR

예:

## Consequences

긍정적인 영향:

- 현재 임무 상태를 명확하게 확인할 수 있다.
- 상태별 성공 및 실패 조건을 분리할 수 있다.
- 상태 전환에 대한 테스트를 작성하기 쉽다.

부정적인 영향:

- 상태가 많아지면 전환 조건이 복잡해질 수 있다.
- 임무를 동적으로 조합하는 데에는 한계가 있다.

후속 작업:

- 각 상태의 진입 조건과 종료 조건을 정의해야 한다.
- 상태별 timeout을 정의해야 한다.
- 비정상 상황에서 Hold와 RTL 중 어떤 상태로 전환할지 결정해야 한다.

좋은 ADR의 조건

1. 하나의 ADR에서는 하나의 결정만 다룬다

너무 큰 주제를 하나의 문서에 모두 넣지 않는 것이 좋다.

예를 들어 드론 전체 시스템 구조 결정이라는 하나의 ADR에 모든 내용을 넣기보다는 다음과 같이 서로 독립적으로 검토할 수 있는 개별 결정으로 나누어 문서화한다.

  • 자연어 기반 객체 검출 모델을 선택한다.
  • 목표물의 3차원 위치 추정 방식을 선택한다.
  • 탐색 경로 생성 방식을 선택한다.

하나의 결정이 다른 결정과 밀접하게 관련되어 있다면, 하나의 문서에 모두 합치는 대신 별도의 ADR로 작성한 뒤 서로 링크하는 것이 좋다.

2. 검토한 대안과 제외한 이유를 기록한다

최종 선택을 선택한 이유뿐만 아니라, 현실적으로 검토했던 다른 대안과 각 대안을 제외한 이유도 기록한다.

예:

대안 A: 단순 if-else 구조
- 구현은 빠르지만 상태가 증가할수록 조건문이 복잡해진다.

대안 B: 유한 상태 머신
- 현재 정의된 임무 단계를 명확하게 표현할 수 있다.

대안 C: Behavior Tree
- 확장성은 높지만 현재 프로젝트 규모에 비해 학습 및 구현 비용이 크다.

모든 가능한 기술을 조사할 필요는 없고, 당시 현실적으로 채택 가능했던 주요 대안을 기록하면 된다.

3. 결정의 긍정적·부정적 영향을 모두 기록한다

최종 선택으로 얻게 되는 장점뿐만 아니라, 그 선택 때문에 감수해야 하는 단점과 위험도 함께 작성한다. 즉, 결정으로 인해 발생하는 trade-off를 솔직하게 기록해야 한다는 것.

예:

장점:
- 상태 전환 과정을 명확하게 추적할 수 있다.
- 상태별 안전 조건을 분리할 수 있다.

단점:
- 상태의 수가 증가하면 전환 규칙이 복잡해질 수 있다.
- 동적으로 임무를 조합하기는 어렵다.

4. 기존 기록을 조용히 고치지 않는다

ADR은 당시의 상황과 판단을 기록한 문서다. 시간이 지나 결정이 잘못되었다고 판단되거나 상황이 바뀌더라도, 과거의 ADR 내용을 현재의 기준에 맞게 조용히 덮어쓰면 안된다.

결정이 변경되었다면 다음과 같은 방법을 사용할 수 있다.

  1. 기존 ADR에 새로운 정보를 날짜와 함께 추가한다.
  2. 새로운 ADR을 작성한다.
  3. 기존 ADR의 상태를 Superseded로 변경한다.
  4. 기존 ADR에 새 ADR의 링크를 추가한다.
  5. 새 ADR에도 어떤 이전 결정을 대체하는지 기록한다.

예:

## Status

Superseded by ADR-0012 — 2026-10-20

이렇게 관리하면 단순히 현재의 결정만 알 수 있는 것이 아니라, 시간이 지나면서 아키텍처가 어떤 이유로 변화했는지까지 추적할 수 있다.

5. 중요한 결정만 기록한다

모든 구현 세부사항을 ADR로 작성하면 문서의 수가 지나치게 많아지고, 정작 중요한 결정을 찾기 어려워질 수 있다.

다음과 같은 결정은 ADR 작성 대상으로 고려할 수 있다.

  • 변경 비용이 큰 결정
  • 여러 팀원이나 컴포넌트에 영향을 주는 결정
  • 시스템의 성능, 보안, 안정성에 큰 영향을 주는 결정
  • 장기간 유지될 가능성이 높은 결정
  • 여러 대안 사이에서 의미 있는 비교가 필요했던 결정
  • 나중에 “왜 이렇게 구현했는가?”라는 질문이 나올 가능성이 높은 결정

반면,

  • 변수명 선택
  • 단순한 함수 분리
  • 일시적인 실험 코드
  • 쉽게 되돌릴 수 있는 작은 구현 변경
  • 팀 전체에 영향을 주지 않는 개인적인 코딩 방식

과 같은 세세한 내용은 ADR로 작성하지 않아도 된다.

6. 결정의 배경을 모르는 사람도 이해할 수 있게 작성한다

ADR은 작성자 자신만 보는 개인 메모가 아니다. 미래의 팀원과 유지보수 담당자도 읽을 수 있도록 작성해야 한다. 프로젝트 내부에서만 사용하는 약어와 맥락을 지나치게 생략하지 않는 것이 좋다. 필요한 경우 관련 요구사항, 이슈, 코드, 다이어그램의 링크를 추가한다.

예:

## Related Artifacts

- 요구사항: docs/requirements.md
- 상태 전환도: docs/mission-state-diagram.drawio
- 구현 코드: src/mission_manager.py
- 테스트: tests/test_state_transition.py

7. 간결하지만 결정에 필요한 정보는 빠뜨리지 않는다

문서를 길게 작성하는 것보다 다음 질문에 명확하게 답하는 것이 중요하다.

  • 무엇을 결정했는가?
  • 왜 이 결정이 필요했는가?
  • 어떤 대안을 검토했는가?
  • 왜 이 대안을 선택했는가?
  • 이 결정으로 무엇이 달라지는가?

ADR 작성 예시

# ADR-0003: 임무 제어에 유한 상태 머신을 사용한다

## Status

Accepted — 2026-08-05

## Context

드론은 Takeoff, Search, ConfirmTarget,
ApproachTarget, Hold, RTL의 여러 단계를 수행한다.

각 단계의 성공 조건과 실패 조건이 다르기 때문에
현재 임무 상태와 상태 전환 조건을 명확하게 관리해야 한다.

검토한 대안은 다음과 같다.

- 단순 if-else 구조
- 유한 상태 머신
- Behavior Tree

단순 if-else 구조는 초기 구현은 쉽지만,
상태가 증가할수록 조건문이 복잡해질 가능성이 높다.

Behavior Tree는 임무 확장에 유리하지만,
현재 프로젝트 규모에 비해 구현 및 학습 비용이 크다.

## Decision

초기 버전의 임무 제어 구조로 유한 상태 머신을 사용한다.

각 임무 단계를 독립적인 상태로 정의하고,
성공 조건, 실패 조건 및 안전 전환 조건을 명시한다.

## Consequences

긍정적인 영향:

- 현재 임무 상태를 명확하게 추적할 수 있다.
- 상태별 성공 및 실패 조건을 테스트할 수 있다.
- 센서 오류나 통신 장애 발생 시 안전 전환을 명시할 수 있다.

부정적인 영향:

- 상태의 수가 증가하면 상태 전환 규칙이 복잡해질 수 있다.
- 동적으로 임무를 조합하는 기능에는 한계가 있을 수 있다.

후속 작업:

- 상태별 timeout을 정의한다.
- Hold와 RTL 전환 조건을 정의한다.
- 상태 전환 로그를 구현한다.

마무리

ADR은 당시 어떤 상황에서 어떤 대안을 검토했고, 왜 해당 결정을 내렸으며, 그 결정으로 인해 무엇이 달라지는지를 기록하는 문서다.

코드에는 의사결정의 결과만 남지만, ADR은 코드가 놓치는 의사결정의 맥락을 보존하는 역할을 한다.

요약: ADR은 중요한 아키텍처 결정의 내용과 이유, 그리고 그 결과를 미래의 개발자에게 전달하기 위한 결정 기록 문서

참고자료

https://github.com/architecture-decision-record/architecture-decision-record

0개의 댓글