Docs Architecture

마이크로서비스 아키텍처를 정의하는 3단계 핵심 프로세스

마이크로서비스 아키텍처를 정의하는 3단계 핵심 프로세스

마이크로서비스 아키텍처(MSA)를 설계하는 것은 단순한 기술적 결정을 넘어 비즈니스 요구사항을 서비스 단위로 해체하고 재구성하는 복합적인 과정입니다. 성공적인 MSA 전환을 위한 체계적인 3단계 프로세스를 정리해 봅니다.


1단계: 시스템 작업(System Operations) 식별

아키텍처 정의의 출발점은 애플리케이션이 처리해야 할 핵심 요청을 도출하는 것입니다. 이 단계에서는 요구사항을 바탕으로 도메인 모델과 시스템 작업을 지속적으로 보완하는 것이 중요합니다. 시스템 작업을 정의하다 보면 모델에서 놓친 개념을 발견해 보완하기도 하고, 반대로 모델의 구조에 맞춰 작업 내용을 수정하기도 합니다. 이처럼 모델과 작업을 서로 보완하며 비즈니스 요구사항을 아키텍처 시나리오로 구체화합니다. 이 과정은 아래 이미지와 같이 요구사항 분석을 통해 도메인 모델을 도출하고, 이를 바탕으로 작업을 정의하는 두 단계로 나뉩니다. 시스템 작업 식별 프로세스

1.1 고수준 도메인 모델(High-level Domain Model) 생성

시스템 작업의 동작을 설명하기 위한 **어휘(Vocabulary)**를 정립하는 단계입니다. 이 모델은 구현 단계의 복잡한 모델과 달리, 비즈니스 핵심 개념 간의 관계를 파악하는 데 집중합니다.

  • 도출 방법: 사용자 스토리의 명사에서 핵심 클래스를 추출하여 시스템의 어휘를 정립합니다. (또는 event storming 기법 활용)
  • 분석 방법: 사용자 시나리오(Given-When-Then)에 등장하는 **명사(Nouns)**를 분석하여 시스템의 핵심 클래스들을 식별합니다.

[시나리오 1: 주문 생성]

전제(Given)
소비자와 음식점이 존재하고, 배달 가능 지역 및 최소 주문 금액 조건을 만족한다.

조건(When)
소비자가 음식점에 주문을 요청한다.

결과(Then)
소비자 신용카드가 승인되고, 주문이 \`PENDING_ACCEPTANCE\` 상태로 생성되어 소비자와 음식점에 각각 연관된다.
  • 💡 도출된 클래스: `Consumer`, `Restaurant`, `Order`, `CreditCard`

[시나리오 2: “주문 접수(Accept Order)”]

전제(Given)
- 현재 주문은 PENDING_ACCEPTANCE 상태고, 해당 지역에 배달 가능한 배달원이 존재한다.

조건(When)
- 음식점이 주문을 접수하고, 준비 완료 시각을 약속한다.
 
결과(Then)
- 주문 상태가 ACCEPTED로 변경된다.
- 주문의 약속 시각(promiseByTime)이 업데이트된다.
- 배달을 담당할 배달원이 배정된다.
  • 💡 도출된 클래스: `Courier`(배달원), `Delivery`(배달)

위 과정에서 추출된 명사들은 시스템의 핵심 클래스가 되고, ‘주문 상태’와 같은 구체적인 데이터는 클래스의 **속성(Attribute)**이 됩니다. 이러한 분석을 반복하여 시스템 전체를 설명할 수 있는 고수준 도메인 모델을 완성합니다. 고수준 도메인 모델


1.2 시스템 작업(System Operations) 정의

도메인 모델이 완성되면, 이를 기반으로 애플리케이션이 처리해야 할 요청인 시스템 작업을 구체화합니다.

  • 도출 방법: 사용자 스토리의 **동사(Verbs)**를 분석하여 시스템의 책임을 정의합니다.
  • 분류: 시스템 작업은 크게 **명령(Commands)**과 **쿼리(Queries)**로 나뉩니다.

A. 명령(Commands)

명령은 데이터의 생성, 수정, 삭제를 통해 시스템의 상태를 변화시키는 작업입니다. 도메인 모델의 어휘를 사용하여 기술적인 상세 구현 전의 **동작 명세(Specification)**를 작성합니다.

  • [동작 명세의 구성 요소]
  1. 매개변수 및 반환 값: 입력 데이터와 결과 데이터를 정의합니다.
  2. 선행 조건(Pre-conditions): 작업 호출 시 반드시 충족되어야 하는 시스템 상태입니다. (Givens)
  3. 후행 조건(Post-conditions): 작업이 완료된 후 반드시 보장되어야 하는 시스템의 상태 변화입니다. (Thens - 예: 주문 객체가 생성됨)`

