카테고리 없음

도메인 주도 설계로 시작하는 마이크로서비스 개발 - 5장 마이크로서비스 설

Hwisaek 2022. 12. 7. 00:40
반응형

 마이크로서비스의 중요한 점은 기능적으로 응집도를 높이고, 타 서비스 간의 의존도를 낮추는 것이다. 이를 만족해야 마이크로서비스가 유연해진다. 5장은 응집도를 높이고, 의존도를 낮추는 것에 대한 내용이다.

 

5. 1. 마이크로서비스를 도출하는 방법

5. 1. 1. 비즈니스 능력에 근거한 도출

 마이크로서비스를  도출하는 가장 쉬운 방법은 경험을 근거로 도출하는 것이다. 예를 들어 하나의 비즈니스를 다음과 같은 마이크로서비스들로 구분 할 수 있다.

 이 방식은 대략적인 도출에는 유용하지만, 서비스 간의 관계 파악이나 해당 서비스의 구체적인 기능, 독립적인 데이터 식별에는 미흡하다.

 

5. 1. 2. DDD의 바운디드 컨텍스트 기반 도출

 비즈니스 능력에 근거한 도출을 보완하기 위해 DDD의 전략적 설계를 적용할 수 있다. 마이크로서비스를 도출할 때는 서비스가 소유권을 가진 데이터를 독립적으로 식별하는 것이 중요하다. 즉, 해당 서비스를 통해서만 접근 가능한 데이터를 식별해야한다. 

 위의 비즈니스 능력에 근거한 도출은 기능과 데이터가 분리되고, 하나의 통합 데이터가 여러 기능에서 사용되는 방식이다. 그러나 DDD에서는 데이터와 기능을 분리하지 않고 문제 영역인 하위 도메인마다 별도의 도메인 모델로 구분하며, 이 도메인 모델을 중심으로 마이크로서비스를 도출한다.

 

5. 2. DDD에서의 설계

MSA는 여러 마이크로서비스들을 사용하여, 독립적인 개선, 배포, 장애 격리 등의 장점을 가지고 있다. 이러한 MSA 를 위해 마이크로서비스를 제대로 구분하는 것이 중요하다. 여기서 하나의 마이크로서비스를 구분하기위한 단위로 바운디드 컨텍스트를 사용한다.

 

5. 3. DDD의 전략적 설계

5. 3. 1. 도메인과 서브 도메인

 DDD는 하나의 큰 도메인을 여러 도메인으로 나누고, 나뉘어진 도메인을 하나씩 해결하는 방법을 기본으로 한다. 하나의 큰 도메인을 비즈니스 도메인이라고 부르고, 이를 나눈 여러 도메인을 서브도메인이라고 한다.

 서브 도메인에서도 중요도에 따라 핵심 서브도메인, 지원 서브도메인, 일반 서브도메인 유형으로 나뉜다.

  • 핵심 서브도메인: 비즈니스 영역. 높은 우선순위를 갖는 영역이자 전략적으로 가장 큰 투자가 필요한 영역.
  • 지원 서브도메인: 비즈니스에 필수적이지만 핵심은 아닌 영역.
  • 일반 서브도메인: 특정 부분에 특화된 것은 아니나, 전체적으로 필요한 영역. 기존 제품으로 대체 가능.

 

5. 3. 2. 유비쿼터스 언어와 도메인 모델, 바운디드 컨텍스트

보통 고객, 현업, 설계자, 개발자들이 같은 것을 다른 용어로 부르는 경우가 많다. 이처럼 용어가 헷갈리거나 잘못 전달되는 것을 방지하기 위해 DDD에서는 유비쿼터스 언어를 이용한다. 유비쿼터스 언어는 특정 업무와 관련된 사람들 간에 자율적으로 정의되고 통용되는 개념을 의미한다.

 책에서는 다음과 같은 예시를 사용한다. 결제 도메인에서의 고객과 배송 도메인에서의 고객은 다른 것을 지칭하고 있으나 같은 용어를 사용한다. 이를 명확히 구분하기 위해 결제 도메인의 고객은 결제자, 배송 도메인의 고객은 수취자라고 명확히 구분하여 유비쿼터스 언어로 정의할 수 있다고 한다.

 이러한 결제자와 수취자 같은 개념들을 잘 정의한 것이 도메인 모델이다. 

 이 도메인 모델에서 사용되는 개념은 다른 도메인 모델에서는 다른 언어로 사용하는데, 이 다른 도메인 모델간의 경계가 바로 바운디드 컨텍스트이다.

 

