이커머스 프로젝트 - 이벤트 스토밍을 통한 마이크로서비스 도출

김동균·2022년 12월 11일
0

마이크로서비스는 각 저장소를 독립적으로 보유하고, 각 데이터는 다른 서비스에서 직접 참조해서는 안 되는 특성이 있다.
따라서 마이크로서비스를 도출할 때 서비스가 소유권을 가진 데이터를 독립적으로 식별하는 것이 중요한데, 이를 위해 DDD의 전략적 설계를 활용하여 문제 영역마다 별도의 도메인 모델로 정의한다.
이 때 DDD의 전략적 설계를 가속화하기 위해 이벤트 중심의 전략적 설계 기법인 이벤트 스토밍을 활용하여 마이크로서비스를 도출해보겠다.
설계는 이전에 작성한 요구사항 정의를 기반으로 진행한다.

이벤트 스토밍

이벤트 스토밍은 모든 이해관계자가 모여 서로가 가지고 있는 각 관점들을 논의하는 설계 기법으로, 민첩성과 효율성이 뛰어난 장점이 있다.
시스템을 분석하기 위해 현실의 비즈니스 도메인을 이벤트 스토밍에서 사용하는 다양한 의미의 스티커를 통해 표현한다.
이벤트 스토밍 스티커의 유형

도메인 이벤트 : 발생한 사건, 과거시제동사로 표현
커맨드 : 도메인 이벤트를 트리거하는 명령
외부 시스템 : 도메인 이벤트가 호출하거나 관계가 있는 외부 시스템
액터 : 개인 또는 조직
애그리거트 : 도메인 이벤트와 커맨드가 처리하는 데이터, 상태가 변경됨
정책 : 이벤트 조건에 따라 진행되는 결정
읽기 모델 : 도메인 이벤트 액터에게 제공되는 데이터
사용자 인터페이스 : 스케치 형태의 화면 레이아웃
핫스팟 : 의문, 질문, 미결정 사항

도메인 이벤트 찾기

우선 요구사항 정의를 기반으로 도메인 이벤트를 도출한다.
도메인 이벤트는 시간의 흐름에 따른 시스템의 동작을 의미하며, 비즈니스 흐름에서 발생한 이벤트에 초점을 둔다.
왼쪽에서 오른쪽으로 시간 흐름순으로 이벤트를 작성하며, 이벤트가 연쇄적으로 발생하는 경우 바로 옆에 작성하고 비즈니스 조건에 따라 대체적으로 발생하는 경우 바로 아래에 작성한다.
도메인 이벤트 도출

외부 시스템 도출

도메인 이벤트가 연쇄적으로 발생하는 곳을 보면 외부 시스템을 도출할 수 있다.
상품이 주문될 때 발생하는 [결제 승인됨] 이벤트, 상품이 주문 취소될 때 발생하는 [결제 취소됨] 이벤트와 연계되는 외부의 결제 시스템이 도출된다.
외부 시스템 도출

커맨드 도출

도출된 도메인 이벤트를 동작하게 하는 커맨드를 찾는다.
커맨드 도출

핫스팟 도출

참여자들끼리 결정하기 힘든 사항 등 정의할 수 없는 것들을 파악하고 핫스팟으로 도출한다.
핫스팟 도출

액터 도출

도출된 커맨드를 실행하는 액터를 도출한다.
액터는 판매자, 구매자, 시스템 관리자 등 명확한 역할자를 도출해야 한다.
액터 도출

액터를 도출하면서 비즈니스 흐름을 문장으로 만들어 식별한 커맨드와 이벤트를 검토할 수 있다.
구매자가 상품 주문을 취소하면 [상품 주문 취소됨] 이벤트가 발생하고, 이어서 결제 시스템을 통해 [결제 취소됨] 이벤트가 발생, 연쇄 이벤트로 [상품 재고 수정됨], [배송정보 삭제됨] 이벤트가 발생함으로써 시스템이 동작한다.

애그리거트 정의

애그리거트 정의 단계부터는 비즈니스 관점이 아닌 설계 관점에서 바라보아야 한다.
애그리거트는 커맨드와 도메인 이벤트가 영향을 주는 데이터 요소로, 도메인의 실체 개념을 표현하는 객체인 엔티티가 된다.
바운디드 컨텍스트의 경계를 식별하는데 애그리거트가 활용되기 때문에 최대한 구체적인 표현으로 도출하는 것이 좋다.
애그리거트 정의

