Step 15. 선택의 기술 — 트레이드오프와 결정의 기록

만화로 보는 요약 — 먼저 읽어보세요
정답표 대신 도메인 복잡도·조직 규모·수명과 무결성의 세 다이얼을 읽고, 되돌리기 비싼 선택과 그 대가를 ADR로 남긴다.
면접 실전 질문: ① 아키텍처 선택의 세 다이얼은 무엇인가? ② ADR에는 어떤 항목을 남기는가? ③ 왜 결정의 나쁜 결과도 기록해야 하는가?
이 장의 질문: 도구는 전부 손에 있다. 이제 실제 상황 앞에서 — 무엇을 근거로 고르고, 그 선택을 어떻게 남기는가? 그리고 이 책의 첫 문장이었던 정의는, 열다섯 장을 지나 어떤 모습으로 돌아오는가?
1. 정답표는 없지만 판단 절차는 있다
독자가 이 장에 기대할 법한 것부터 부수자: “팀 규모 N명, 트래픽 M이면 아키텍처 X”라는 표는 존재할 수 없다. 제1법칙(Step 04)이 그 이유다. 모든 선택이 트레이드오프라면, 정답은 상황(무엇을 포기할 수 있는가)의 함수이지 입력값의 함수가 아니다. 목표는 최선(best)이 아니라 가장 덜 나쁜(least worst) 것이었다.
정답표 대신 이 장이 주는 것은 세 가지다. 상황을 읽는 다이얼(2절), 결정을 남기는 문법(3절), 그리고 결정 앞에서 도는 체크리스트(4절).
2. 세 개의 다이얼로 상황을 읽는다
아키텍처 선택에 들어가는 변수는 수십 개지만, 이 책의 여정에서 반복해 등장한 지배 변수는 셋이다. 각 다이얼은 특정 품질 속성의 몸값을 올린다.
다이얼 1: 도메인 복잡도. 규칙과 불변식이 얼마나 많고 자주 자라는가.
- 낮음 → 빈혈 모델 + 트랜잭션 스크립트가 정직함이다(Step 06). 레이어드로 충분하다.
- 높음 → 리치 도메인 모델(Step 07)과 그것을 지킬 벽(헥사고날, Step 08)의 할증이 정당화된다. 갈림길의 교차점은 지나고서야 보이므로(Step 07), 복잡도가 자라는 추세라면 그것이 신호다.
다이얼 2: 조직 규모. 몇 팀이 이 시스템을 함께 바꾸는가.
- 한 팀 → 모놀리스. 경계는 패키지로 충분하다.
- 여러 팀 → 컨텍스트·모듈·팀의 삼중 정렬(Step 09)이 사활 문제가 된다. 모듈러 모놀리스(Step 10)가 기본값이고, 배포 조율이 실측된 병목이 된 모듈만 서비스로 뗀다. 분산의 물리학(Step 10)은 그때 지불해도 늦지 않다.
다이얼 3: 수명과 무결성 요구. 얼마나 오래 살고, 틀리면 얼마나 비싼가.
- 짧고 관대함(프로토타입, 캠페인) → 구조 투자 최소화. 버릴 것이라면 진흙이어도 좋다(Step 05의 Throwaway Code). 단, 정말 버려진다는 보장이 있을 때만이다.
- 길고 엄격함(금융, 원장) → 무결성이 가용성에 앞서고(Step 04, 11), 불변 원장·대사·적합도 함수(Step 11, 12)가 선택이 아니라 요건이 된다.
다이얼을 읽는 순서도 여정이 가르쳐준 대로다. 안에서 밖으로 읽는다. 도메인 모델의 형태(다이얼 1)를 먼저, 경계와 소유권(다이얼 2)을 다음에, 배포 토폴로지는 마지막에, 그리고 가능하면 미룬 채로(최종 책임 시점, Step 12). 유행의 순서는 흔히 그 반대라는 점(“일단 마이크로서비스로”)이, 유행이 자주 실패하는 이유다.
3. 결정의 문법은 ADR이다
무엇을 고를지 알았다면, 남는 일은 남기는 것이다. Step 01에서 Perry & Wolf가 아키텍처의 세 요소에 rationale(근거)을 넣었을 때부터 예약된 결말이다. 근거가 아키텍처의 일부라면, 근거를 저장할 형식이 필요하다.
Michael Nygard가 2011년에 제안한 아키텍처 결정 기록(ADR, Architecture Decision Record)이 그 형식이다. 마크다운 한 장, 다섯 항목:
# ADR-007: 정산 원장은 추가 전용으로 하고 수정은 역분개로만 한다
## Status
Accepted (2026-07-16)
## Context
정산 금액 정정 요구가 월 평균 12건. 현재는 UPDATE로 원본을 덮어쓰고 있어
감사 시점에 "왜 이 값인가"를 재구성할 수 없다. 금융 규제상 변경 이력의
완전성이 요구된다. 팀은 이벤트 소싱 전면 도입을 검토했으나 운영 경험이 없다.
## Decision
원장 테이블을 추가 전용(append-only)으로 전환한다. 정정은 역분개 행 추가로만
한다. 이벤트 소싱 전면 도입은 하지 않는다 — 원장 하나에만 그 규율을 적용한다.
## Consequences
+ 모든 잔액이 행의 합으로 재구성 가능 — 감사 추적 완결.
+ 정정의 이력이 업무 언어(역분개)로 남는다.
- 조회가 집계 쿼리가 된다 — 잔액 스냅숏 테이블(읽기 모델)이 추가로 필요하다.
- UPDATE에 익숙한 팀의 학습 비용. 기존 정정 화면 재작업 2주.구조가 곧 규율이다. Context는 “그때 우리가 알던 것”을 박제한다. 6개월 뒤 이 결정이 이상해 보일 때, 틀린 것이 결정이었는지 상황이 바뀐 것인지는 이 기록으로 구별한다. Consequences에는 나쁜 것을 반드시 적는다. Step 04의 교환 명세서(“X를 얻으려 Y를 지불했다”)가 문서 형식이 된 것이며, 지불 항목이 없는 ADR은 트레이드오프를 아직 못 본 것이다(제1법칙의 따름정리). 그리고 ADR은 불변이다. 결정이 바뀌면 수정하지 않고 새 ADR이 이전 것을 대체(supersede)한다. 원장과 역분개, 낯익은 규율이다.
보관 위치는 코드 옆(docs/adr/)이다. 위키가 아니라 저장소에 둔다. 결정은 코드와 함께 버전되고, 코드 리뷰의 대상이 되고, 코드를 읽는 사람의 손이 닿는 곳에 있어야 하기 때문이다. 무엇이 ADR감인가의 판별은 이 책의 정의가 해준다. 되돌리기 비싼 결정이면 쓴다. 라이브러리 하나 고르는 것은 대개 아니고, 원장의 저장 모델은 확실히 그렇다.
4. 결정 앞에서 여덟 개를 묻는다
실제 결정 앞에서 도는 질문 여덟 개. 각각이 이 책의 장 하나씩을 등에 업고 있다.
- 이것은 되돌리기 비싼 결정인가? (Step 01) 아니라면 그냥 하라. 체크리스트는 여기서 끝이다. 모든 결정을 아키텍처 결정으로 만드는 것 자체가 병이다.
- 미룰 수 있는가, 또는 미룰 수 있게 만들 수 있는가? (Step 02, 12) 결정하지 않는 구조(포트, 모듈 경계)가 결정보다 나을 때가 많다.
- 무엇을 얻고, 무엇을 지불하는가? (Step 04) 지불 항목이 안 보이면 결정할 준비가 안 된 것이다.
- 그 “얻는 것”은 측정 가능한 문장인가? (Step 04) 품질 속성 시나리오로 쓸 수 없는 이득은 소망이지 근거가 아니다.
- 변경의 결을 따르는가? (Step 02, 05) 함께 바뀌는 것이 같은 쪽에 묶이는가. 자주 바뀌는 것이 화살표를 받게 되지는 않는가(Step 03).
- 팀 경계와 정렬되는가? (Step 09) 이 경계를 한 팀이 소유할 수 있는가. 아니라면 다이어그램은 조직에 진다.
- 데이터 소유권과 트랜잭션 경계는? (Step 07, 11) 코드 경계가 아무리 고와도 공유 데이터가 그것을 무효화한다. 경계에 걸치는 원자성 요구가 있다면 경계가 틀렸다는 신호부터 의심하라. 그리고 그 경계가 프로세스를 넘는다면, 분산의 물리학(부분 실패, CAP, 지연)을 지불할 준비가 됐는가(Step 10)?
- 방어선은 무엇인가, 그리고 기록했는가? (Step 12, 이 장) 이 결정을 지킬 적합도 함수 한 줄, 그리고 ADR 한 장. 이 둘이 없으면 결정은 6개월짜리다.
5. 흔한 오해 바로잡기
오해 1은 “선택 가이드가 있다면 결정 트리로 만들 수 있다”는 것이다. 다이얼은 이산값이 아니라 연속값이고, 서로 독립도 아니다(도메인이 복잡해지면 팀이 커지고, 팀이 커지면 수명이 길어진다). 2절은 판단을 대체하는 순서도가 아니라 판단이 살펴야 할 변수 목록이다. 자동화할 수 있는 결정은 되돌리기 싼 결정이므로 1번 질문에서 이미 걸러졌어야 한다.
오해 2는 “ADR은 관료제다”라는 것이다. 관료제는 결정을 늦추는 문서다. ADR은 이미 내린 결정을 박제하는 문서이고, 잘 쓰면 반 페이지다. 진짜 비교 대상은 “ADR 쓰는 15분”이 아니라 “2년 뒤 그 결정의 이유를 고고학하는 2주”다. 그리고 그 고고학은 대개 실패한다.
오해 3은 “결정했으면 끝이다”라는 것이다. ADR의 Status 필드와 supersede 메커니즘이 반대를 말한다. 결정은 그때의 Context 위에서만 옳고, Context는 변한다(Lehman). 좋은 팀은 결정을 번복하는 것을 실패가 아니라 학습의 기록으로 다룬다. 단, 번복도 새 ADR로 남긴다.
오해 4는 “넷플릭스/아마존이 하는 방식이 우리의 목표다”라는 것이다. 그들의 답은 그들의 다이얼 값(수백 팀, 행성 규모 트래픽, 초장수명)에 대한 least worst다. 다이얼 값이 다른데 답을 복사하는 것은, 남의 처방전으로 약을 먹는 일이다. 이 책이 아키텍처를 정답이 아니라 계기의 역사로 쓴 이유가 이것이다.
6. 요약
- 정답표는 없다. 세 다이얼(도메인 복잡도, 조직 규모, 수명·무결성)을 읽고, 안에서 밖으로(도메인 → 경계 → 배포) 결정하며, 배포는 가능한 한 미룬다.
- ADR(Nygard, 2011): Context(그때 알던 것) / Decision / Consequences(지불 항목 필수). 불변, 대체(supersede), 코드 옆에. 되돌리기 비싼 결정이면 쓴다.
- 체크리스트 여덟 질문: 되돌리기 비싼가 → 미룰 수 있는가 → 무엇을 지불하는가 → 측정 가능한가 → 변경의 결 → 팀 정렬 → 데이터 소유권 → 방어선과 기록.
- 첫 문장의 회귀: 아키텍처 = 되돌리기 비싼 결정 + 근거, 구조는 흔적, 지키는 활동까지가 아키텍처. 유행이 아니라 고통에서 출발하라.
다음 글은 닫는 글 · 다시, 변경 앞에서다. 이 책의 첫 문장을 다시 꺼내, 열다섯 장의 도구를 실제 변경 앞에서 어떻게 쓰는지 한 번 더 묶는다.
원전
| 연도 | 문헌 | 이 장에서의 역할 |
|---|---|---|
| 2011 | Nygard, Documenting Architecture Decisions (블로그) | ADR의 원전 — Title/Status/Context/Decision/Consequences |
| 2020 | Ford & Richards, Fundamentals of Software Architecture | 제1법칙·least worst의 회수 (Step 04) |
| — | 이 책의 Step 01~14 | 체크리스트 여덟 질문의 출처 — 각 질문이 장 하나씩을 압축 |