한 줄 정의

아키텍처 스타일은 컴포넌트 토폴로지, 통신 방식, 데이터 토폴로지 등 아키텍처의 구조적 특성을 정의하는 이름 붙여진 패턴의 집합입니다.

쉽게 말하면

건축에서 “고딕 양식”, “바로크 양식”처럼, 소프트웨어에도 “계층형”, “마이크로서비스” 같은 구조적 스타일이 있습니다.

스타일을 알면 “우리 시스템은 계층형 모놀리스입니다”라는 한 문장으로 토폴로지, 배포 방식, 통신 방식까지 공유할 수 있습니다.

왜 중요한가?

아키텍처 스타일을 모르면 시스템의 구조적 특성을 효율적으로 논의할 수 없습니다. 스타일은 아키텍트가 가장 먼저 내려야 하는 결정 중 하나이며, 이후의 모든 기술적 의사결정에 영향을 미칩니다.

특히 최상위 분할(top-level partitioning) 을 기술적으로 할지 도메인 중심으로 할지, 모놀리스로 갈지 분산으로 갈지에 따라 아키텍처의 성격이 완전히 달라집니다.

핵심 내용

스타일 vs 패턴

아키텍처 스타일아키텍처 패턴은 혼동하기 쉬운 개념입니다.

구분아키텍처 스타일아키텍처 패턴
초점아키텍처의 토폴로지, 통신, 배포 등 기본적인 특성들주어진 상황에 적합한 해법
예시마이크로서비스, 계층형, 이벤트 주도설계 패턴(design pattern)

스타일은 아키텍처의 구조적 형태를 설명하고, 패턴은 특정 문제에 대한 해법을 캡처합니다.

스타일을 형성하는 주요 특징은 다음과 같습니다.

컴포넌트 토폴로지

시스템에 어떤 컴포넌트들이 있고 그 컴포넌트들이 어떤 의존관계를 이루는지가 스타일에 따라 달라집니다. 계층형 아키텍처는 컴포넌트를 기술적 계층으로 구성하지만, 모듈형 모놀리스는 도메인 중심으로 구성합니다.

물리적 아키텍처

스타일이 물리적 아키텍처의 유형을 결정하기도 합니다. 모놀리스는 단일 배포본으로, 분산 아키텍처는 여러 배포 단위로 구성됩니다.

배포

시스템의 세분도(granularity)와 배포 빈도(deployment frequency)는 아키텍처 스타일과 관련이 깊습니다. 모놀리스는 단일 관계형 데이터베이스와 함께 단일 배포본으로 배포되지만, 마이크로서비스는 조각별로 배포되며 배포 주기도 훨씬 짧습니다.

통신 스타일

모놀리스에서는 컴포넌트들이 안에서 직접 메서드를 호출할 수 있지만, 분산 아키텍처에서는 REST나 메시지 큐 같은 네트워크 프로토콜을 통해 통신합니다.

데이터 토폴로지

시스템의 데이터 토폴로지도 아키텍처 스타일에 의해 결정될 때가 많습니다. 모놀리스는 모놀리식 데이터베이스를 갖는 경향이 있지만, 분산 아키텍처 스타일의 철학에 따라 종종 데이터를 분리합니다.

기본적인 아키텍처 패턴

소프트웨어 아키텍처의 역사를 보면 몇 가지 기본적인 패턴이 계속 나타납니다. 계층(layer)으로 관심사를 분리하는 개념은 소프트웨어 자체만큼이나 오래되었습니다.

진흙잡탕(Big Ball of Mud) 안티패턴

식별 가능한 아키텍처 구조가 없는 상태를 진흙잡탕이라고 부릅니다. 1997년 브라이언 푸트와 조지프 요더가 발표한 논문에서 정의된 안티패턴입니다.

진흙잡탕은 무계획적으로 구조되고, 무질서하게 뻗어나가며, 조잡하고, 덕테이프와 철사 워어맨 스파게티 코드 정글입니다.

구조의 부재는 진흙잡탕의 유일한 문제가 아닙니다. 모든 것이 다른 모든 것과 결합되어 있기 때문에 뭔가를 바꾸면 예측하기 어려운 부수효과(side effect)가 연쇄적으로 발생합니다.

