6장에서는 도서 대출 시스템을 예시로 하여 마이크로서비스를 도출하고 아키텍처를 구성하는 것을 살펴본다.
6.1. 요구사항 정의
도서 대출 시스템은 다음 기능을 필요로 한다.
사용자 관리 및 로그인
- 사용자를 등록한다. 등록시 사내 HR 시스템에 의해 검증된다.
- 특정 사용자는 사서의 역할을 부여받는다.
- 사용자는 로그인하거나 로그아웃 할 수 있다.
도서 관리
- 사서는 도서분류 정보를 등록/수정/삭제한다.
- 사서는 입고된 도서를 분류하고 등록/수정/삭제한다.
- 일반적인 도서는 도서공급사에 의해 공급된다.
- 각 도서는 대출할 수 있는 재고가 있으며, 대출/반납에 의해 재고가 조정된다.
도서 대출 및 반납
- 사용자는 도서를 검색한다.
- 사용자는 베스트 대출 목록을 조회할 수 있다.
- 사용자는 재고가 있는 도서를 대출한다.(기간은 2주, 인당 5권 제한)
- 반납되지 않고 대출 기간이 지난 도서는 연체된다.
- 1권이라도 연체되면 사용자는 대출 불가 상태가 된다.
- 사용자는 대출한 도서를 반납할 수 있다.
- 대출한 모든 도서 이력은 기록된다.
- 대출하거나 반납 시 사용자에게 10포이트가 부여된다.
- 연체가 있는 사용자는 대출할 수 없다.
- 포인트는 연체 1일당 10포인트씩 연체일을 감면하는데 사용된다.
- 연체일을 0으로 만듦으로써 대출가능상태가 된다.
배송
- 원격지의 사용자는 배송을 요청할 수 있다.
- 배송의 상태는 접수/준비/발송/배송완료다.
- 배송은 외부 배송업체를 이용한다.
이메일
- 주요 업무 변화 시 이메일로 사용자에게 통보한다.
6.2. 이벤트 스토밍을 통한 마이크로서비스 도출
이번 단계에서는 앞의 요건을 기반으로 이벤트 스토밍을 통해 바운디드 컨텍스트 식별을 통해 마이크로서비스 후보를 찾아내고 관계를 정의한다.
6.2.1 이벤트 스토밍 워크숍
위에서 정의한 요건을 사용자 관리, 도서 관리, 도서 대출 및 반납, 배송, 이메일로 분류하 서브도메인 별로 이벤트 스토밍을 진행해보면 다음과 같다.
사용자 관리 서브도메인
도서 관리 서브도메인
대출, 반납 서브도메인
배송 서브도메인
게시판 서브도메인
6.2.2. 바운디드 컨텍스트 식별
앞의 이벤트 스토밍 결과를 이용하여 컨텍스트를 구분할 차례이다.
사용자 관리 서브도메인
기능이 사용되는 정도로 구분하여 "로그인"과 "회원"으로 바운디드 컨텍스트를 분리할 수 있다.
대출, 반납 서보드메인
"카탈로그", "대출" 컨텍스트로 분리 할 수 있다.
도서 대출 시스템의 메인 기능들은 "대출" 컨텍스트로 묶고, "대출"이라는 행위를 통한 정보가 아닌 "도서검색정보", "최다대출도서집계" 는 "카탈로그" 컨텍스트로 분리할 수 있다.
"대출" 컨텍스트는 다른 모든 컨텍스트와 관계를 맺으므로 많은 호출 관계를 가지고 있다.
게시판 서브도메인
"게시판" 컨텍스트로 식별
도서 서브도메인
"도서" 컨텍스트로 식별
배송 서브도메인
"배송" 컨텍스트로 식별
마지막 세 서브도메인은 특이한 점이 없어 그대로 바운디드 컨텍스트로 분리 할 수 있으며 서브도메인은 사각형, 바운디드 컨텍스트는 타원형으로 표시하면 아래와 같다.
6.2.3. 컨텍스트 다이어그램
구체적인 부분은 생략하고 컨텍스트 간의 호출 방식만 표현하면 아래와 같다. 점선은 비동기 호출, 실선은 동기 호출이다.
이렇게 구분된 컨텍스트는 마이크로서비스 후보가 되며 배포, 운영 효율성 등을 고려해 통합되거나 분하될 수 있다.
6.2.4. 이벤트 스토밍 결과를 헥사고날 아키텍처로 표현하기
이벤트 스토밍 | 헥사고날 아키텍처 구성요소 |
커맨드 | 외부영역의 인바운드 아댑터 - API 후보 |
어그리게잇 | 내부영역의 도메인 모델의 후보 |
도메인이벤트 | 외부영역의 아웃바운드 아댑터로 전송되는 메시지 이벤트 후보 |
외부시스템 | 외부영역의 아웃바운드 아댑터로 연결될 대외 인터페이스 후보 |
정책 | 내부영역의 비지니스 로직 규현 규칙 외부영역의 아웃바운드 어댑터로 연결될 타서비스와의 방향 결정에 도움이 됨 |
이벤트 스토밍 결과를 위 표와 같이 매핑하면 아래와 같은 헥사고날 아키텍처가 된다.
6.3. 외부 아키텍처 정의
- 백엔드 마이크로서비스: 기존에 구분한 컨텍스트를 기반으로 마이크로서비스를 만든다.
- 프론트엔드: Vue.js
- API 게이트웨이: 로드 밸런싱, 라우팅 역할 수행. 줄, 리본을 사용.
- 프론트엔드 + 사용자/로그인 백엔드 서비스 + API 게이트웨이: 하나의 서비스에 통합되어 구현
- 서비스 저장소: 서비스의 저장소는 RDB로 MariaDB를 이용하며, 카탈로그 서비스는 읽기에 최적화된 NoSQL인 MongoDB를 사용한다.
- 서비스 통신: 동기 통신에는 페인을 쓰고 비동기 통신에는 메시지 큐를 사용.
- 메시지 큐: Kafka
- 배포: 도커 컨테이너로 쿠버네티스에 배포
- 로그 중앙화: ELK
- 모니터링: Kiali
- 형상관리: Github
- 개발 환경 구축: Jhipster
6.4. 내부 아키텍처 정의
이 책에서는 저장 메커니즘으로 MyBatis를 사용하고 저장 메커니즘으로는 스프링 데이터를 적용했다. 책의 예시는 Java로 되어 있어 Java에서 주로 사용되는 규칙을 이용하고 있다.
6.4.1. 패키지 구조 및 명명 규칙
구분 | 패키지명 | 유형 | 명명 규칙 | 명칭 및 역할 | 작성 기준 |
내부 영역 | domain | 클래스 | 도메인개념을 명확히 표현할 수 있는 명사형 | 도메인 모델 비지니스 개념 및 로직 표현. 애그리거트, 엔터티, VO, 표준 타입 패턴으로 구현 |
애그리거트 단위 |
service | 인터페이스 | ~Service | 서비스 인터페이스: 서비스 퍼사드 역할 | 애그리거트당 1개 | |
클래스 | ~ServcieImpl | 서비스의 구현체: 업무처리흐름 구현 | 서비스 I/F당 1개 | ||
repository | 인터페이스 | ~Repository | 리포지토리: 저장소 처리 | 엔터티 당 1개 | |
외부 영역 | web.rest | 클래스 | ~Resource | REST 컨트롤러: REST API 발행, 인바운드 요청 처리 | |
adaptor | 클래스 | ~Client | REST 클라이언트: 동기 아웃바운드 처리 다른 서비스를 동기 방식으로 호출 |
호출할 타 서비스당 1개 | |
클래스 | ~Consumer | 컨슈머 어댑터: 비동기 메시지 인바운드 처리 | |||
인터페이스 | ~Producer | 비동기 메시지 인터페이스: 비동기 아웃바운드 메시지 전송을 정의하는 인터페이스 | 호출할 타 서비스당 1개 | ||
클래스 | ~ProducerImpl | 비동기 메시지 구현체: 비동기 아웃바운드 메시지 전송을 구현 | Producer에 의존 | ||
dto | 클래스 | ~DTO | 데이터 전송 객체: 동기 호출 시 데이터 전송 객체로 사용 | API에 의존 |
6.5. JHipster를 이용한 아키텍처 구성
책에 나온대로 실습을 진행해보려 했는데 아래와 같이 에러가 발생하여 현재 진행하지 못하고 있다. 에러를 처리 후 다시 작성 하도록 할 예정이다.
출처
https://github.com/CNAPS-MSA/CNAPS3/blob/master/contents/ddd.md