한 줄 정의
아키텍처적 결정(architectural decision) 은 시스템의 구조·비기능적 특성·의존성·인터페이스·구축 기법에 영향을 미치는 결정이며, 충분한 정보 수집·정당화·문서화·전달이라는 네 단계를 거쳐야 합니다. 이를 효과적으로 기록하는 표준 형식이 아키텍처적 결정 기록(Architectural Decision Record, ADR) 입니다.
쉽게 말하면
아키텍트의 핵심 역할은 결정을 내리는 일입니다. 그런데 결정 자체보다 더 까다로운 것은 그 결정이 왜 내려졌는지를 미래의 누군가가 이해할 수 있도록 남기는 일 입니다.
좋은 결정을 내리려면 두 가지를 동시에 해야 합니다.
첫째, 결정을 내리는 과정에서 빠지기 쉬운 함정(보신주의·사랑의 블랙홀·이메일 주도)을 피해야 합니다. 둘째, 일단 결정이 내려졌다면 그 명분과 트레이드오프를 일관된 형식으로 기록하고 적절한 사람에게 전달해야 합니다.
ADR은 그 기록을 위한 짧은 텍스트 템플릿입니다. 제목·상태·맥락·결정·결과·준수·참고의 7개 섹션으로 구성되며, 보통 1~2페이지 분량으로 한 결정을 정리합니다. 이 형식이 널리 채택된 이유는 단순함과 일관성 때문이고, 그 단순함 안에 “왜 이 결정을 내렸는가”라는 가장 중요한 정보가 자연스럽게 녹아들기 때문입니다.
왜 중요한가?
- 해결하는 문제: 결정을 내리는 행위가 끝이 아니라, 결정을 정당화하고 추적 가능하게 만드는 것 까지가 아키텍트의 책임이라는 점을 강조합니다. 결정이 사라지면 시스템이 왜 그렇게 생겼는지 아무도 답할 수 없는 상태가 됩니다.
- 이게 없다면: 같은 논의가 6개월마다 반복되거나(사랑의 블랙홀), gRPC 대신 REST를 쓰자는 결정이 원래 결정의 이유를 모른 채 뒤집혀 시스템 전체에 지연시간 사고가 발생하거나, 이메일에 흩어진 결정 사본들이 서로 충돌하는 상황이 발생합니다.
핵심 내용
아키텍처적 결정의 안티패턴
안티패턴(antipattern) 은 “처음에는 좋은 생각처럼 보이지만 결국 문제를 일으키는 것” 또는 “부정적인 결과를 낳는 반복 가능한 프로세스”로 정의됩니다.
아키텍트가 결정을 내릴 때 가장 흔히 마주치는 세 가지 안티패턴은 보통 차례로 이어집니다. 보신주의를 극복하면 사랑의 블랙홀이, 그것을 극복하면 이메일 주도 아키텍처가 등장하는 식입니다. 셋을 모두 극복해야 효과적이고 정확한 아키텍처적 결정이 가능합니다.
보신주의(Cover Your Assets) 안티패턴
아키텍트가 잘못된 선택을 할까 두려워 결정을 회피하거나 미룰 때 발생합니다. 극복 방법은 두 가지입니다.
책임이 따르는 마지막 순간(LRM)까지 기다리기
LRM(Last Responsible Moment) 은 결정을 정당화하고 검증할 정보를 충분히 확보할 수 있는 시점까지 결정을 늦추되, 개발 팀의 작업을 지연시키지 않는 시점입니다.
여기서 또 다른 안티패턴인 분석 마비(Analysis Paralysis) 를 경계해야 합니다. 분석에만 빠져 아무 것도 결정하지 못하는 상태입니다.
LRM의 판정 기준은 시간 축 위에서 비용과 위험이 교차하는 지점입니다.
graph LR subgraph 시간축["결정을 내릴 시간"] direction LR Early["초기<br/>비용 낮음<br/>위험 높음"] --> Cross["교차점<br/>= LRM"] Cross --> Late["후기<br/>비용 높음<br/>위험 낮음"] end
초기에는 정보가 부족해 위험이 높지만 결정 비용은 낮습니다. 시간이 갈수록 분석이 쌓이며 위험은 줄지만 결정을 미루는 비용(개발 지연·아키텍처 부채)이 커집니다. 비용 증가분이 위험 감소분을 넘어서는 순간이 결정을 내려야 할 때입니다.
개발 팀과의 협업으로 검증
아키텍트가 모든 기술의 세부 사항을 알 수는 없습니다. 결정한 사항이 예상대로 구현될 수 있는지를 개발 팀과 함께 확인하는 것이 중요합니다. 협업은 신속한 대응·통찰력 확보·잘못된 결정 위험 감소를 동시에 가져옵니다.
예를 들어 모든 제품 참조 데이터를 필요 서비스에 캐싱하기로 결정했다면, 그 결정대로 구현 가능한지를 팀과 확인하는 과정에서 일부 서비스의 메모리 가용량 부족이 드러날 수 있습니다. 긴밀한 협업이 있으면 이 사실을 빨리 인지하고 결정을 조정할 수 있습니다.
사랑의 블랙홀 안티패턴
사람들이 왜 아키텍트가 특정 결정을 내렸는지 몰라서 그 결정을 계속해서 논의만 하고 최종적인 결론에 이르지 못할 때 발생합니다. 1993년 영화 〈사랑의 블랙홀(Groundhog Day)〉에서 유래했으며, 주인공이 매일 2월 2일을 반복해서 사는 것에 빗댄 이름입니다.
이 안티패턴은 아키텍트가 자신의 결정을 정당화하지 못할 때(혹은 부분적으로만 정당화했을 때) 발생합니다. 정당화에는 기술적 명분과 비즈니스적 명분이 모두 필요합니다.
비즈니스 명분이 빠진 결정의 위험
예를 들어 모놀리스를 여러 서비스로 분리하는 결정을 내리고 명분으로 “기능적 측면을 분리해 각 부분을 더 적은 VM 자원에서 유지보수·배포 가능하게 한다”를 제시했다고 합시다. 이는 기술적으로는 훌륭하지만 비즈니스 측면의 논리가 빠져 있습니다.
이 명분은 “비즈니스 관점에서 왜 이 리팩터링에 비용을 지불해야 하는가”라는 질문에 답하지 못합니다. 이 질문에 답하지 못하는 결정은 6개월 뒤에 다시 도마에 오릅니다.
좋은 비즈니스 명분의 예는 다음과 같습니다.
- 새로운 비즈니스 기능성을 더 빨리 제공해 시장 출시 기간 단축
- 새 기능 개발·출시 비용 절감
비즈니스 가치 제시는 애초에 해당 결정을 내려야 하는지를 판단하는 리트머스 시험지 이기도 합니다. 비즈니스 가치가 없다면 결정을 재고해야 합니다.
가장 흔한 네 가지 비즈니스 명분
| 명분 | 설명 |
|---|---|
| 비용 | 라이선스·하드웨어·인력·구현 비용 절감 |
| 시장 출시 기간 | 새 기능을 더 빨리 제공 |
| 사용자 만족도 | 반응성·기능성으로 사용자 가치 증대 |
| 전략적 입지 | 장기적인 경쟁 우위 확보 |
비즈니스 이해관계자에게 어떤 것이 중요한지를 우선 파악해야 합니다. 시장 출시 기간을 중시하는 조직에서 단지 비용 절감만으로 결정을 정당화하는 것은 잘못된 선택일 수 있습니다.
이메일 주도 아키텍처 안티패턴
아키텍처적 결정 사항을 사람들이 놓치거나 잊어버리는 안티패턴입니다. 결정이 내려졌다는 사실 자체를 몰라서 이행할 수 없는 경우도 포함됩니다.
이메일 본문에 결정을 담지 말 것
이메일은 의사소통 도구이지만 문서 보관 저장소 가 아닙니다. 결정 사항을 이메일 본문에 그대로 담으면 이메일마다 사본이 만들어지고, 그 사본은 결정의 정당화 명분 같은 중요 세부 사항이 빠져 있기 마련입니다. 결정이 변경될 때 모든 관련자가 수정된 결정을 받았는지 확인하기도 어렵습니다.
더 나은 접근법
세부 사항은 단일 기록 시스템에 저장하고, 이메일 본문에는 결정의 성격과 맥락만 언급하며 세부 사항은 해당 저장소로의 링크로 대체합니다.
“샌드라 님, 안녕하세요. 담당하시는 업무에 직접적인 영향을 미치는 서비스 간 통신에 관한 중요한 결정을 내렸습니다. 다음 링크에서 결정 사항을 확인해 주세요.”
이 한 문장에 두 가지 좋은 관행이 동시에 들어 있습니다.
- 이메일 서두에 수신자에게 직접 영향을 미친다는 점 을 명시 — 무관한 사람에게 알리지 않는 리트머스 시험지
- 결정 사항이 있는 단일 위치로의 링크 만 제공 — 단일 기록 시스템(single source of truth) 보장
아키텍처적 중요성(Architecturally Significant)
특정 기술 결정은 아키텍처적 결정이 아니라 단순한 기술적 결정이라고 믿는 아키텍트도 있습니다. 하지만 마이클 나이가드의 정의에 따르면 다음에 영향을 미치는 결정은 아키텍처적으로 중요한 결정입니다.
구조(structure)
사용 중인 아키텍처 패턴이나 스타일에 영향을 미치는 결정. 예를 들어 마이크로서비스 집합이 코드를 공유하도록 한 결정은 마이크로서비스의 경계 컨텍스트에 영향을 미치므로 시스템의 구조에 대한 결정입니다.
비기능적 특성(non-functional characteristic)
성능·확장성·가용성 같은 아키텍처 특성에 영향을 미치는 결정. 특정 제품이나 프레임워크 선택이라도 그 선택이 아키텍처 특성을 직접 좌우한다면 아키텍처적 결정입니다.
의존성(dependency)
시스템을 구성하는 컴포넌트나 서비스 사이의 결합점에 대한 결정. 의존성은 확장성·모듈성·민첩성·테스트성·신뢰성에 영향을 미치므로 아키텍처적 결정에 해당합니다.
인터페이스
시스템·사용자·다른 요소들이 서비스나 컴포넌트에 접근·오케스트레이션하는 방식. 게이트웨이·통합 허브·서비스 버스·어댑터·API 프록시 등이 포함되며, 일반적으로 버전 관리와 지원 중단 전략을 포함한 계약 정의가 따릅니다.
구축 기법(construction technique)
플랫폼·프레임워크·도구·프로세스에 관한 결정. 본질적으로 기술적이지만 아키텍처의 특정 측면에 영향을 미칠 수 있습니다.
이 다섯 카테고리는 결정 사항이 ADR로 남길 가치가 있는지 판단하는 실용적인 체크리스트입니다.
아키텍처적 결정 기록(ADR)
ADR(Architectural Decision Record) 은 마이클 나이가드가 2011년 블로그 게시물에서 처음 주창했고, 2017년에 소트웍스 기술 레이더에 등재되며 널리 채택되었습니다. 보통 1~2페이지 분량의 짧은 텍스트 파일이며, AsciiDoc·Markdown 같은 텍스트 형식으로 작성합니다.
기본 구조
ADR은 표준 다섯 섹션 + 권장 두 섹션, 총 일곱 섹션으로 구성됩니다.
| 섹션 | 역할 |
|---|---|
| 제목(Title) | 결정을 짧게 표현하는 일련번호 + 문구 |
| 상태(Status) | 제안됨·수락됨·대체됨 |
| 맥락(Context) | 이 결정을 내리게 된 이유 |
| 결정(Decision) | 결정 사항과 명분 |
| 결과(Consequences) | 이 결정이 미치는 영향 |
| 준수(Compliance) | 결정을 어떻게 측정·거버넌스할지 (권장) |
| 참고(Notes) | 작성자·승인자·생성일 등 메타데이터 (권장) |
제목 섹션
문서 일련번호 + 결정을 설명하는 짧은 구문. 예를 들어 “42. 주문 서비스와 결제 서비스 간 비동기 메시징 사용”. 모호함을 없앨 만큼 충분히 설명적이되 짧게 유지합니다.
상태 섹션
세 가지 핵심 상태를 갖습니다.
stateDiagram-v2 [*] --> Proposed: 작성 Proposed --> Accepted: 승인 Accepted --> Superseded: 변경 발생 Superseded --> [*]
- 제안됨(Proposed): 상위 의사 결정권자나 ARB(Architecture Review Board)의 승인 대기
- 수락됨(Accepted): 승인되어 구현 준비 완료
- 대체됨(Superseded): 다른 ADR로 대체됨. 항상 이전 상태가 수락됨이었음을 전제
대체됨 상태는 역사적 추적의 핵심입니다. ADR 42(“주문과 결제 서비스 간 비동기 메시징 사용”)가 수락됨이었는데, 나중에 REST를 쓰기로 바뀌면 새 ADR 68을 만들고 다음과 같이 기록합니다.
ADR 42. 주문과 결제 서비스 간 비동기 메시징 사용
상태: 68번에 의해 대체됨
ADR 68. 주문과 결제 서비스 간 REST 사용
상태: 수락됨, 42번을 대체함
이렇게 양방향 링크를 남기면 누군가가 ADR 68에 대해 “그냥 메시징을 쓰면 어떨까요?”라고 묻는 일을 막을 수 있습니다. 과거의 결정 이유까지 추적 가능해지기 때문입니다.
RFC 상태 추가
표준 세 상태 외에 의견 수렴 중(RFC, Request for Comments) 상태를 추가하면 협업이 활발해집니다. ADR 초안을 공유해 의견을 받고 마감 일자를 명시한 뒤, 마감 후 의견을 취합·분석해 최종 결정을 내립니다. 이때 상태를 ‘제안됨’(또는 아키텍트에게 직접 승인 권한이 있다면 ‘수락됨’)으로 변경합니다.
상태 섹션의 또 다른 가치는 승인 권한의 경계 를 명시한다는 점입니다. 비용·팀 간 영향·보안 세 기준점에서 어디까지 아키텍트가 직접 승인 가능한지(예: 5,000달러 초과는 ARB 승인 필요)를 미리 합의하면, 모든 ADR 작성자가 자신의 결정을 직접 승인할 수 있는지 즉시 알 수 있습니다.
맥락 섹션
“어떤 상황 때문에 이 결정을 내려야 하는가?”에 대한 답입니다. 구체적인 상황 + 가능한 대안들을 간결히 설명합니다. 분석을 더 자세히 문서화해야 한다면 별도의 대안(Alternatives) 섹션을 추가하는 것이 좋습니다.
맥락 섹션은 아키텍처 자체를 문서화하는 공간 이기도 합니다. 예를 들어 “주문 서비스는 현재 진행 중인 주문 건을 결제하기 위해 결제 서비스로 정보를 전달해야 한다. REST나 비동기 메시징을 사용해서 수행할 수 있다.”처럼 한두 문장에 시나리오와 대안이 모두 명시됩니다.
결정 섹션
결정에 대한 설명과 충분한 명분을 담습니다. 핵심 원칙은 수동적인 어조가 아닌 긍정적이고 단정적인 어조 입니다.
| 좋은 표현 | 나쁜 표현 |
|---|---|
| ”서비스 간 통신에는 비동기 메시징을 사용하기로 한다" | "서비스 간 통신에는 비동기 메시징이 최선의 선택이라고 생각한다” |
후자는 결정이 무엇인지조차 불분명하게 만듭니다. 결정 섹션의 가장 강력한 측면은 명분 강조 입니다. 어떤 결정이 내려진 이유 를 이해하는 것이 어떻게 동작하는지 이해하는 것보다 훨씬 중요합니다.
새로 온 아키텍트가 “왜 gRPC를 쓰는가”의 이유를 모르면 일관성을 위해 REST로 바꿉니다. 그러면 원래 gRPC를 선택한 이유였던 지연시간 단축이 사라져 상위 시스템에서 타임아웃이 발생합니다. ADR이 있었다면 막을 수 있었던 사고입니다.
결과 섹션
결정이 미치는 좋은 영향과 나쁜 영향을 모두 서술합니다. 트레이드오프 분석을 문서화하기에도 좋은 공간입니다.
예를 들어 리뷰 게시 기능에 ‘발사 후 망각(fire-and-forget)’ 비동기 메시징을 채택해 반응성이 3,100ms → 25ms로 단축됨을 명분으로 제시했다고 합시다. 어떤 팀원이 “금칙어가 포함된 리뷰가 게시되면 어떡하죠?” 같은 이의를 제기할 수 있습니다.
이미 트레이드오프 분석 단계에서 그 문제가 논의되었고 “복잡한 오류 처리를 감수하더라도 반응성을 우선한다”는 합의에 이르렀다면, 그 분석을 결과 섹션에 담아두면 같은 이의가 미연에 방지됩니다.
준수(Compliance) 섹션
표준 ADR에는 없지만 강력히 권장되는 추가 섹션입니다. 결정을 어떻게 측정하고 거버넌스할지를 명시합니다.
핵심 질문 두 가지입니다.
- 사람이 수동으로 확인할 것인가, 아니면 적합성 함수로 자동화할 것인가?
- 자동화 가능하다면 어떻게 작성할 것이며 코드베이스에 어떤 변경이 필요한가?
예시로, n층 아키텍처에서 비즈니스 객체가 사용하는 모든 공유 객체를 공유 서비스 계층에 두기로 한 결정을 자바의 ArchUnit으로 자동 점검하는 코드입니다.
@Test
public void shared_services_should_reside_in_services_layer() {
classes().that().areAnnotatedWith(SharedService.class)
.should().resideInAPackage("..services..")
.check(myClasses);
}@SharedService 애너테이션을 만들고 모든 공유 클래스에 붙이면 위 적합성 함수가 위반을 자동 검출합니다. 거버넌스가 코드로 박제되는 셈입니다.
참고(Notes) 섹션
표준에는 없지만 권장되는 메타데이터 섹션입니다.
- 최초 작성자
- 승인 일자
- 승인자
- 대체 일자
- 마지막 수정일
- 수정자
- 마지막 수정 내용
깃 같은 버전 관리 시스템에 저장하더라도 이 정도의 추가 메타데이터를 ADR 본문에 명시해 두는 편이 유용합니다.
ADR 예시: GGG의 별도 대기열 결정
[그림 21-4]의 토폴로지를 ADR로 작성하면 다음과 같습니다.
graph LR Bid[입찰] --> BC[Bid Capture] BC -.-> Q1[(대기열 1)] Q1 -.-> BS[Bid Streamer] BC -.-> Q2[(대기열 2)] Q2 -.-> BT[Bid Tracker] BT --> DB[(DB)]
ADR 76. Bid Streamer 서비스와 Bidder Tracker 서비스를 위한 별도 대기열
상태: 수락됨
맥락: Bid Capture 서비스는 입찰을 받으면 Bid Streamer와 Bidder Tracker에 전달해야 한다. 단일 토픽(발행/구독), 서비스마다 별도 대기열(점대점), 또는 REST를 사용할 수 있다.
결정:
- Bid Streamer와 Bidder Tracker에 별도 대기열을 사용하기로 한다.
- Bid Capture는 두 서비스로부터 어떤 정보도 필요하지 않다(통신은 단방향).
- Bid Streamer는 Bid Capture가 수락한 순서와 정확히 동일한 순서로 입찰을 받아야 한다. FIFO 대기열을 사용하면 자동으로 보장된다.
- 동일 호가에 대해 다수 입찰이 들어올 때 Bid Streamer는 가장 먼저 접수된 입찰만 있으면 되지만 Bidder Tracker는 모든 입찰이 필요하다. 토픽을 사용하면 Bid Streamer가 이전 호가와 동일한 입찰을 무시해야 하므로 인스턴스 간 공유 상태가 필요해진다.
- Bid Streamer는 메모리 내 캐시, Bidder Tracker는 데이터베이스에 저장하므로 Bidder Tracker가 더 느리며 배압(backpressure)이 필요할 수 있다. 별도 대기열은 배압 지점으로도 작용한다.
결과:
- 메시지 대기열의 클러스터링과 고가용성이 요구된다.
- Bid Capture는 동일 정보를 여러 대기열로 전송해야 한다.
- 내부 입찰 이벤트는 API 계층의 보안 검사를 우회한다.
- 업데이트(2025-01-14): ARB 회의 검토 결과 수용 가능한 트레이드오프이며 추가 보안 검사는 필요 없다고 결정.
규정 준수: 주기적인 수동 코드 검토로 비동기 발행/구독 메시징 사용 여부 확인.
참고: 작성자: 수바시니 나델라 / 승인: ARB 회의 / 마지막 갱신: 2025-01-14
이 형식이 보여주는 핵심은 결정 자체보다 결정의 명분이 더 큰 비중을 차지 한다는 점입니다. 단방향 통신·FIFO 보장·공유 상태 회피·배압 등 네 가지 명분이 모두 명시되어 있어, 미래의 누군가가 “그냥 토픽 쓰면 되는 거 아닌가?”라고 물어도 답을 추적할 수 있습니다.
ADR의 저장
모든 아키텍처적 결정은 별도로 저장해야 합니다. 소스 코드와 같은 깃 저장소에 보관하는 것을 선호하는 아키텍트도 있지만, 규모가 큰 조직에서는 권장하지 않습니다.
이유는 두 가지입니다.
- ADR을 봐야 할 사람 중 깃 저장소에 접근하지 못하는 사람이 있을 수 있음
- 애플리케이션 범위를 벗어난 ADR(통합·엔터프라이즈·전사 결정)을 특정 애플리케이션 저장소에 두는 것은 부적절
권장 디렉터리 구조
architecture decisions/
├── application/
│ ├── common/ # 모든 앱 공통
│ ├── app1/ # 특정 앱
│ └── app2/
├── integration/ # 앱·시스템·서비스 간 통신
└── enterprise/ # 전사 적용
| 디렉터리 | 용도 |
|---|---|
| application/common | 모든 애플리케이션에 적용되는 공통 결정. “모든 프레임워크 관련 클래스는 @Framework 애너테이션을 포함해야 한다” 같은 것 |
| application/app1, app2 | 특정 애플리케이션 맥락의 결정 |
| integration | 시스템 간 통신 관련 결정 |
| enterprise | 전사적 결정. “시스템 데이터베이스에는 그 데이터베이스를 소유한 시스템만 접근할 수 있다” 같은 것 |
위키에 저장할 때도 같은 구조를 적용합니다. 각 디렉터리는 탐색 랜딩 페이지에 대응하고, 각 ADR은 그 안의 개별 페이지로 표현됩니다.
이 디렉터리·랜딩 페이지 이름은 권장 사항이자 예시일 뿐이며, 회사 상황에 맞게 정하되 팀 전체가 일관되게 사용하는 것이 중요합니다.
ADR의 다양한 활용
문서화로서의 ADR
소프트웨어 아키텍처를 문서화하는 일에는 합의된 표준이 아직 없습니다. C4 모델·ArchiMate 같은 시도들이 있지만 어느 것도 표준이 되지 못했습니다. 이 공백을 ADR이 메웁니다.
ADR이 아키텍처 문서화에 강력한 이유는 결정 섹션의 이유 와 결과 섹션의 트레이드오프 분석 때문입니다. 일반 다이어그램은 “어떻게”를 보여주지만 “왜”를 담지 못합니다. ADR은 정확히 그 빈자리를 채웁니다.
표준을 위한 ADR
표준을 좋아하는 개발자는 거의 없습니다. 종종 표준은 통제 수단으로 작용할 뿐 유용한 목적을 제공하지 못합니다. 표준을 ADR 형식으로 문서화하면 이런 나쁜 관행을 바꿀 수 있습니다.
- 맥락 섹션: 조직이 특정 표준을 채택하게 만든 상황 설명
- 결정 섹션: 표준이 무엇인지뿐 아니라 그 표준이 존재하는 이유
- 결과 섹션: 표준의 영향과 결과를 고찰
이 과정에서 정당화하지 못하는 표준이라면 애초에 강제할 만한 표준이 아닐 수 있다는 통찰이 따라옵니다. 개발자들이 왜 이 표준이 존재하는지 이해할수록 준수율이 올라갑니다.
기존 시스템을 위한 ADR
이미 잘 돌아가는 시스템에 ADR을 작성하는 것이 의미 있을지 의문을 제기하는 아키텍트가 많습니다. 답은 “있다”입니다.
ADR은 단순한 문서 이상이고, 어떤 결정이 왜 내려졌고 그것이 가장 적절한 결정이었는지를 아키텍트와 개발자가 이해하는 데 도움이 됩니다. 원래 결정을 내린 사람이 회사를 떠나서 답을 아는 사람이 아무도 없을 수도 있습니다.
이런 경우 여러 대안의 트레이드오프를 파악·분석해 기존 결정을 검증(또는 무효화)하는 것이 아키텍트의 몫입니다. 이런 종류의 ADR을 작성해 나가면 시스템에 대한 명분과 근거(그리고 핵심 지식)를 점차 이해하게 되며, 이는 비효율성과 잘못된 시스템 설계를 식별하는 데 도움이 됩니다.
생성형 AI와 LLM을 활용한 아키텍처적 결정
생성형 AI가 아키텍트의 결정을 도울 수 있는가?
대부분의 아키텍처 질문에 대한 답은 “상황에 따라 다르다”입니다. 소프트웨어 아키텍처 제1법칙 “소프트웨어 아키텍처의 모든 것은 트레이드오프이다”가 그 이유입니다. 결정은 적용되는 특정 맥락을 비롯한 수많은 요인에 따라 달라지므로 ‘모범관행’이 존재하지 않습니다.
대부분의 LLM은 확률에 기반해 결과를 도출합니다. 즉, 프롬프트 맥락에서 가장 확률이 높은 답변 혹은 모범관행을 출력할 뿐입니다. 하지만 아키텍처 결정에는 확률과 모범관행이 끼어들 자리가 없습니다.
| LLM이 잘하는 것 | LLM이 못 하는 것 |
|---|---|
| 주어진 결정에 관한 트레이드오프 개괄 — 아키텍트가 놓쳤을 수 있는 트레이드오프 식별 | 가장 적절한 아키텍처적 결정 도출 — 비즈니스 맥락 + 기술적 맥락 + 시장 출시 시간 같은 비즈니스 관심사를 유지보수성·테스트성 같은 아키텍처 특성으로 변환하는 작업 |
| 풍부한 지식 제공 | 가장 적절한 결정을 내리는 데 필요한 지혜 |
“생성형 AI 도구는 풍부한 지식을 갖추고 있지만, 가장 적절한 아키텍처적 결정을 내리는 데 필요한 지혜는 부족하다.”
LLM은 트레이드오프 발견기 로 쓰는 것이 가장 안전합니다. 결정 자체는 여전히 아키텍트의 몫입니다.
비교 / 트레이드오프
세 안티패턴의 관계
| 안티패턴 | 원인 | 해결 |
|---|---|---|
| 보신주의 | 결정 회피·미루기 | LRM·팀 협업 |
| 사랑의 블랙홀 | 결정의 정당화 부족 | 기술적 + 비즈니스적 명분 |
| 이메일 주도 | 결정 전달·기록 부재 | 단일 기록 시스템(ADR) + 링크만 이메일에 포함 |
세 안티패턴은 직선적으로 이어집니다. 보신주의를 극복했다고 해서 끝이 아니라, 사랑의 블랙홀과 이메일 주도까지 모두 해결해야 비로소 결정 프로세스가 완성됩니다.
ADR vs 기존 아키텍처 문서화
| 관점 | C4·ArchiMate | ADR |
|---|---|---|
| 표준화 | 합의된 표준 없음 | 사실상 업계 표준 |
| 강조점 | 구조·뷰·관계 | 결정의 이유와 트레이드오프 |
| 작성 비용 | 도구 학습·다이어그램 작성 | 짧은 텍스트 |
| 변경 추적 | 어려움 | 상태 변화로 자연스럽게 추적 |
| 보존 가치 | 시간 지나면 빠르게 노후화 | ”왜”는 노후화되지 않음 |
ADR이 “왜”를 담는 형식이라서 시간이 지나도 가치를 유지합니다. 다이어그램은 코드를 따라가야 하지만 결정의 명분은 그 자체로 역사적 자산입니다.
내 생각
”비즈니스 명분 없는 결정은 6개월 후 다시 도마에 오른다”
기술 부채 청산·리팩터링 제안이 매번 거절당하는 이유가 정확히 이것입니다. “코드 품질이 좋아진다”, “기술적으로 깔끔하다”는 명분만으로는 절대 통과되지 않습니다. 시장 출시 기간 단축·장애 감소로 인한 영업 손실 회피·신규 기능 개발 속도 향상 같은 비즈니스 언어로 번역해야 합니다.
ADR의 결정 섹션 작성을 강제하는 것은 결국 아키텍트에게 “비즈니스 명분이 없으면 그 결정은 애초에 내릴 가치가 없다”는 사실을 끊임없이 상기시키는 장치입니다.
깃 저장소 vs 별도 ADR 저장소
현실적으로는 작은 팀에서 깃 저장소 안의 docs/adr/ 디렉터리에 마크다운으로 두는 패턴이 가장 흔합니다. 책의 권장처럼 별도 위키로 분리하면 권한 관리 비용이 늘어나기 때문입니다.
다만 ADR이 enterprise 단계로 올라가는 순간, 즉 여러 시스템에 영향을 주는 결정이 등장하는 순간 깃 저장소 방식은 한계에 부딪힙니다. 이 시점에서 ADR을 별도 인프라로 옮기는 마이그레이션을 미리 준비해 두면 좋습니다.
LLM은 트레이드오프 발견기
실무에서 ChatGPT나 Claude에게 “이 두 옵션 중 어느 게 좋은가?”를 물으면 거의 항상 “둘 다 일장일단이 있습니다”라는 답으로 끝납니다. 이게 한계처럼 느껴지지만 사실은 LLM의 적절한 사용 모드입니다.
가장 효과적인 프롬프트는 결정을 묻는 게 아니라 “이 결정에서 내가 놓쳤을 수 있는 트레이드오프를 모두 나열해 달라”는 것입니다. 이 모드로 쓰면 LLM은 30개 트레이드오프를 평탄하게 나열해주고, 아키텍트는 자신의 맥락에서 가중치를 매겨 결정을 내립니다. 책의 결론과 정확히 일치합니다.
준수 섹션의 자동화가 ADR을 살아있게 만든다
ArchUnit·NetArchTest로 준수 섹션을 적합성 함수로 박제하면 ADR이 “한 번 쓰고 잊혀지는 문서”에서 “지속적으로 강제되는 거버넌스”로 변신합니다.
실무에서 이 단계까지 가는 팀은 드물지만, 한 번 도입하면 신규 입사자가 무심코 위반 코드를 PR에 넣을 때 CI에서 명시적인 ADR 위반 메시지가 뜨는 경험을 합니다. ADR 번호가 에러 메시지에 박혀 나오면 그 자체로 강력한 학습 기회가 됩니다.
더 알아볼 것
- ADR Tools(https://oreil.ly/6d8LN) — Nat Pryce의 ADR 관리 CLI
- ArchUnit·NetArchTest를 이용한 준수 섹션 자동화 패턴
- adr.github.io의 ADR 템플릿 카탈로그
- 마이클 나이가드의 ADR 원본 블로그 게시물
- 미샤 콥스의 ADR Tools 활용 예제(https://oreil.ly/0gBZK)
관련 개념
- Ch19 적절한 아키텍처 스타일의 선택 — ADR의 주요 산출물 사례
- Ch20 아키텍처 패턴 — 패턴 채택 결정도 ADR로 기록
- Ch06 아키텍처 특성의 측정과 거버넌스 — 적합성 함수와 준수 섹션의 연결
- Ch22 아키텍처 위험 분석 — 결정의 위험 평가 결과를 ADR에 반영
- Ch07 아키텍처 특성의 범위 — 아키텍처적 중요성 판정의 기준 도구
출처
- 마크 리처즈, 닐 포드, 라주 간디, 프라모드 사달게. 『소프트웨어 아키텍처 The Basics』. 한빛미디어, 2024. Chapter 21.