아키텍트가 의도적으로 진흙잡탕을 만들려고 하는 경우는 거의 없지만, 코드 품질과 구조에 대한 거버넌스가 없으면 많은 프로젝트가 이 상태에 이르게 됩니다.

통일적(Unitary) 아키텍처

컴퓨팅의 초창기에는 컴퓨터(하드웨어)와 소프트웨어가 분리되지 않는 하나의 개체였습니다. 시간이 흐르면서 기능이 필요해짐에 따라 둘이 점차 분리되었습니다. 오늘날 임베디드 시스템이나 극도로 제약된 환경을 제외하면 통일적 아키텍처는 매우 드뭅니다.

클라이언트/서버

시스템의 기술적 기능성을 프론트엔드(앞단)와 백엔드(뒷단)로 분리하는 것이 가장 기초적인 아키텍처 스타일입니다. 이를 2층(two-tier) 아키텍처 또는 클라이언트/서버 아키텍처라고 합니다.

데스크톱 + 데이터베이스 서버

초기 PC용 아키텍처에서 Windows 같은 사용자 인터페이스로 된 데스크톱 애플리케이션을 리치 클라이언트(rich client)로 삼고 데이터 기능은 별도의 데이터베이스 서버로 분리하도록 권장하는 아키텍처가 있었습니다.

브라우저 + 웹 서버

현대적인 웹 개발이 등장하면서, 웹 브라우저를 웹 서버에 연결하는 방식으로 아키텍처를 분할하는 스타일이 일반화되었습니다. 데스크톱 + 데이터베이스 서버와 비슷하되, 브라우저라는 더 얇은(thin) 클라이언트를 사용하는 덕분에 방화벽 안팎으로 더 넓은 배포가 가능했습니다.

3층 아키텍처

1990년대 후반에는 더 추가된 계층을 가진 3층 아키텍처(three-tier architecture) 가 인기를 끌었습니다. 전형적인 3층 아키텍처에서 하나의 시스템은 엔터프라이즈급 데이터베이스 서버를 사용하는 데이터베이스 계층과 애플리케이션 서버가 관리하는 애플리케이션 계층, 그리고 HTML로 코딩된 프론트엔드(표현 계층)로 구성됩니다.1

3층 아키텍처는 분산 아키텍처의 구축을 용이하게 하기 위해 CORBA나 DCOM 같은 네트워크 수준 프로토콜과 함께 사용되었습니다.

오늘날 개발자들이 TCP/IP 같은 네트워크 프로토콜의 작동 방식을 걱정하지 않는 것처럼, 대부분의 아키텍트는 이런 수준의 ‘배관(plumbing)’ 작업을 걱정할 일이 없습니다.

3층 아키텍처, 언어 설계, 그리고 장기적 영향

자바 언어가 설계될 1990년대에는 3층 컴퓨팅이 큰 인기를 끌었고, 미래에 모든 시스템이 3층 아키텍처를 가질 것이라고 가정했습니다. 그래서 자바 설계자들은 직렬화(serialization) 라는 메커니즘을 언어의 핵심부에 축하기로 결정했습니다. 모든 자바 객체는 직렬화 지원이 필수인 인터페이스를 구현했고, 3층 아키텍처의 인기는 사그라들었지만 그 잔재는 오늘날까지 자바에 남아 있습니다.

설계상의 결정이 장기적으로 미치는 영향을 파악하는 것은 언제나 어려운 문제입니다.

아키텍처의 분할

소프트웨어 아키텍처의 제1법칙은 소프트웨어의 모든 것이 트레이드오프라는 것입니다. 아키텍트가 컴포넌트를 분할할 때도 이 법칙이 적용됩니다. 컴포넌트는 일반적인 격리 메커니즘(containment mechanism)을 나타내므로, 아키텍트는 원하는 임의의 방식으로 컴포넌트를 분할할 수 있습니다.

특히나 큰 영향을 미치는 컴포넌트 분할 방식이 하나 있는데, 바로 최상위 분할(top-level partitioning) 입니다.

기술적 분할 vs 도메인 분할

