19장, 아키텍처 결정

2022.08.16

아키텍트에게 기대하는 핵심 가치 중 하나는 아키텍처 결정을 내리는 것이다. 아키텍처 결정은 애플리케이션이나 시스템의 구조에 관한 것이 대부분이지만 기술 결정 역시 (그것이 아키텍처 특성에 영향을 미칠 경우) 포함될 수 있다. 아키텍처 결정을 하려면 충분한 정보를 수집하고 결정을 정당화 문서화한 다음 이해관계자들과 효과적으로 소통해야 한다.

19.1 아키텍처 결정 안티패턴

아키텍처를 결정하는 것도 기술이다. 따라서 아키텍트가 결정을 내릴 때 아키텍처 안티패턴에 빠지는 일도 드물지 않다. 안티패턴이란 처음에는 좋은 생각처럼 보이지만 이내 곧 곤경에 빠뜨리는 애물단지라고 정의한다. 부정적인 결과를 내는 반복 가능한 프로세스라고 정의하는 이들도 있다.

19.1.1 '네 패를 먼저 보여주지마' 안티패턴

아키텍트가 잘못된 선택을 하는 것을 두려워한 나머지 아키텍처 결정을 회피하거나 미루는 현상을 말한다.

이 안티패턴은 두 가지 방법으로 극복할 수 있다. 첫째, 어떤 중요한 아키텍처 결정을 내리 기 전, 마지막으로 책임질 수 있는 순간까지 기다리는 것이다. 아키텍트가 자신의 결정을 정당화하고 검증하기 위해 충분한 정보를 수집할 때까지 기다리지만, 개발팀을 마냥 붙잡아 두거나 분석 마비 안티패턴에 빠질 정도로 오래 기다리지는 않음을 의미한다. 둘째, 개발팀과 지속적으로 협력하면서 아키텍트가 결정한 내용을 원래 의도한 대로 추진한다. 세부적인 기술에 관한 모든 이슈를 아키텍트 혼자 전부 다 알 수는 없기 때문에 개 발팀의 협력은 절대적으로 필요하다. 그래야 나중에 문제가 생겨도 아키텍트가 아키텍처 결 정을 변경하면서 재빠르게 대응할 수 있다.

19.1.2 '무한반복 회의' 안티패턴

'네 패를 먼저 보여주지마' 안티패턴을 극복하면 이어서 '무한반복 회의'안티패턴으로 이어진다. 사람들이 어떤 결정을 왜 했는지 모르고 주구장창 회의만 계속 하는 것이다.

'무한반복 회의'안티패턴이 발생하는 이유는 아키텍트가 자신이 내린 결정을 정당화하는 데 실패했기 때문이다. 아키텍처 결정을 정당화하려면 그 결정을 내리게 된 기술적, 비즈니스적 근거를 제시하는 것이 중요하다. 예를 들어, 모놀리식 애플리케이션을 개별 서비스로 분리하여 애플리케이션 각 파트가 가상 머신 리소스 사용량을 줄이고 별도 관리/배포할 수 있도록 결정했다고 하자. 기술적인 명분은 충분한 듯하지만, 비즈니스적으로는 어떻게 정당화할 수 있을까? 다시 말해, 이렇게 아키텍처를 리팩터링하는 비용을 경영진이 지불해야 하는 이유를 명쾌하게 설명할 수 있나? 만약 새로운 비즈니스 기능을 더 빨리 제공해서 시장 출시 시기를 앞당길 수 있다면 그들도 충분히 납득할 것이다. 신기능의 개발/출시 관련 비용을 절감할 수 있다면 적극적으로 어필해볼 만하다.

어떤 아키텍처 결정이건 그것을 정당화할 때에는 비즈니스 가치를 제시하는 것이 중요하다다. 그렇게 해야 그 아키텍처 결정을 정말 다른 무엇보다 우선해야 하는지 한 번 더 돌아볼 수 있다.

가장 일반적인 비즈니스 정당화로는 비용, 출시 시기, 유저 만족도, 전략적 포지셔닝 등이 있다. 이 네 가지 관점에서 비즈니스적으로 정당화할 때에는 무엇이 비즈니스 이해관계자에게 중요한지 숙고해봐야 한다. 이를테면, 비즈니스 이해관계자가 비용보다 시장 출시 시기에 더 관심이 있는데도 단순히 비용 절감만 내세우면서 결정을 정당화하려는 건 바람직하지 않다.