5. 3. 3. 컨텍스트 매핑

 바운디드 컨텍스트 식별 시에도 마찬가지로 응집성은 높고 의존성은 낮게 설계해야 한다. 그러나 각 컨텍스트가 관계가 없지는 않다. DDD에서는 각 컨텍스트 간의 관계를 컨텍스트 매핑이라고 하고 관계를 선으로 그려 표시한다.

 시스템을 구성하는 컨텍스트 매핑 관계를 표시한 다이어그램을 컨텍스트 맵이라고 하며, 이를 그리려면 다양한 컨텍스트 매핑 패턴의 이해가 필요하다.

 

 

주요 컨텍스트 매핑 관계

 

공유 커널(Shared Kernel)

 공유 커널은 컨텍스트가 공통 모델을 공유하는 관계이다. 공통 라이브러리 등이 여기에 해당한다.

 

소비자와 공급자(Customer-Supplier)

 공급 컨텍스트는 상류(U;upstream)로, 소비 컨텍스트는 하류(D;downstream)로 표시한다. 데이터가 상류에서 하류로 흐르며, 공급자는 소비자가 원하는 기능을 제공해야 한다.

 

준수자(Confirmist)

소비자와 공급자와 유사하지만 공급자가 소비자가 원하는 기능을 제공하지 못하는 경우이다. 소비자는 공급자가 제공하는 모델을 그대로 사용한다.

 

충돌 방지 계층(ACL; Anti-Corruption Layer)

 소비자가 공급자의 모델에 영향을 받지 않도록 번역 계층을 만드는 것이다. ACL에서 소비자의 모델에 맞춰 공급자의 모델을 변환한다. 보통 레거시와 신규 시스템을 통합할 때 사용한다.

 

공개 호스트 서비스(OHS; Open Host Service)

 컨텍스트에 접근을 제공하는 프로토콜이나 인터페이스를 정의한다. 다른 컨텍스트에서 사용하도록 공유된 API가 해당된다.

 

발행된 언어(PL; Published Languate)

 소비자가 공급자의 기능을 사용하게 하기 위한 문서화된 정보 교환 언어이다. XML, JSON 등으로 표현 가능하며, 보통 공개 호스트 서비스와 짝을 이룬다.

 

컨텍스트 맵

 여러 컨텍스트간의 관계를 표현한 다이어그램이다. 앞에서의 여러 컨텍스트 매핑 패턴으로 작성가능하며 아래는 여러 패턴을 이용한 예시이다.

 

5. 4. 이벤트 스토밍을 통한 마이크로서비스 도출

 이벤트 스토밍은 DDD의 설계를 가속화할 수 있는 설계 기법으로 이해관계자들이 모여 브레인 스토밍하는 워크숍을 뜻한다.

5. 4. 1. 이벤트 스토밍 워크숍 준비

워크숍 쥰비

  • 공간: 깨끗한 벽 또는 탁자가 있는 넓은 공간
  • 참가자: 모든 이해관계자
  • 준비물: 다양한 색의 스티커, 라인테이프와 스카이테이프
  • 열린 분위기로 이벤트 스토밍을 이끌어 갈 퍼실리테이터

워크숍 방식

  1. 넓은 공간에 설계 공간을 마련한다.
  2. 준비물을 접근하기 쉽게 세팅한다.
  3. 모든 참가자가 펜을 든다
  4. 퍼실리테이터가 이끌어간다.

스티커 유형별 의미

이벤트 스토밍은 도메인을 다양한 색의 스티커로 표현한다.

유형색깔설명