graph TB
    subgraph tech["기술적 분할 (계층형)"]
        P[표현 계층]
        B[비즈니스 규칙 계층]
        S[서비스 계층]
        D1[영속성 계층]
        DB1[(데이터베이스)]
        P --> B --> S --> D1 --> DB1
    end

    subgraph domain["도메인 분할 (모듈형)"]
        CC[CatalogCheckout]
        UI[UpdateInventory]
        SC[ShipToCustomer]
        RP[Reporting]
        AN[Analytics]
        UA[UpdateAccounts]
        DB2[(데이터베이스)]
        CC --> DB2
        UI --> DB2
        SC --> DB2
        RP --> DB2
        AN --> DB2
        UA --> DB2
    end

기술적 분할은 시스템의 컴포넌트를 표현, 비즈니스 규칙, 서비스, 영속성 같은 기술적 역량들로 분할합니다. MVC(Model-View-Controller) 분리와 비슷한 방식으로 계층들을 분할하는 형태로 나타납니다.

계층형 아키텍처의 조직화 원칙 중 하나는 기술적 관심사의 분리(separation of technical concerns) 입니다. 이 원칙을 잘 따르면 유용한 결합 분리 수준(levels of decoupling)이 만들어집니다. 하지만 대부분의 현실적인 소프트웨어 시스템에는 기술적 역량들을 가로지르는(횡단) 작업흐름이 필요합니다. 예를 들어 카탈로그를 체크아웃하는 비즈니스 작업흐름을 처리하는 코드는 모든 계층에 나타납니다.

도메인 분할은 에릭 에반스의 Domain-Driven Design에서 영감을 받았고, 도메인 주도 설계(DDD)에서 아키텍트는 서로 독립적이고 분리된 도메인이나 작업흐름을 식별합니다. 마이크로서비스 아키텍처는 이러한 철학을 기반으로 합니다.

기술적 분할의 장단점

장점:

  • 같은 기술적 역할을 하는 코드가 한 곳에 모여 있으므로, “표현 로직은 여기, 영속성 로직은 저기”처럼 코드의 위치를 직관적으로 파악할 수 있습니다.
  • 계층형 아키텍처 패턴(MVC 등)과 잘 맞아서 많은 개발자에게 친숙합니다.
  • 특정 기술 역량(예: 영속성 계층)을 한 곳에서 관리하므로, 기술별 전문 팀이 독립적으로 작업하기 좋습니다.

단점:

  • 하나의 비즈니스 기능(예: “주문하기”)을 구현하려면 표현·비즈니스 규칙·서비스·영속성 등 모든 계층을 건드려야 합니다. 비즈니스 변경이 잦을수록 수정 범위가 넓어집니다.
  • 모든 도메인이 같은 영속성 계층을 공유하는 경향이 있어 데이터 수준의 결합도가 높아집니다.
  • 하위 계층(예: 공통 유틸리티)을 변경하면 그 위의 모든 계층에 영향을 미칠 수 있습니다.
도메인 분할의 장단점

장점:

  • 비즈니스가 실제로 운영되는 방식에 더 가깝게 모델링됩니다. “주문”, “배송”, “결제”처럼 비즈니스 단위로 코드가 묶이므로, 비즈니스 요구사항 변경 시 해당 도메인 컴포넌트만 수정하면 됩니다.
  • 도메인을 중심으로 교차 기능 팀(cross-functional team)을 구축하기 쉽습니다. 한 팀이 프론트엔드부터 데이터베이스까지 하나의 도메인을 온전히 소유할 수 있습니다.
  • 각 도메인 컴포넌트가 독립적이므로, 나중에 분산 아키텍처(마이크로서비스 등)로 마이그레이션하기 쉽습니다.
  • 메시지 흐름이 비즈니스 흐름과 자연스럽게 일치합니다.

단점:

  • 여러 도메인에 걸쳐 공통으로 필요한 로직(예: 인증, 로깅, 공통 유틸리티)이 각 도메인 컴포넌트에 중복되거나 흩어질 수 있습니다. 공통 로직을 수정하려면 여러 컴포넌트를 찾아다녀야 합니다.

카타: 실리콘 샌드위치 — 분할

실리콘 샌드위치는 프랜차이즈 샌드위치 가게 시스템을 설계하는 예제 카타입니다. 이 카타를 통해 같은 시스템을 도메인 분할과 기술적 분할로 각각 설계했을 때 어떤 차이가 나는지 비교할 수 있습니다.

도메인 분할 설계