[주요 시스템 명령 예시]

액터스토리커맨드설명
소비자주문 생성 + "createOrder()" + 주문을 생성한다.
음식점주문 접수 + "acceptOrder()" + 주문을 접수하고 준비 완료 시각을 약속한다.
음식점픽업 준비 완료 + "noteOrderReadyForPickup()" + 음식이 준비되어 픽업 가능함을 알린다.

[동작 명세 상세 예시: createOrder]

항목상세 내용
작업createOrder(소비자ID, 결제수단, 배달주소, 배달시각, 음식점ID, 주문품목)
반환값orderId, status 등
전제 조건• 소비자가 존재하며 주문 가능 상태여야 함
• 주문 품목이 음식점 메뉴에 존재해야 함
• 배달 주소가 해당 음식점의 서비스 범위 내여야 함
사후 조건• 신용카드 승인이 완료됨
• 주문이 + "PENDING_ACCEPTANCE" + 상태로 생성됨

B. 쿼리(Queries)

쿼리는 데이터를 조회하여 사용자에게 필요한 정보를 제공하는 작업입니다. 명령과 달리 시스템의 상태를 변경하지 않으며, 주로 UI를 구성하거나 사용자의 의사결정을 돕는 데 사용됩니다.

  • 특징: 복잡한 검색 로직이나 성능 최적화가 필요한 경우가 많아 설계 시 중요하게 다뤄집니다.
  • 예시:
  • `findAvailableRestaurants(주소, 시각)`: 특정 조건에서 배달 가능한 음식점을 검색합니다. (지오서치 등 복잡한 로직 포함 가능)
  • `findRestaurantMenu(음식점ID)`: 음식점의 상세 정보와 메뉴판 정보를 조회합니다.`

2단계: 서비스 분해(Decomposition) 전략

식별된 작업을 어떤 서비스에 담을지 결정하는 단계입니다. 기술적인 계층보다는 비즈니스 개념을 중심으로 조직하는 것이 핵심입니다.

주요 분해 전략

  1. 비즈니스 역량(Business Capabilities) 기반: “무엇을 하는가”에 집중하여 주문 관리, 재고 관리 등 비즈니스가 가치를 창출하는 단위로 서비스를 나눕니다.
  2. DDD 서브도메인(Subdomains) 기반: 도메인 주도 설계의 Bounded Context 개념을 적용하여 언어적, 기능적 경계에 따라 서비스를 나눕니다.

3단계: 서비스 API 및 협업 설계

마지막으로 각 시스템 작업을 실제 서비스에 할당하고, 서비스 간에 어떻게 협력할지 정의합니다.

  • API 할당: 1단계에서 정의한 작업을 서비스에 배정합니다.
  • 협업 정의: 하나의 작업이 여러 서비스를 거쳐야 할 경우, 추가적인 작업(API)과 통신 방식(IPC)을 설계합니다.

MSA 설계 시 마주하는 4가지 장애물

이 프로세스는 기계적으로 흘러가지 않습니다. 설계 과정에서 반드시 다음의 기술적 난관을 고려해야 합니다.

  1. 네트워크 지연(Network Latency): 서비스 분할로 인한 왕복 호출(Round-trip) 시간이 서비스의 실용성을 해치지 않는지 검토해야 합니다.
  2. 가용성 저하: 서비스 간 동기 통신은 전체 시스템의 가용성을 떨어뜨릴 수 있습니다. 자립적인(Self-contained) 서비스 구조를 고민해야 합니다.
  3. 데이터 일관성: 분산된 데이터베이스 환경에서 정합성을 유지하기 위해 Saga 패턴과 같은 보상 트랜잭션 기법이 필요합니다.
  4. 거대 클래스(God Classes): 여러 도메인에 걸쳐 있는 복잡한 객체는 DDD의 개념을 활용해 각 서비스에 맞는 형태로 쪼개야 합니다.

결론

MSA 아키텍처 정의는 단순한 기술 도입이 아니라 **비즈니스를 이해하고 이를 서비스로 투영하는 반복적인 예술(Art)**과 같습니다. 추상적인 시스템 작업 정의부터 시작하여 비즈니스 중심의 서비스 분해로 나아가는 이 3단계 프로세스는 복잡한 MSA 여정의 신뢰할 수 있는 가이드가 되어줄 것입니다.

Reference