바운디드 컨텍스트 그리기

도출된 애그리거트를 보면 일부 애그리거트들은 이름이 같거나 유사한 것을 알 수 있다.
이름이 같거나 유사한 애그리거트를 완전히 다른 애그리거트와 구분하여 경계를 식별하는데, 이 때 그동안 도출했던 도메인 이벤트, 커맨드, 액터, 애그리거트를 모두 고려한다.
이렇게 구분된 경계를 바운디드 컨텍스트라고 하며, 컨텍스트의 이름은 보통 애그리거트 이름으로 정의하지만 동일 컨텍스트 내에 여러 개의 애그리거트 이름이 있는 경우 전체를 아우를 수 있는 이름으로 정한다.
바운디드 컨텍스트 그리기

[결제수단] 애그리거트는 [회원] 애그리거트의 부가 정보라고 생각하여 [회원]이라는 바운디드 컨텍스트로 정의하고, [상품]과 [상품분류정보] 애그리거트도 묶어 [상품] 바운디드 컨텍스트로 정의했다.
[로그인] 또한 [회원] 애그리거트와 분리하여 독립적인 마이크로서비스로 식별할 수도 있지만, [회원] 컨텍스트에서 회원이 등록되고 삭제되는 시점에 [로그인] 컨텍스트와 일관성을 맞춰야 하고 구현의 편의성을 위해 [회원] 컨텍스트로 묶었다.
[주문], [결제] 애그리거트는 상품 검색 이후 주문, 결제까지 하나의 흐름으로 이어지기에 [주문] 컨텍스트로 묶어 정의했다.

상품 검색은 [상품] 컨텍스트에 잘 어울리지만, 상품의 등록/수정/삭제보다 상품 검색 것이 훨씬 빈번히 사용되어 CQRS 패턴을 적용하여 별도의 [상품 카탈로그]라는 컨텍스트로 분리할 수 있다.
하지만 본 프로젝트에서는 [로그인]과 마찬가지로 구현의 편의를 위해 [상품] 컨텍스트에 함께 묶었다.

정책 도출 및 바운디드 컨텍스트간의 관계 그리기

정책을 도출하고 바운디드 컨텍스트 간의 관계를 그리면 다음과 같다.
정책 도출 및 바운디드 컨텍스트간의 관계 그리기

컨텍스트 매핑

식별된 바운디드 컨텍스트 간의 관계를 별도의 컨텍스트 맵으로 표현한다.
컨텍스트 간에 호출이 발생할 때 동기 방식의 호출이 필요한지, 비동기 방식의 호출이 필요한지 판단하여 작성한다.
데이터의 일관성과 컨텍스트의 가용성을 고려하여 호출 방식을 선택하며, 컨텍스트 간에 항상 일관된 데이터가 필요한 경우 동기 호출로 표현하고 궁극적 일관성으로 충분히 처리 가능한 관계는 비동기 방식의 호출로 표현한다.
이벤트 기반으로 비동기 호출을 처리할 것이기 때문에 컨텍스트 간의 의존성을 낮출 수 있기 때문이다.
동기 방식은 실선, 비동기 방식은 점선으로 표현한다.
컨텍스트 매핑

마이크로서비스 정의

도출된 바운디드 컨텍스트들은 마이크로서비스 후보가 된다.
최종적으로 마이크로서비스로 정의하려면 다음과 같은 항목을 고려해서 판단할 수 있다.

  • (비즈니스 측면) 비즈니스 프로세스를 수행하기 위한 하나의 맥락의 단위로 구분될 수 있는가?
  • (데이터 관점) 마이크로서비스별로 분리된 데이터를 정의할 수 있는가?
  • (운영 조직 측면) 하나의 팀이 독립적으로 운영 가능한 단위인가?
  • (배포 측면) 독립적으로 배포 가능한 단위인가?
  • (변경 영향도) 변경 시 영향을 받는 마이크로서비스가 존재하는가?
  • (클라우드/MSA 도입 목적 측면) 도입을 통한 기대효과를 충분히 활용할 수 있는가?

위 항목들을 모두 만족한다면 바운디드 컨텍스트를 최종 마이크로서비스로 식별하고, 만족하지 못한다면 각 항목의 결과에 따라 바운디드 컨텍스트를 분리하거나 통합하여 마이크로서비스로 식별한다.

profile
백엔드 개발자

0개의 댓글