도메인 분할 방식에서는 비즈니스 작업흐름을 중심으로 최상위 컴포넌트를 구성합니다. 각 도메인 컴포넌트 안에는 프랜차이즈 전체에서 공통인 하위 컴포넌트(공통)와 매장별로 다르게 동작하는 하위 컴포넌트(매장별)가 함께 들어갑니다.

graph TB
    subgraph 구매
        구매_주문[주문] --> 구매_결제[결제]
    end
    subgraph 프로모션
        프로모션_공통[공통]
        프로모션_매장별[매장별]
    end
    subgraph 주문제조
        주문제조_상품[상품]
    end
    subgraph 배달
        배달_주소[주소]
    end
    subgraph 재고관리
        재고관리_공통[공통]
        재고관리_매장별[매장별]
    end
    subgraph 레시피
        레시피_공통[공통]
        레시피_매장별[매장별]
    end
    subgraph 위치
        위치_공통[공통]
        위치_매장별[매장별]
    end

    구매 --> 프로모션
    구매 --> 주문제조
    구매 --> 배달
    주문제조 --> 재고관리
    주문제조 --> 레시피
    배달 --> 위치

각 도메인 컴포넌트가 자신의 비즈니스 영역을 온전히 소유하므로, “레시피 관련 변경은 레시피 컴포넌트만 수정하면 된다”는 식으로 변경 범위가 명확합니다. 하지만 공통/매장별 로직이 여러 도메인에 흩어져 있어서, 예를 들어 모든 매장별 로직을 한꺼번에 수정하려면 여러 컴포넌트를 찾아다녀야 합니다.

기술적 분할 설계

기술적 분할에서는 공통 요소들과 매장별 요소들을 최상위 컴포넌트로 격리합니다. 매장별(Local)과 공통(Common)이 각각 최상위에 위치하고, 작업흐름을 처리하는 데 필요한 구매와 배달 컴포넌트는 별도로 남겨 둡니다.

graph TB
    subgraph 매장별
        direction LR
        L_레시피[레시피]
        L_재고[재고]
        L_프로모션[프로모션]
        L_위치[위치]
    end

    subgraph 구매
        구매_주문[주문]
        구매_결제[결제]
    end
    subgraph 배달
        배달_주소[주소]
    end

    subgraph 공통
        direction LR
        C_레시피[레시피]
        C_재고[재고]
        C_프로모션[프로모션]
        C_위치[위치]
    end

    구매 --> L_레시피
    구매 --> L_재고
    구매 --> L_프로모션
    구매 --> 배달
    구매 --> C_레시피
    구매 --> C_재고
    배달 --> L_위치
    배달 --> C_프로모션
    배달 --> C_위치

이 방식에서는 “매장별 코드는 매장별 아래에 전부 있다”는 식으로 기술적 역할별 위치가 명확하지만, 하나의 비즈니스 기능(예: 레시피 변경)을 수정하려면 매장별과 공통 양쪽을 모두 건드려야 합니다.

지난 몇 년간 모놀리스형과 분산형(마이크로서비스) 아키텍처 모두에서 업계가 도메인 분할 쪽으로 쏠리고 있습니다. 이것은 아키텍트가 가장 먼저 내려야 하는 결정 중 하나입니다. 오

모놀리스 대 분산 아키텍처

아키텍처 스타일은 두 가지 주요 유형으로 분류할 수 있습니다.

분류아키텍처 스타일
모놀리스계층형 아키텍처, 파이프라인 아키텍처, 마이크로커널 아키텍처
분산서비스 기반 아키텍처, 이벤트 주도 아키텍처, 공간 기반 아키텍처, 서비스 지향 아키텍처, 마이크로서비스 아키텍처

모놀리스는 하나의 배포 단위에 모든 코드가 포함된 아키텍처이고, 분산은 여러 배포 단위가 원격 접근 프로토콜로 연결된 아키텍처입니다.

분산 아키텍처 스타일은 성능, 확장성, 가용성 측면에서 모놀리스보다 훨씬 강력하지만, 중요한 트레이드오프들이 존재합니다. 1994년에 피터 도이치가 정리한 “분산 컴퓨팅에 관한 오해들(fallacies of distributed computing)” 이 이를 잘 보여줍니다.

오해 #1: 네트워크는 신뢰할 수 있다