유형 크기/색 설명
도메인 이벤트 오렌지색 발생된 사건, 과거시제동사로 표현
커맨드 파란색 도메인 이벤트를 트리거하는 명령
외부 시스템 핑크색 도메인 이벤트가 호출하거나 관계가 있는 레거시 또는 외부 시스템
액터 작은 노란색 개인 또는 조직의 역할
애그리거트 노란색 도메인 이벤트와 커맨드가 처리하는 데이터
상태가 변경되는 데이터
정책 라일락색 이벤트 조건에 따라 진행되는 결정
When [이벤트] Then [커맨드]
읽기 모델 초록색 도메인 이벤트 액터에게 제공되는 데이터
사용자 인터페이스 흰색 스케치 형태의 화면 레이아웃
핫스팟(Hot spot) 보라색 의문, 질문, 미결정 사항

 

5. 4. 2. 이벤트 스토밍 워크숍 진행

 이벤트 스토밍은 아래 순서대로 진행되며, 한번에 3시간을 넘기지 않는 것이 좋다.

 

1. 도메인 이벤트 찾기

 시간의 흐름에 따라 시스템의 동작을 의미하는 도메인 이벤트를 도출한다. 왼쪽에서 오른쪽으로 시간 흐름 순으로 붙이되, 연쇄적으로 발생하는 경우 바로 옆에 붙인다. 

 

2. 외부 시스템/외부 프로세스 찾기

 외부 시스템과 연계될 경우 우측 상단에 붙이고, 화살표를 이용해 외부 시스템을 호출하는 것을 표시한다. 

3. 커맨드 찾기

 도메인 이벤트를 동작하게 만드는 커맨드를 찾아서 동사 형태로 작성한다. 하나의 커맨드로 여러 이벤트가 발생 할 수 있다.

4. 핫스폿 찾기

의문점이 생기거나 결정하기 힘든 사항, 타 부서 문의가 필요한 사항 등은 보라색으로 문제가 되는 위치에 붙이며, 워크숍 진행 중 언제라도 작성 할 수 있다.

 

5. 액터(사용자/역할) 찾기

 액터는 사용자 또는 조직, 역할자를 의미하며 비즈니스를 수행하는 구체적인 역할로 도출한다. 보든 업무에서 보편적으로 사용되는 회원, 관리자로 정의하기보단 특정 비즈니스를 실제로 수행하는 판매자, 구매자, 상품 관리자, 배송 관리자와 같이 명확한 역할자를 도출해야한다.

 

6. 애그리거트 정의하기

 애그리거트는 커맨드와 도메인 이벤트가 영향을 주는 데이터 요소로 도메인의 실체 개념을 표현하는 객체인 엔티티이다. 애그리거트를 구체적으로 식별할 수록 컨텍스트의 경계를 식별하기 좋으므로 구체적으로 도출하는 것이 좋다.

7. 바운디드 컨텍스트 정의하기

일부 애그리거트는 이름이 같거나 유사하다. 이러한 애그리거트들을 다른 애그리거트와 구분해서 경계를 그릴 수 있다. 이 경계를 바운디드 컨텍스트라고 한다.

 컨텍스트의 이름은 바운디드 컨텍스트를 대표할 수 있는 이름으로 정의한다. 

정책을 도출하면서 연관관계 생각하기

 정책은 이벤트 뒤에 따라오는 반응적인 비즈니스 로직으로, 어딘가의 커맨드를 동작하게 하며 다음과 같이 정의한다.

[도메인 이벤트] 할 때는 항상 [커맨드] 한다.

 정책이 호출하는 커맨드는 다른 컨텍스트에 존재할 수도 있으며, 이를 통해 다른 컨텍스트와의 관계를 식별 할 수 있다.

 

8. 컨텍스트 매핑하기

 컨텍스트 관계를 컨텍스트 맵으로 표현 할 수 있으며 표현 시 호출 방향을 고려해야 한다. 그리고 동기, 비동기 방식도 판단해야하며 동기는 실선, 비동기는 점선으로 표현한다.

 동기 호출은 실시간 동시 처리를 위해 사용하며 의존도가 높다. 비동기 호출은 처리 후 이벤트를 발행하여 다른 컨텍스트가 처리 할 수 있도록 하며, 의존도가 낮다. 그러므로 반드시 실시간 동시 처리가 필요한 것이 아니면 비동기를 고려하는 것이 좋다.

 

