아키텍처 결정은 어떻게 기억되는가
ADR로 결정을 기록하는 방법부터 기술 부채 상환 전략, 성장 단계별 아키텍처 선택, FinOps 실천까지 — 팀의 기술 판단을 지속 가능하게 만드는 원칙을 추적한다.
- 01 시스템 설계의 모든 결정은 하나의 질문으로 귀결된다
- 02 트래픽 진입점 설계 — DNS부터 스토리지까지
- 03 시스템 설계 면접의 공통 문법
- 04 대규모 서비스 설계의 공통 언어
- 05 대규모 데이터 시스템, 무엇을 포기하고 무엇을 얻는가
- 06 시스템은 어떻게 실패하지 않는가
- 07 아키텍처 결정은 어떻게 기억되는가
“왜 우리가 MySQL을 쓰는지 아는 사람?” 이 질문에 팀에서 아무도 답하지 못한다면, 지금까지 내려온 수십 개의 결정도 같은 운명일 가능성이 높다. 아키텍처의 진짜 문제는 기술 선택이 아니라, 결정의 맥락이 사라지는 것이다. 어떻게 결정을 기억하고, 부채를 관리하고, 규모에 맞게 성장할 수 있는가?
결정을 기록한다는 것 — ADR
ADR(Architecture Decision Record)은 “우리가 왜 이 선택을 했는가”를 남기는 짧은 문서다. 형식은 단순하다. 컨텍스트(왜 이 결정이 필요했는가), 결정(무엇을 선택했는가), 대안(무엇을 고려했는가), 결과(예상한 것과 실제). 여기에 재검토 조건을 명시하는 것이 핵심이다.
# ADR-001: Kafka 대신 AWS SQS 사용
**날짜**: 2023-06-10 | **상태**: Accepted
## 결정
AWS SQS (Standard Queue) 사용.
## 고려한 대안
- Kafka: 팀이 운영 경험 없어 초기 신뢰성 불확실.
- RabbitMQ: 마찬가지로 운영 부담.
**재검토 조건**: 일일 5억 건 초과 또는 메시지 재처리 기능 필요 시
ADR의 생명주기는 Proposed → Accepted → Deprecated / Superseded로 흐른다. 잘못된 결정이 있어도 삭제하지 않는다. 새 ADR로 대체하고 기존 것에 “Superseded by ADR-012”를 남긴다. 역사를 지우는 것보다 학습 자료로 남기는 것이 팀에 더 가치 있다.
기술 부채 — 이자가 붙기 전에
Martin Fowler의 분류에 따르면 기술 부채는 의도적/비의도적, 무모한/신중한 두 축으로 나뉜다. 스타트업 초기의 “지금 출시하고 나중에 리팩터링”은 신중한 의도적 부채다. 문제는 이 부채가 계획 없이 쌓일 때다.
기술 부채를 방치할수록 이자가 복리로 붙는다. Lead Time이 늘고, Change Failure Rate가 오르고, 개발자 체감 속도가 떨어진다. 반대로 부채 상환에 지나치게 집착하면 오버엔지니어링이라는 또 다른 부채가 생긴다. 목표는 “부채 없음”이 아니라 “관리 가능한 수준의 부채 유지”다.
실천 방법은 두 가지로 압축된다. 첫째, Sprint 예산의 20%를 기술 부채 상환에 의도적으로 예약한다. PM을 설득할 때는 추상적 논리가 아니라 수치로 말한다. “인증 모듈 리팩터링 2주 투자로 향후 6개월 12일 절감 — ROI 긍정적.” 둘째, 레거시 교체는 Strangler Fig 패턴으로 점진적으로 한다. 새 서비스를 옆에 세우고 트래픽을 1% → 10% → 100%로 이전한다. 빅뱅 재작성은 Joel Spolsky가 말한 “가장 위험한 일”이다.
성장 단계에 맞는 아키텍처
“처음부터 대규모를 대비해야 한다”는 말은 대부분 틀렸다. 복잡성이 초기 탐색 속도를 죽이기 때문이다. 단계를 건너뛰지 않는 것이 원칙이다.
단계 1 (DAU < 1,000): 단일 서버. PostgreSQL 하나. 배포는 git pull.
단계 2 (DAU ~10만): ALB + 앱 서버 ×2 + Read Replica + Redis(세션).
단계 3 (DAU ~100만): Redis 캐시 계층 + SQS 비동기 + Elasticsearch.
단계 4 (DAU ~1,000만): 병목 서비스 2~3개만 선별해 마이크로서비스 분리.
단계 5 (DAU 1,000만+): 멀티 리전 + GeoDNS + Aurora Global.
마이크로서비스는 팀이 10명을 넘고 단일 코드베이스의 배포 충돌을 실제로 경험한 뒤에 도입한다. Kubernetes는 마이크로서비스가 3개 이상일 때부터 고려한다. Shopify는 단일 Rails 모놀리스로 수백억 달러 규모까지 성장했다. “모놀리스는 더 오래 유지해도 된다”는 것이 최근의 경향이다.
다음 단계로 올라갈 때: 현재 아키텍처의 한계에 반복적으로 부딪힐 때, 장애의 근본 원인이 확장성 부족일 때, 팀 규모가 운영 인원을 넘어설 때. 이 신호 없이 올라가면 불필요한 복잡성만 남는다.
비용도 아키텍처다 — FinOps
클라우드 비용의 40~50%는 EC2다. 그리고 그 중 상당 부분은 CPU 사용률 10% 미만의 인스턴스들이다. FinOps의 출발점은 가시화다. 모든 리소스에 환경, 서비스, 팀 태그를 달고 팀별 월간 비용 보고서를 돌린다. 비용이 보이면 행동이 바뀐다.
빠른 절감은 세 곳에서 나온다. 개발 환경을 업무 시간(월금 919시)에만 실행하면 EC2 비용의 70%가 줄어든다. S3 Lifecycle 정책으로 90일 이상 된 객체를 Glacier로 자동 이동하면 스토리지 비용의 83%가 절감된다. 6개월 이상 안정적으로 사용하는 서비스에는 Reserved Instance 1년 약정을 적용해 On-Demand 대비 30~40%를 아낀다.
절감하면 안 되는 것이 있다. 프로덕션 DB 다운그레이드, 모니터링 리소스, 백업 스토리지, 보안 서비스. 기준은 단순하다 — “이 절감이 신뢰성이나 성능에 영향을 주는가?” 답이 예라면, SLO 유지가 비용 절감보다 항상 우선이다.
정리
- ADR은 결정이 내려지는 순간 작성한다. “나중에”는 대부분 안 쓰게 된다.
- 기술 부채 상환에 Sprint 20%를 예약하고, 레거시 교체는 Strangler Fig으로 점진적으로 한다.
- 아키텍처는 현재 규모와 팀 크기에 맞게 유지하고, 전환 신호를 보고 나서 다음 단계로 간다.
- FinOps는 태깅과 가시화로 시작해, 개발 환경 스케줄링과 Right-sizing으로 즉시 효과를 낸다.
다음 글에서는 이 아키텍처들을 지탱하는 신뢰성 설계 — SLO, 에러 버짓, 포스트모텀 프로세스를 추적한다.