네트워크는 신뢰할 수 없습니다. 네트워크의 신뢰성이 점차 높아지긴 했지만, 일반적으로 여전히 신뢰할 수 없는 수준입니다. 네트워크에 문제가 있으면 서비스 A는 서비스 B에 접근하지 못하고, 더 나쁜 상황으로는 서비스 A가 서비스 B에 데이터 처리를 요청했지만 도중에 네트워크에 문제가 생겨서 응답을 받지 못할 수도 있습니다.

이것이 서비스들에 타임아웃(시간만료)과 서킷 브레이커(circuit breaker)가 존재하는 이유이며, 시스템이 네트워크에 더 많이 의존할수록(마이크로서비스 아키텍처) 네트워크를 신뢰할 수 없게 될 가능성이 더 커집니다.

오해 #2: 지연시간은 0이다

로컬에서 메서드나 함수 호출로 다른 컴포넌트와 통신할 때 접근하는 시간(t_local)은 나노초나 마이크로초로 측정됩니다. 하지만 원격 접근 프로토콜(REST, 메시징, RPC 등)을 통해 이루어질 때는 접근 시간(t_remote)을 밀리초로 측정합니다. 원격 접근 시간은 로컬 접근 시간보다 항상 큽니다.

분산 아키텍처를 고려하는 아키텍트는 이 평균 지연시간을 알아야 합니다. 예를 들어, 요청당 평균 지연시간이 100ms라고 하고, 특정한 비즈니스 기능 하나를 수행하기 위해 10개의 서비스가 꼬리에 꼬리를 물고 호출한다면 총 지연시간은 1,000ms가 됩니다. 그런데 평균 지연시간만큼이나 중요한 것은 95~99번째 백분위수(percentile) 지연시간입니다. 시스템의 평균 지연시간이 60ms로 양호해도, 95번째 백분위수 지연시간이 400ms이면 문제가 있는 것입니다. 분산 아키텍처에서 성능을 저해하는 것은 보통 이런 ‘긴 꼬리(long tail)’ 지연시간입니다.

오해 #3: 대역폭은 무한하다

보통 모놀리스 아키텍처에서는 대역폭(bandwidth)이 문제가 되지 않지만, 분산 아키텍처(마이크로서비스 등)에서는 시스템이 더 작은 배포 단위(서비스)로 분해되기 마련이며, 배포 단위들 사이의 통신이 상당한 대역폭을 사용합니다.

이런 형태의 결합을 스탬프 결합(stamp coupling) 이라고 부릅니다. 예를 들어, 서비스 A가 서비스 B를 호출할 때마다 서비스 B는 45개의 속성(총 500KB)을 서비스 A에 돌려주지만, 서비스 A에 필요한 것은 이름(200바이트)뿐입니다. 이것이 초당 약 2,000번 발생한다면, 요청당 500KB이므로 두 서비스는 매초 1GBps의 대역폭을 소비하게 됩니다.

스탬프 결합을 해소하는 몇 가지 방법이 있습니다:

  • 비공개(private) REST API 종단점(endpoint)을 만듭니다.
  • 계약에 필드 선택자(field selector)를 사용합니다.
  • GraphQL을 이용해서 계약들을 분리합니다.
  • 소비자 주도 계약(consumer-driven contract)을 가치 주도 계약(value-driven contract)과 함께 사용합니다.
  • 내부 메시징 종단점을 사용합니다.

어떤 기술을 사용하든, 가장 좋은 방법은 서비스나 시스템이 꼭 필요한 데이터만 전송하게 하는 것입니다.

오해 #4: 네트워크는 안전하다

대부분의 아키텍트와 개발자는 VPN, 신뢰 네트워크(trusted network), 방화벽을 사용하는 데 익숙하다 보니 네트워크가 안전하다고 착각하기 쉽지만, 네트워크는 안전하지 않습니다. 분산 배포 단위의 모든 종단점은 알 수 없거나 악의적인 요청으로부터 보호되어야 합니다.

모놀리스에서 분산 아키텍처로 이동할 때는 위험과 공격의 표면적이 크게 증가해서 보안이 훨씬 더 어려워집니다. 모든 종단점을 보호하는 것은 동기식 고도 분산 아키텍처 스타일에서 성능을 느리게 만드는 또 다른 요인입니다.

오해 #5: 토폴로지는 절대 변하지 않는다