5. 5. 마이크로서비스 상세설계

5. 5. 1. 프런트엔드 모델링

 기술이 발전하며 더 나은 UX를 위한 SPA가 대두되었으며, 이를 지원하는 다양한 프레임워크들이 등장했으며 대표적으로 리액트, 뷰, 앵귤러가 존재한다.

 

프런트 아키텍처 정의

  • 사용자 요건에 적절한 아키텍처를 정의해야 한다. B2C의 경우 모바일이 대중화되어 웹과 모바일 등 다양한 환경을 지원하는 반응형 UI가 많이 사용된다.
  • 아키텍처 수립 시 패키지 구조도 정의가 필요하다. 마이크로서비스 팀이 책임지고 있는 업무를 고려하여 잘 정의한다.

표준 레이아웃 정의

  • 시스템 목적과 기능을 고려하여 표준 레이아웃을 정의한다. 사용자가 주로 사용하는 것들을 고려하고 이러한 사용자 경험을 검토하여 정의한다.

UI레이아웃 설계

  • 각 기능을 만족할 UI를 정의하는 과정으로, 표준 유형을 기반으로 개별 UI 레이아웃을 설계한다.
  • 산출물로 UI 스토리보드가 있다.

UI 디자인 및 UI레이아웃 반영

  • 표준 화면 유형에 맞는 UI 디자인을 정의한다. 
  • 보통 웹 디자이너가 수행하며 프런트엔드 개발자와 긴밀한 협의가 필요하다.

이벤트 설계

  • 화면 이벤트에 따라 백엔드 API를 호출하는 방식을 정의한다.

 

5. 5. 2. 백엔드 모델링

 이벤트 스토밍 결과를 이용해 헥사고날 구조로 정의하고 매핑 가능하다. 이벤트 스토밍의 커맨드는 헥사고날의 인바운드 어댑터인 REST API가 되고, 애그리거트는 내부 영역인 도메인 모델이 되며, 도메인 이벤트는 외부 영역의 아웃바운드 메시지 처리 어댑터의 처리 대상이 되고, 외부 시스템은 아웃바운드 어댑터가 호출 할 외부 연계 시스템으로 매핑된다.

API 설계

 API는 백엔드에 존재하지만 프런트엔드의 요구사항을 만족하도록 정의해야 한다. REST API가 표준처럼 사용된다.

 

REST API의 개념

 REST(Representational State Transfer) API는 HTTP를 이용한 네트워크 기반 아키텍처 스타일이다. 구성요소로 자원, 행위, 표현이 있다. "홍길동이라는 사용자를 생성한다"를 예로 보면 자원은 사용자이고 행위는 생성한다이며 표현은 홍길동이 된다. 이를 REST API로 표현하면 다음과 같다.

HTTP POST http://example.com/users/

{
    "users":{
                "name": "홍길동"
    }
}

 

자원은 URI, 행위는 POST, 표현은 JSON으로 표현할 수 있다.

 

REST API 성숙도

 다음 레오나르도 리처드슨이 정의한 REST API 성숙도 모델이다.

  • 레벨 0: REST API를 사용하지 않고 RPC 방식으로 HTTP 프로토콜만 이용한 것.
  • 레벨 1: URI에 개별적인 자원을 표현하는 것.
  • 레벨 2: 서비스의 기능을 위해 약속된 HTTP 메서드를 사용하는 것. ex) GET, POST, PUT, DELETE
  • 레벨 3: HATEOAS(Hypertext As The Engine Of Application State). 요청의 반환값에 추가로 다음에 무엇을 할 수 있는지와 그것을 하기 위해 다룰 수 있는 URI 값을 보내준다.

API 설계 문서화

설계물은 최대한 줄이며, 공유와 협업의 측면에서만 고려하는 것이 좋다. 최대한 간소한 것이 좋으며 다음 항목을 포함시키도록 한다.

  • 서비스명, API명, 리소스(URI)
  • 요청 매개변수, 요청 샘플
  • 응답 매개변수, 응답 샘플

 