19.1.3 '이메일 기반 아키텍처' 안티패턴

아키텍트가 아키텍처 결정을 하고 그 결정을 온전히 정당화한 다음은 '이메일 기반 아키텍처 안티패턴이 등장할 차례이다. 사람들이 아키텍처 결정을 놓치거나 잊어버리고 심지어는 그렇게 결정됐다는 사실조차 알지 못해 아키텍처 결정을 구현하지 못하는 상태이다. 즉, 아키텍처 결정을 효과적으로 전달하는 문제와 관련된 안티패턴이다. 이메일은 훌륭한 소통 수단이지만 문서 저장 체제로는 정말 형편없다.

이 안티패턴을 방지하고 아키텍처 결정을 효과적으로 전달하려면 어떻게 해야 할까? 첫째, 이메일 본문에 아키텍처 결정을 포함시키지 않는다. 이메일 본문에 아키텍처 결정을 기재하면 그 결정에 관한 여러 경로의 기록 체제가 파생되고 (정당화 사유를 비롯한 중요한 세부 사항들이 이메일에서 누락되기 쉬운 까닭에 고질적인 '무한반복 회의' 패턴이 재발한다.

그림 아키텍처 결정이 변경되거나 다른 결정으로 대체될 경우, 어떤 식으로 사람들에게 통보하는 게 좋을까? 첫째, 이메일 본문에는 아키텍처 결정의 본질과 매락 정도만 언급하고 세부 정보는 단일 기록 시스템에 보관해서 (위키 페이지 링크든, 파일 시스템의 문서 경로든) 그 링크만 제공하면 된다. 둘째, 아키텍처 결정에 정말 관심있는 사람들에게만 통지한다. 일례로, 이메일 본문에 다음 과 같이 쓰면 효과적이다.

"안녕하세요. 팀장님, 제가 팀장님 부서에 직접적으로 영향을 미치는 서비스 간 통신에 관한 중 요한 결정을 내렸으니 아래 링크를 클릭하여 확인하시기 바랍니다."

또 아키텍처 결정에 관한 세부 내용을 확인 가능한 링크를 제공하면 모든 정보를 일원화하여 관리할 수 있는 체계가 완성된다.

19.2 아키텍처적으로 중요한

아키텍처 결정에 기술적인 내용이 포함되면 그것은 아키텍처 결정이 아니라, 기술 결정이라고 단정짓는 아키텍트들이 많지만 반드시 그런 것은 아니다. 아키텍트가 어떤 기술을 사용하기 로 결정을 했고 그 기술을 어떤 아키텍처 특성 (예: 성능, 확장성)을 직접 지원하기 위해 선택 한 것이라면 이는 아키텍처 결정이 맞다.

저명한 소프트웨어 아키텍트이자 「Release It 릴리스 잇(위키북스, 2007)의 저자인 마이클 나이가드(Michael Nygand)는 아키텍트가 어떤 아키텍처 결정을 담당하는지 (즉, 아키텍처 결정이란 대관절 무엇인지) '아키텍처적으로 중요한(achitecturally significant)'이라는 용어를 만들어 풀이하고자 했다.

구조(structure)는 사용 중인 아키텍처의 패턴이나 스타일에 영향을 미치는 결정들이다. 일례로, 여러 마이크로서비스 간에 데이터를 공유하기로 한 결정은 마이크로서비스의 경계 콘텍스트는 물론 애플리케이션 구조에도 영향을 미친다.

비기능 특성(nonfunctional characteristic)은 개발 또는 유지보수 중인 애플리케이션이나 시스템에 중요한 아키텍처 특성('~성)들이다. 만약 어떤 기술을 선택하느냐에 따라 성능이 달라지고 성능이 애플리케이션의 중요한 팩터일 경우, 이러한 기술 선택이 곧 아키텍처 결정이 된다.

의존성(dependency)은 전체 확장성, 모듈성. 민첩성, 시험성, 안정성 등에 영향을 미치는 시스템 내부의 컴포넌트와 (또는) 서비스 간의 커플링 지점을 가리킨다.

인터페이스(interface)는 게이트웨이, 통합 허브, 서비스 버스, API 프록시를 통해 서비스와 컴포넌 트에(를) 액세스하고 조정하는 수단을 말한다. 계약 버저닝. 버전 구식화 전략 등 계 약에 정의된 내용이 곧 인터페이스이다. 인터페이스는 시스템을 사용하는 다른 부분에도 영 향을 미치므로 아키텍처적으로 매우 중요하다.

구현 기술(construction technique)은 원래 그 자체는 기술적인 것이지만, 아키텍처의 많은 부분에 영향 을 미치는 플랫폼, 프레임워크, 도구, 프로세스에 관한 결정이다.

19.3 아키텍처 결정 레코드

아키텍처 결정을 가장 효과적으로 문서화하는 방법은 바로 아키텍처 결정 레코드(Architecture Decision Record, ADR)이다. ADR은 마이클 나이가드의 블로그 게시글에서 처음 소개됐고 이후 쏘우트웍스 기술 레이더에서 채틱됨(adopt)으로 표시됐다. ADR은 아키텍처 결정이 기술된 짧은 텍스트 파일로, 일반 텍스트로 작성할 수도 있지만 대개 아스키독(AsciiDoc)이나 마크다운(Markdown) 같은 텍스트 문서 포맷 또는 위키 페이지 템플릿으로 작성한다.

19.3.1 기본 구조

ADR의 기본 구조는 제목(Title), 상태(Status), 콘텍스트(Context), 결정(Decision), 결과(Consequences), 이렇게 주요 5개 섹션으로 구성된다. 여기에 컴플라이언스(Compliance)와 노트(Notes)라는 추가 섹션을 덧붙인다.

ADR 포맷


제목

아키텍처 결정을 간략히 기재

상태

제안됨, 수락됨, 대체됨

콘텍스트

왜 이렇게 결정할 수밖에 없었나?

결정

결정, 그리고 그렇게 결정한 합당한 사유 결과 이 결정이 어떤 영향을 끼치는가?

컴플라이언스

이 결정의 컴플라이언스를 어떻게 보장할 것인가?

노트

이 결정에 관한 메타데이터(결정한 사람 등)

제목

ADR 제목은 일련 번호와 함께 아키텍처 결정을 짤막한 문구로 표현한다. 예를 들어, 주문 서비스와 결제 서비스가 서로 비동기 메시징을 사용하기로 결정했다면 '42. 주문 서비스와 결제 서비스 간의 비동기 메시징 사용' 정도의 제목을 쓴다. 아키텍처 결정의 성격과 콘텍스트의 모호함을 해소할 수 있을 정도로, 짧고 간결하게 기술한다.

상태

ADR 상태는 제안됨(Proposed), 수락됨(Accepted), 대체됨(superseded)으로 표시한다. '제안됨'은 해당 결정이 상위 레벨의 의사 결정권자 또는 아키텍처 거버넌스 협의체 (예: 아키텍처 검토 위원회) 의 승인을 득해야 하는 상태이다. '수락됨'은 결정이 승인되어 구현할 준비가 된 상태이다. '대체됨'은 결정이 번복되어 다른 ADR에 의해 대체된 상태로, 이건 ADR 상태는 수락된 상태여야 한다. 즉, 제안된 상태의 ADR은 다른 ADR로 대체되는 일 없이 수락됨 상태가 될 때까지 계속 수정된다.

대체된 상태는 어떤 결정이 내려졌고, 당시 왜 그런 결정을 했는지, 새로운 결정은 무엇이고 어쩌다 변경을 하게 됐는지 등에 관한 이력을 보관하는 강력한 수단이다. 일반적으로 어떤 ADR이 대체되면 그 ADR을 대체한 결정이 병기되며, 반대로 다른 ADR을 대체한 결정은 자신이 대체한 ADR이 병기된다.

  • ADR 42. 주문 서비스와 결제 서비스 간의 비동기 메시징 사용
    • 상태: 68로 대체됩
  • ADR 68.주문 서비스와 결제 서비스 간의 REST 사용
    • 상태: 수락됨. 42를 대체함

이렇게 ADR 42와 ADR 68를 서로 연관 지어 이력을 남기면 나중에 ADR 68에 대해 "메시징 을 사용하는 게 어떨까요?" 같은 불필요한 질문이 나올 일은 없을 것이다.

ADR 상태 섹션은 아키텍트 본인이 아키텍처 결정을 승인할 수 있는 기준, 상급 아키텍트의 승인이나 아키텍처 검토 위원회, 또는 다른 아키텍처 관리 협의체의 승인을 받고 진행해야 하는지 등의 문제를 두고 자신의 상사나 수석 아키텍트와 대화를 하도록 만들기 때문에 중요한 측면도 있다.

콘텍스트

ADR 콘텍스트 context 섹션은 불가항력적인 요소를 특정한다. 다시 말해, '어떤 사정 때문에 그렇게 결정할 수밖에 없었나?" 입니다. 아키텍트는 이 섹션에서 특수한 상황이나 문제점을 이야기하고 다른 대안에 대해 상술한다. 각 대안을 상세히 분석한 문서가 필요할 경우, 콘텍스트 섹션 대신 ADR에 대안(Alternatives) 섹션을 추가한다.

콘텍스트 섹션은 아키텍처를 문서화하는 수단이기도 하다. 아키텍트는 콘텍스트를 기술함으로써 곧 아키텍처를 기술하는 것이다. 이는 분명하고 간결하게 특정 아키텍처 영역을 문서화하는 효과적인 방법이다. 앞 절의 예로 돌아가 콘텍스트를 읽어보면 이와 같다. 현재 주문의 총 결제 금액을 주문 서비스가 처리하려면 반드시 결제 서비스에 정보를 전달해야 하는데, 이는 REST 또는 비동기 메시징을 통해 수행할 수 있다' 이 간결한 한 문장에 시나리오는 물론 대안까지 들어있다.

결정

ADR 결정 섹션에는 아키텍처 결정과 그렇게 결정하게 된 사유를 전부 밝힌다. 마이클 나이가드는 수동적인 어조 대신, 매우 긍정적이고 당당한 어조로 아키텍처 결정을 설명하는 훌륭한 방법을 강조한다. 예를 들어, 서비스 간에 비동기 메시징을 사용하기로 결정했다면 서비스 간의 비동기 메시징이 최선의 선택이라고 생각합니다'보다는 '서비스 간에는 비동기 메시징을 사용할 것입니다'라고 기술해야 그 결정을 설명하는 문장으로서 설득력이 있다. 전자는 아키텍트의 의견만 기술된 문장으로, 어떤 아키텍처 결정을 했는지. 심지어 정말 그렇게 결정했는지 확실하지 않다.

결정 섹션의 가장 큰 강점은 아키텍트가 방법(how)보다 이유(why)에 더 무게를 실을 수 있다는 것이다. 사실 왜 그런 결정을 내렸는지 이해하는 것이 그것이 어떻게 작동되는지 이해하는 것보다 훨씬 더 중요하다.

결과

ADR 결과 역시 아주 강력한 섹션이다. 이 섹션에는 아키텍처 결정의 전체적인 영 향도를 기술한다. 아키텍트가 어떤 결정을 하더라도 좋은 영향과 나쁜 영향은 공존하기 마련이다. 아키텍처 결정이 어떤 영향을 미치는지 구체적으로 기술함으로써 아키텍트는 결정의 장점보다 그 영향이 더 중요한지 되돌아보게 된다.

이 섹션은 아키텍처 결정에 관한 트레이드오프는 물론, 분석 결과도 문서활할 수 있으므로 유용하다.

컴플라이언스

ADR의 컴플라이언스 섹션은 표준 섹션은 아니지만 우리는 반드시 추가하라고 권장한다. 이 섹션은 컴플라이언스 관점에서 아키텍트가 아키텍처 결정을 어떻게 측정/관리하는 게 좋을지 생각하게 만든다. 아키텍트는 본인의 결정에 대한 컴플라이언스 체크를 수동으로 할지, 아니면 피트니스 함수로 자동화할지 결정해야 한다. 피트니스 함수로 자동화할 수 있으면 피트니스 함수를 작성하는 방법, 그리고 컴플라이언스 측면에서 이 아키텍처 결정을 판단하기 위해 코드베이스에 다른 변경은 필요 없는지 등의 내용을 이 섹션에 기재한다.

노트

노트 섹션 역시 표준 섹션은 아니지만 가급적 추가하는 게 좋다. 이 섹션에는 다음과 같이 ADR에 관한 다양한 메타데이터가 포함된다.

  • 원저자
  • 승인일
  • 승인자
  • 대체일
  • 최종 수정일
  • 수정자
  • 최종 수정 내역

ADR을 (것 같은) 버전 관리 시스템에 저장할 때에도 저장소에서 지원되지 않는 부가적인 메타 정보가 있으면 유리하므로 ADR을 어디에, 어떻게 저장하더라도 이 섹션은 추가하는 것이 좋다.

19.3.2 ADR 저장

이렇게 작성한 ADR은 어딘가에 저장을 해야 한다. 저장 위치와 상관없이 각 아키텍처 결정은 자체 파일이나 위키 페이지도 갖고 있어야 한다. 일부 아키텍트들은 ADR을 소스 코드와 함께 깃 리포지터리에 보관하는 것을 선호한다. 깃 리포지터리에 ADR을 보관하면 버전 관리 및 추적은 간편하지만, 규모가 큰 조직에서는 몇 가지 주의할 점이 있다. 첫째, 아키텍처 결정을 확인해야 하는데 어떤 이들은 깃 리포지터리에 액세스할 수 없는 경우가 있다. 둘째, 애플리케이션 깃 리포지터리를 벗어난 콘텍스트(예: 통합 아키텍처 결정, 엔터프라이즈 아키텍처 결정, 모든 애플리케이션에 공통적인 결정)가 있는 ADR을 것에 저장하는 것은 적절하지 않다. 그러므로 ADR은 위키 (또는 위키 템플릿) 또는 다른 문서 렌더링 소프트웨어 에서 쉽게 접근 가능한 공유 파일 서버의 공유 디렉터리에 저장하는 것이 좋다.

19.3.3 ADR로 문서화

소프트웨어 아키텍처의 문서화는 언제나 어려운 주제이다. 일부 아키텍처 도식화 표준(예: 소프트웨어 아키텍트 사이먼 브라운의 CA 모델, 오픈 그룹의 아키메이트 ArchiMate 표준)이 있긴 하지만, 아직 이렇다 할 소프트웨어 아키텍처 문서화 표준은 없다. 어쩌면 그래서 더 더욱 ADR이 필요한 건지도 모르겠다.

ADR은 소프트웨어 아키텍처를 효과적으로 문서화하는 수단으로 활용할 수 있다. ADR 콘텍스트 섹션은 아키텍처 결정이 필요한 시스템의 특정 영역을 기술하는, 더 없이 훌륭한 장소인 데다 어떤 대안들이 있는지 기술하기에 적절한 곳이다. 하지만 무엇보다 중요한 섹션은, 아키텍처 결정을 내린 사유가 기술된 결정 섹션이다. 이 섹션 하나만 봐도 ADR은 현존 하는 최고의 아키텍처 문서화 포맷이다. 확장성을 희생하고 성능을 선택한 트레이드오프 분석처럼 어떤 결정을 내리게 된 부가적인 사정을 결과 섹션에 기술함으로써 아키텍처 문서화의 마지막 퍼즐 조각이 맞춰지는 것이다.

19.3.4 ADR로 표준화

이 세상에 표준을 좋아하는 사람이 있을까요? 일반적으로 표준은 그것이 유용해서라기보다 사람들이 일하는 방식을 통제하는 용도로 더 많이 사용되는 것 같다. 그러나 ADR을 표준화하면 이런 나쁜 관행이 바뀔 수도 있다. 예를 들어, ADR 콘텍스트 섹션은 어떤 표준을 강제 적용할 수밖에 없는 상황을 설명하고, ADR 결정 섹션은 어떤 표준이 있는지, 그리고 (더 중요한 것이지만) 그런 표준이 왜 존재해야 하는지 표현한다. 이것은 어떤 표준을 다른 무 엇보다 우선시해야 하는 논리를 효과적으로 검증하는 수단이 된다. 아키텍트 본인이 정당화 할 수 없는 표준을 정해 적용하는 것은 타당하지 않다. 표준이 필요한 이유를 개발자가 더 잘 납득할 수 있게 해야 그들이 표준을 따를(그래서 반기를 들지 않을 가능성이 높아진다.