이 오해에서 말하는 토폴로지는 모든 라우터, 허브, 스위치, 방화벽, 네트워크, 어플라이언스를 포함한 전체적인 네트워크 토폴로지를 의미합니다. 흔히 아키텍트들은 토폴로지가 고정되어 있고 절대 변하지 않는다고 가정하지만, 네트워크 토폴로지는 항상 변합니다.

예를 들어, 월요일 아침에 출근했더니 서비스가 계속 타임아웃되어 모든 사람이 미친 듯이 뛰어다니고 있다고 가정합니다. 팀들과 함께 왜 이런 일이 발생하는지 필사적으로 알아내려 합니다. 주말 동안 새로운 서비스는 배포되지 않았습니다. 뭐가 문제일까? 몇 시간 후, 새벽 2시에 있었던 ‘사소한’ 네트워크 업그레이드가 시스템의 지연시간과 관련된 모든 가정(assumption)을 무효화했고, 그래서 타임아웃과 서킷 브레이커가 발동되었음을 알게 됩니다.

이런 뜻밖의 사고를 피하려면 아키텍트는 무엇이 언제 변하는지에 대해 운영 팀 및 네트워크 관리자와 지속적으로 소통해야 합니다.

오해 #6: 관리자는 한 명뿐이다

일반적인 대기업에는 수십 명의 네트워크 관리자가 있습니다. 이 오해는 분산 아키텍처가 얼마나 복잡한지, 그리고 모든 것이 제대로 작동하게 하는 데 필요한 조정(coordination) 작업이 얼마나 많은지와 관련이 있습니다. 배포 단위가 하나뿐인 모놀리스 애플리케이션에서는 그런 수준의 의사소통과 협력이 필요하지 않습니다.

오해 #7: 전송 비용은 0이다

이 오해를 오해 #2(지연시간이 0이다)와 혼동하는 아키텍트가 많습니다. 여기서 전송 비용(transport cost) 은 지연시간이 아니라, ‘간단한 REST 호출’에 필요한 실제 금전적 비용을 말합니다. 분산 아키텍처는 모놀리스 아키텍처보다 비용이 훨씬 많이 드는데, 주된 이유는 하드웨어, 서버, 게이트웨이, 방화벽, 새로운 서브넷, 프록시 등에 대한 요구사항이 증가하기 때문입니다.

오해 #8: 네트워크는 동질적이다

대부분의 아키텍트와 개발자는 네트워크가 동질적(homogeneous)이라고 가정합니다. 즉, 단일 벤더사(vendor)의 네트워크 하드웨어로만 구성되어 있다고 생각합니다. 대부분의 경우 회사의 인프라에는 여러 벤더사의 제품이 섞여 있고, 서로 다른 하드웨어 제조사의 장비들이 모두 잘 어울려서 작동하지는 않습니다.

기타 오해들

오해 #9. 버전 관리는 쉬운 일이다

두 서비스가 통신할 때는 계약(contract) 을 통해서 정보를 주고받습니다. 시간이 흘러 서비스의 내부 구현이 진화하면서 필드들도 바뀝니다. 이에 따른 문제를 해결하는 한 가지 방법은 계약에 버전 관리(versioning) 를 적용하는 것입니다.

버전 관리에서는 다음과 같은 트레이드오프가 제기됩니다:

  • 버전을 개별 서비스 수준에서 적용해야 할까, 아니면 전체 시스템 수준에서 적용해야 할까?
  • 아키텍처에서 버전 관리를 지원해야 하는 부분이 몇 퍼센트나 되어야 할까?
  • 주어진 시점에 몇 개의 버전을 지원해야 할까?
  • 오래된 버전들의 사용 중단을 시스템 수준에서 적용할 것인가, 아니면 서비스별로 적용할 것인가?
오해 #10. 보상 갱신은 항상 작동한다

보상 갱신(compensating update) 은 일부 메커니즘(예: Orchestrator 서비스)을 통해 연관된 여러 서비스가 모두 함께 갱신되도록 보장하는 아키텍처 패턴입니다. 만약 일부 갱신이 실패할 경우, 오케스트레이터는 전체 갱신을 이전 상태로 되돌립니다.

대부분의 아키텍트가 당연히 잘 되리라고 가정하는 패턴이지만, 항상 잘 되는 것은 아닙니다. 주된 갱신과 보상 갱신(또는 그것의 일부)이 둘 다 실패했을 때 그것을 복구하는 방법도 고려해야 합니다.