5. 6. 도메인 모델링

 마이크로서비스의 내부 구조는 폴리글랏하게 접근 가능하다. 따라서 서비스의 내부 영역의 구조를 도메인 중심, 트랜잭션 스크립트 형태 등으로 선택하여 만들 수 있다.

 단순한 로직은 트랜잭션 스크립트 구조로 만들어도 무방하다. 그러나 복잡해지면 도메인 모델 구조가 효과적이다. 어떤 내부 구조를 선택할 지 결정하려면 서비스가 제공할 기능과 팀의 역량을 고려해야 한다.

 

5. 6. 1. DDD의 전술적 설계(도메인 모델링 구성요소)

 DDD의 전술적 설계에서는 단순하고 이해하기 쉬운 구조를 위해 객체들의 역할에 따른 유형을 정의하고, 이러한 규칙에 따라 모델링하는 설계 기법을 제공한다.

 

엔티티

 엔티티는 다른 엔티티와 구별할 수 있는 식별자를 가진 도메인의 실체 개념을 표현하는 객체이다. 식별자를 제외한 속성 및 상태는 변할 수 있다. 이 식별자와 변화 가능성이 VO와 구분되는 차이점이다.

 

값 객체(Value Object)

 값 객체는 속성과 속성의 합에 의해 전체 개념이 부며되며, 개별 속성이 별개로 수정되지 않고 전체 객체가 한번에 생성되거나 삭제되는 객체이다.

 

표준 타입

 대상의 타입을 나타내는 서술적 객체이다. 엔티티나 값 객체의 속성을 구분하는 용도로 사용되며, 컨텍스트에 맞는 유비쿼터스 용어로 정의하는 것이 좋다.

 

애그리거트

 애그리거트는 트랜잭션의 기본 단위로 연관된 엔티티와 값 객체들의 묶음이다. 애그리거트 내 엔티티 중 최상위 엔티티를 애그리거트 루트로 정하고, 애그리거트 루트를 통해서만 애그리거트 내 엔티티나 값 객체를 변경할 수 있다.

 하나의 컨텍스트에 여러 애그리거트가 존재 할 수도 있으며, 애그리거트는 별도의 마이크로서비스의 후보가 될 수도 있다. 그러므로 여러 애그리거트가 존재할 때, 다른 애그리거트 내 엔티티를 직접 참조하면 마이크로서비스로 분리하기 힘들어지므로 애그리거트 루트를 통해서만 참조하는 것이 좋다.

 

도메인 서비스

 도메인의 비즈니스 로직 처리가 특정 엔티티나 값 객체에 속하지 않을 때 단독 객체를 만들어서 처리하게 되는데, 이것이 도메인 서비스이다. 

 

도메인 이벤트

 도메인 이벤트는 DDD에서 말하는 도메인 이벤트의 구현체이다. 서비스 간 정합성 일치를 위해 애그리거트의 주요 값을 담아 전달하도록 모델링한다.

 

 

 

 

 

정리

 이번 장에서는 마이크로서비스를 상세 설계하는 내용을 살펴보았다. 지금까지는 이론 부분이 대부분 이었는데 뒤에서는 각종 사례들을 이용하여 실무에서 어떻게 사용되는지 알아볼 수 있어서 기대가 된다.

 

 

출처

https://engineering-skcc.github.io/agile/microservice-agile/

https://engineering-skcc.github.io/microservice%20modeling/microservice-%EB%8F%84%EC%B6%9C%EA%B8%B0%EB%B2%95/

https://engineering-skcc.github.io/microservice%20modeling/ddd-Srategic-design/

https://engineering-skcc.github.io/microservice%20modeling/Event-Storming/

https://engineering-skcc.github.io/microservice%20modeling/FrontEnd-modeling/

https://engineering-skcc.github.io/microservice%20modeling/BackEnd-modeling-API/

https://engineering-skcc.github.io/microservice%20modeling/BackEnd-modeling-domainModeling/

반응형