Hook
“왜 이렇게 했지?” 6개월 전의 결정을 기억하지 못합니다. 코드에는 “무엇”과 “어떻게”는 있지만 “왜”는 없습니다. 그래서 같은 논의가 반복되고, 이미 기각된 대안이 다시 제안됩니다.
ADR (Architecture Decision Record) 은 “왜”를 기록하는 도구입니다. 세 프로젝트에서 작성된 14개의 ADR에서 가장 흥미로운 트레이드오프를 소개합니다.
TL;DR
- ADR은 “왜 이 결정을 했는가”를 기록하는 짧은 문서 — Context, Decision, Rationale, Consequences 구조
- 14개 ADR 중 핵심 7개 선별: 플랫폼 선택, 파일 분할, i18n 방식, 인증 전환, 테스팅 전략 등
- 가장 중요한 교훈: “기각된 대안”을 기록하는 것이 “선택한 결정”을 기록하는 것보다 가치 있다
- 이 글은 AI 주도 개발 거버넌스 시리즈의 마지막 편입니다
Background: ADR이 필요한 순간
ADR이 필요한 경우
| 상황 | 예시 |
|---|---|
| 새 외부 의존성 | “상태 관리 라이브러리를 X로 정함” |
| DB 스키마 변경 | “users 테이블에 gender 컬럼 추가” |
| API 설계 원칙 변경 | “에러 응답 형식을 envelope 방식으로” |
| 플랫폼 변경 | “Cloudflare Workers를 주 플랫폼으로” |
| 보안 결정 | “PIN 인증 → OAuth로 전환” |
| 성능/비용 트레이드오프 | “빌드 도구 없이 순수 파일 분할만” |
ADR이 불필요한 경우
- 버그 수정
- 기존 패턴 내 기능 추가
- 동일 아키텍처 내 리팩터링
- 문서 업데이트
ADR 구조
# ADR-XXXX: 결정 제목
## Status
Accepted | Superseded by ADR-XXXX | Deprecated
## Context
왜 이 결정이 필요한가? (문제 상황, 제약 조건)
## Decision
무엇을 결정했는가? (구체적 선택)
## Rationale
왜 이 선택을 했는가? (대안 포함, 기각 이유)
## Consequences
이 결정의 결과는? (긍정/부정적 영향)
Solution: 핵심 ADR 7선
ADR 1: 엣지 우선 플랫폼 채택
Context: SaaS 에코시스템을 구축해야 하는데, 인프라 관리 부담을 최소화하면서 글로벌 배포가 필요
Decision: Cloudflare Workers(D1/R2/KV/Queues)를 주 플랫폼으로 채택. 단, 코어 로직은 추상화 계층으로 접근
기각된 대안:
- Lambda — 콜드 스타트, 복잡한 설정
- Vercel + Supabase — 비용, egress 요금
- 자체 호스팅 — 인프라 관리 부담
Consequences: 글로벌 엣지 배포, 무료 티어 전 스택, 무료 egress. 트레이드오프: D1 500MB 제한, CPU 10ms
ADR 2: API 우선 개발 원칙
Context: AI 도구 기반 개발에서 “프리뷰 → 코드 → 데이터” 순서 역전이 반복됨
Decision: 도메인 → 스키마 → 컨트랙트 → UI → 디자인 순서를 4단계 게이트로 강제
Rationale: 순서 역전이 데드 버튼, 목 데이터, 상태 누락의 근본 원인으로 진단됨
Consequences: 개발 속도 일시적 저하, but 장기적 부채 급감. → 이 시리즈 (2)에서 상세히 다룸
ADR 3: 단일 파일 → 기능별 분할 전환
Context: 단일 HTML 파일이 346KB/7600줄까지 성장. AI 컨텍스트 비효율, 머지 충돌, 캐싱 비효율
Decision: 빌드 도구는 도입하지 않고 순수 파일 분할만으로 4-Phase 마이그레이션
Rationale: 빌드 도구 도입은 원래 아키텍처 결정(오프라인 PWA, 무료 호스팅)의 정신을 훼손
Consequences: AI 컨텍스트 80% 절약, Git diff 가독성 향상. 트레이드오프: 수동 파일 관리 부담. → (3)에서 상세
ADR 4: PIN 인증 → OAuth 전환
Context: 4자리 PIN 인증은 보안이 약하고, 기기 간 동기화가 안 됨
Decision: Google/Kakao OAuth 2.0 Authorization Code Flow 도입. HttpOnly 쿠키, JWT 1h/Refresh 7d
기각된 대안:
- 이메일/비밀번호 — 관리 부담, 비밀번호 리셋 필요
- Magic link — 이메일 의존, 지연
Consequences: 보안 강화, 기기 간 동기화. 트레이드오프: 외부 의존성 (Google/Kakao 가용성)
ADR 5: GNU gettext 원문 키 채택
Context: 구조적 키(
t('ui.a_065'))의 가독성/관리 부담이 심각Decision: GNU gettext 원문 키 방식 채택. 듀얼 모드(점 유무로 분기)로 점진적 마이그레이션
Consequences: 키 발명 단계 제거, 296건 → 0건 마이그레이션 완료. → (4)에서 상세
ADR 6: 레이어드 테스팅 (E2E 최후)
Context: E2E 우선 테스트가 느리고(12~15분), 불안정(30% flaky)하여 CI 차단
Decision: Unit → Component → Contract → E2E Smoke 바텀업 전환. E2E는 스모크 5~10개만
Consequences: CI 시간 1~2분, flaky 5% 미만. → (5)에서 상세
ADR 7: 시간형 운동 타입 도입
Context: 플랭크 등 시간/횟수 맨몸 운동이 중량 모델에 억지로 끼워맞춰짐
Decision:
type:'timed'필드 도입. duration +5초 오버로드, 볼륨 계산 제외Rationale: 모든 운동을 “중량 × 횟수” 모델에 맞추는 것은 도메인 왜곡
Consequences: 볼륨 계산에서 시간형 제외. 오버로드 알고리즘 분기 필요
ADR 전체 목록 (14건)
전체 ADR 목록 보기
SaaS 모노레포 (5건)
| ADR | 결정 | 상태 |
|---|---|---|
| 0001 | 엣지 우선 플랫폼 채택 | Accepted |
| 0002 | API 우선 개발 원칙 | Accepted |
| 0003 | 프론트엔드 파일 분리 | Accepted |
| 0004 | GNU gettext 국제화 채택 | Accepted |
| 0005 | 레이어드 프론트엔드 테스팅 | Accepted |
AI 뉴스 서비스 (1건)
| ADR | 결정 | 상태 |
|---|---|---|
| 0001 | Cloudflare 스택 선택 (8가지 근거) | Accepted |
피트니스 PWA (8건)
| ADR | 결정 | 상태 |
|---|---|---|
| 0001 | 단일 파일 정적 PWA 아키텍처 | 부분 폐기 (ADR-0006으로) |
| 0002 | SNS OAuth 인증 도입 | Accepted |
| 0003 | 성별 기반 시작 중량 도입 | Accepted |
| 0004 | 난이도별 포즈 가이드 영상 분기 | Accepted |
| 0005 | 시간형 운동 타입 도입 | Accepted |
| 0006 | 단일 파일 → 기능별 분할 | Accepted (0001 부분 폐기) |
| 0007 | i18n 아키텍처 도입 | Accepted |
| 0008 | GNU gettext 원문 키 방식 | Accepted |
Result: ADR 도입 효과
| 지표 | ADR 도입 전 | ADR 도입 후 |
|---|---|---|
| “왜 이렇게 했지?” 질문 | 주 2~3회 | 거의 없음 (ADR 링크로 응답) |
| 같은 논의 반복 | 월 1~2회 | 0회 (기각 대안 기록) |
| 온보딩 시간 | 구두 설명 필요 | ADR 읽기로 자가 학습 |
| 결정 일관성 | 구두 합의 → 누락 | 기록된 결정 기준 |
가장 가치 있는 ADR: “부분 폐기”
ADR-0001(단일 파일 PWA)이 ADR-0006(기능별 분할)에 의해 부분 폐기된 것이 가장 instructive합니다:
ADR-0001: "단일 파일이 최고다" (2026-06-04)
↓ 2주 후
ADR-0006: "346KB가 됐다. 분할하자. 단, 빌드 도구는 안 도입한다." (2026-06-18)
Status: ADR-0001 부분 폐기
교훈: 결정을 번복하는 것은 실패가 아닙니다. 번복한 이유를 기록하는 것이 가치 있습니다. ADR-0001의 Context(오프라인 보장, 무료 호스팅)는 여전히 유효하고, ADR-0006은 그 정신을 유지하면서 부채만 해결합니다.
Takeaway
ADR의 가장 큰 가치는 “기각된 대안”에 있습니다 — “Cloudflare Workers를 선택했다”는 기록보다 “Lambda는 콜드 스타트 때문에 기각했다”는 기록이 더 가치 있습니다. 6개월 후 누군가 “Lambda로 바꾸자”고 제안했을 때, ADR이 있으면 이미 논의된 근거로 즉시 응답할 수 있습니다. 기각 이유가 기록되어 있지 않으면 같은 논의가 무한히 반복됩니다
결정을 번복해도 괜찮습니다 — 번복한 이유만 기록하면 — ADR-0001이 ADR-0006에 의해 부분 폐기된 것은 실패가 아니라 학습입니다. “단일 파일이 최고라고 생각했는데, 346KB가 되니까 AI 컨텍스트가 비효율적이더라. 그래서 분할하되 원래 정신(빌드 도구 없음)은 유지한다.” 이 학습이 기록되어 있으면, 다음에도 같은 실수를 반복하지 않습니다. Status: Superseded 표시 하나가 결정의 진화를 보여줍니다
AI 주도 개발에서 ADR은 더 중요합니다 — AI 에이전트는 이전 결정의 맥락을 모릅니다. “왜 빌드 도구를 안 쓰고 있지?”라는 의문을 가진 AI가 “Webpack을 도입하겠습니다”라고 제안할 수 있습니다. ADR-0006의 Rationale이 있으면 “빌드 도구 도입은 원래 아키텍처 결정의 정신을 훼손하므로 기각”이라는 명확한 거부 이유를 AI에게 제공할 수 있습니다. ADR은 AI 에이전트에게도 읽혀야 하는 문서입니다
시리즈 마무리
이것으로 AI 주도 개발 거버넌스 시리즈 7편을 마칩니다.
| 편 | 제목 | 핵심 |
|---|---|---|
| (1) | 10가지 함정 | 순서 역전 진단 + 10원칙 |
| (2) | 4단계 디자인 게이트 | 프리뷰 역설 해법 |
| (3) | 모놀리식 HTML 분할 | AI 컨텍스트 절약 |
| (4) | gettext 원문 키 | 키 발명 종결 |
| (5) | 레이어드 테스팅 | E2E 최후의 수단 |
| (6) | 3-Tier CI 게이트 | 기계가 규칙을 지킨다 |
| (7) | ADR 14선 | “왜”를 기록하라 |
거버넌스는 살아있는 문서입니다. 새로운 문제를 겪을 때마다 원칙을 하나씩 추가하고, 그 원칙을 자동화로 뒷받침하는 과정이 중요합니다. 완벽한 거버넌스는 없지만, 진화하는 거버넌스는 있습니다.
| ← 이전 | 시리즈: AI 주도 개발 거버넌스 | 다음 → |
|---|---|---|
| (6) 3-Tier CI 게이트 | (7) ADR 14선 | — (시리즈 끝) |
게이트웨이 On-promise 제품 팀에서 시스템 모니터링 및 관리를 쉽게 다가갈 수 있도록 하기 위한 업무를 하고 있습니다.
Contact: lhjnano@gmail.com