오해 #11. 관측성은 생략할 수 있다

분산 아키텍처에서 관측성(observability) 은 각 서비스가 다른 서비스들 및 생태계와 어떻게 상호작용하는지를 모니터나 로그 등을 통해서 관찰할 수 있는 능력을 뜻합니다. 로깅은 모놀리스 아키텍처에서는 그저 ‘유용하다’ 정도이지만, 분산 아키텍처에서는 치명적으로 중요합니다(critical). 분산 아키텍처의 통신 실패 모드(communication failure mode) 중에는 포괄적인 상호작용 로그 없이는 디버깅하기 어려운 것이 많기 때문입니다.

팀 토폴로지와 아키텍처

아키텍트와 팀들은 아키텍처와 팀 토폴로지의 교점을 많이 연구했습니다. 매튜 스켈턴과 마누엘 파이스의 Team Topologies 에서는 소프트웨어 아키텍처와 교차하는 몇 가지 팀 유형을 정의합니다.

스트림 정렬 팀

스트림 정렬 팀(stream-aligned team) 은 특정 비즈니스 도메인이나 역량으로 범위가 정해진 작업의 흐름입니다. 하나의 제품이나 서비스, 또는 특정 기능 집합과 같은 단일 작업 부문에 좁게 집중합니다.

활성화 팀

활성화 팀(enabling team) 은 긴급하지 않은 필요한 연구, 학습, 기타 작업을 위한 장소를 제공함으로써 일부 역량의 부족한 부분을 메웁니다. 전문 도메인의 지식과 자원을 공급하여 스트림 정렬 팀을 지원합니다.

난해한 하위시스템 팀

난해한 하위시스템 팀(complicated-subsystem team) 은 난해한 하위시스템이나 도메인을 완전히 이해하는 팀원들로 구성됩니다. 이들의 목표는 다른 팀의 인지적 부하를 줄이는 것입니다.

플랫폼 팀

플랫폼 팀은 솔루션을 위한 내부 서비스의 구성요소를 제공합니다. 매력적인 내부 제품으로서 제공되는 셀프서비스 API, 도구, 서비스, 지식, 자원의 기초(foundation)이며, 플랫폼을 활용함으로써 자율적인 전달 팀(delivery team)들은 발견 조정 작업을 줄이고 더 빠른 속도로 제품 기능을 전달할 수 있습니다.

정리

분류장점단점
모놀리스단순한 배포, 낮은 네트워크 오버헤드, 단일 데이터베이스로 트랜잭션 관리 용이확장성 제한, 배포 빈도 낮음, 장애 전파 범위 넓음
분산높은 확장성·성능·가용성, 독립 배포 가능, 팀 자율성네트워크 오해들(8+3가지), 높은 운영 비용, 디버깅 복잡성
분할 방식적합한 상황부적합한 상황
기술적 분할기술 스택이 명확하고 역량별 전문 팀이 있는 조직도메인 변경이 잦고 교차 기능 팀이 필요한 조직
도메인 분할비즈니스 도메인 중심 개발, 마이크로서비스 지향소규모 팀, 단순한 CRUD 애플리케이션

내 생각

  • 분산 컴퓨팅의 8가지 오해는 교과서적으로 보이지만, 실무에서 하나씩 직접 겪어봐야 체감이 됩니다. 특히 오해 #2(지연시간은 0이다) 는 마이크로서비스 전환 시 가장 먼저 부딪히는 벽입니다. 95번째 백분위수 지연시간이 서비스 체이닝에서 누적되면 전체 응답 시간이 SLA를 넘기기 쉽습니다.
  • 최상위 분할 결정은 프로젝트 초기에 내려야 하는데, 한 번 정해지면 바꾸기가 매우 어렵습니다. 초기 서비스가 3~5개 이하인 스타트업이라면 기술적 분할(계층형)로 시작해서 도메인이 명확해질 때 도메인 분할로 전환하는 것이 현실적입니다.
  • 오해 #11(관측성)은 분산 아키텍처에서 가장 과소평가되는 항목입니다. 분산 추적(distributed tracing), 구조화된 로깅, 메트릭 수집을 아키텍처 설계 단계에서 먼저 고려해야 합니다.

관련 개념

출처

  • Fundamentals of Software Architecture (Mark Richards, Neal Ford) — Chapter 9