[마이크로서비스패턴] 2장 분해전략

2장. 분해 전략

2장의 핵심 내용

  • 소프트웨어 아키텍처 정의, 중요성
  • 분해 패턴을 적용하여 비즈니스 능력 및 하위 도메인 별 애플리케이션 서비스 분해
  • DDD의 경계 컨텍스트 개념 활용 데이터 분해

마이크로서비스 아키텍처란?

소프트웨어 아키텍처 정의

애플리케이션 아키텍처는 여러 파트로의 분해와 이런 파트 간의 관계

  • 업무와 지식의 분리 : 전문 지식인들과 함께 애플리케이션 작업 가능
  • 소프트웨어 엘리먼트가 어떻게 상호 작용하는지 밝힘

4+1 뷰 모델

소프트웨어 아키텍처를 바라보는 상이한 4뷰

  • 논리 뷰 : 개발자가 작성한 소프트웨어 엘리먼트. 클래스와 패키지. 상속, 연관, 의존 등 클래스와 패키지의 관계
  • 구현 뷰 : 빌드 시스템의 결과물. 모듈, 컴포넌트로 구성. 모듈 간 디펜던시와 컴포넌트/모듈 간 조합 관계도 포함됨.
  • 프로세스 뷰 : 런타임 컴포넌트. 각 엘리먼트는 개별 프로세스고, IPC는 프로세스 간 관계를 나타냄.
  • 배포 뷰 : 프로세스가 머신에 매핑되는 방법. 이 뷰의 엘리먼트는 (물리 또는 가상) 머신 및 프로세스. 머신 간의 관계가 바로 네트워킹. 프로세스와 머신 사이의 관계도 이 뷰에서 기술.
  • 시나리오 : 뷰의 여러 엘리먼트가 협동하는 과정 명시
  엘리먼트관계
논리 뷰개발자가 작성한 것클래스, 패키지클래스와 패키지의 관계
구현 뷰빌드 시스템이 만들어 내는 것모듈(jar 파일), 컴포넌트(war 또는 실행 파일)모듈/컴포넌트 간 디펜던시
프로세스 뷰컴포넌트 실행프로세스프로세스 간 통신
배포 뷰‘머신’에서 실행 중인 프로세스머신, 프로세스네트워킹

아키텍처 중요성

애플리케이션 두 요건

  1. 기능 요건 : 아키텍처와 무관
  2. 서비스 품질 요건 : 확장성, 신뢰성(런타임 품질) / 관리성, 테스트성, 배포성(개발 시점 품질)
    • 선택한 애플리케이션 아키텍처에 따라 각 품질 요건 충족 결정됨

아키텍처 스타일

계층화 아키텍처 스타일 - Layerd architecture

  • 전형적인 아키텍처
  • 계층마다 명확히 정의된 역할 분담. 계층 간 디펜던시는 아키텍처로 제한
    • 어떤 계층은 바로 하위에 있는 계층에만 의존 or 하위에 위치한 어느 한 계층에 의존
  • 3 계층 아키텍처
    • presentation layer : 사용자 인터페이스, 외부 API 구현 계층
    • business logic layer : 비즈니스 로직 구현 계층
    • persistence layer : DB 상호작용 로직 구현 계층
  • 단점
    • 표현 계층이 하나
    • 영속화 계층이 하나
    • 비즈니스 로직 계층을 영속화 계층에 의존하는 형태로 정의

육각형 아키텍처 스타일 - Hexagonal

논리 뷰를 비즈니스 로직 중심으로 구성하는 계층화 아키텍처 스타일의 대안
표현 계층 -> 인바운드 어댑터
영속화 계층 -> 아웃바운드 어댑터

  • 인바운드 포트 : 비즈니스 로직 표출 API. 외부 애플리케이션은 이 API를 통해 비즈니스 로직 호출
    • 서비스의 퍼블릭 메서드가 정의된 서비스 인터페이스
  • 아웃바운드 포트 : 비즈니스 로직이 외부 시스템을 호출하는 방법
    • 데이터 접근 작업이 정의된 리포지터리 인터페이스
  • 인바운드 어댑터 : 외부에서 들어온 요청을 인바운드 포트를 호출해서 처리
    • REST endpoint, Spring MVC Conroller, 메시지 브로커 클라이언트
    • 동일 인바운드 포트를 여러 인바운드 어댑터 호출 가능
  • 아웃바운드 어댑터 : 비즈니스 로직에서 들어온 요청을 외부 애플리케이션/서비스를 호출해서 처리
    • DB 작업 구현된 DAO 클래스, 원격 서비스 호출하는 proxy 클래스
    • 이벤트를 발행하기도
  • 장점
    • 비즈니스 로직이 표현/데이터 접근 로직 어디에도 의존하지 않음 : 비즈니스 로직 테스트 용이

모놀리식, 마이크로서비스 아키텍처 스타일?

서비스 & 느슨한 결합

서비스

서비스는 어떤 기능이 구현되어 단독 배포가 가능한 소프트웨어 컴포넌트

단독 API를 갖고, 독립적으로 배포 가능

  • 커맨드, 쿼리, 이벤트로 구성된 API 제공
  • API는 어댑터를 이용해 구현
    • 작업 어댑터 : 비즈니스 로직 호출
    • 이벤트 어댑터 : 비즈니스 로직이 내어 준 이벤트 발행
  • 구현 뷰 : 스탠드얼론 프로세스, 컨테이너 내부 웹 애플리케이션, OSGI 번들, 서버리스 클라우드 기능 등 다양한 컴포넌트 사용 가능

느슨한 결합

  • 유지보수성, 테스트성을 높이고 애플리케이션 개발 시간을 단축해줌.
  • DB 테이블 분리
    • 장점 : 런타임 격리, 서로 다른 서비스의 테이블 접근으로 인한 락 불가
    • 단점 : 데이터 쿼리, 일관성 유지 복잡

공유 라이브러리 역할

  • 서비스 코드 중복을 줄이는 것은 좋지만 의도치 않은 서비스 간 결합도 유발하지 않도록 조심
  • 바뀔 일이 거의 없는 기능은 라이브러리에 담아 쓰는 것 좋음

마이크로서비스 아키텍처 정의

3단계를 거침

  1. 시스템 작업 식별
  2. 서비스 식별
    • 비즈니스 능력 패턴별 분해
    • 하위 도메인 패턴별 분해
  3. API 정의

1. 시스템 작업 식별

사용자 스토리, 시나리오 기반 애플리케이션 요건에서부터 시작.
고수준의 도메인 모델 생성 -> 도메인 모델 관점 기술

고수준 도메인 모델 생성

  • 스토리에 포함된 명사 분석.
  • 최종 구현 모델보다는 단순.

시스템 작업 정의

  • 애플리케이션이 어떤 요청을 처리할지 식별 단계
  • 시스템 작업 두 종류
    1. 커맨드 : 데이터 생성, 수정, 삭제(CUD)
    2. 쿼리 : 데이터 읽기(R)

2. 서비스 식별

2.1. 비즈니스 능력

비즈니스 능력 = 조직이 하는 일
비즈니스 객체에 집중하여, 여러 개의 하위 능력으로 분해.

2.2. 하위 도메인

DDD의 도메인 구성 방식 활용. 경계 컨텍스트.
비즈니스 능력에 따라 하위 능력으로 나눈 것과 결과가 거의 비슷함.

2.3. 분해 지침

로버트 C. 마틴의 객체지향 설계 두 가지 원칙

  1. 단일 책임 원칙
    • 클래스는 오직 하나의 변경 사유를 가져야 한다.
    • 마이크로서비스 역시 하나의 책임만 가진 작고 응집된 서비스를 정의
  2. 공동 폐쇄 원칙
    • 패키지의 클래스들은 동일한 유형의 변경에 대해 닫혀 있어야 한다. 패키지에 영향을 주는 변경은 그 패케지에 속한 모들 클래스에 영향을 끼친다.

2.4. 서비스 분해 장애물

  • 네트워크 지연 : 배치 API
  • 동기 통신으로 인한 가용성 저하 : 동기 -> 비동기 메시징 처리
  • 여러 서비스에 걸쳐 데이터 일관성 유지 : SAGA (메시징을 이용한 일련의 로컬 트랜잭션)
  • 데이터의 일관된 뷰 확보 : 다행히 실제로 거의 문제 X —> real?? DB 복제 지연으로도 문제가 발생하는데.
  • 분해를 저해하는 만능 클래스

3. API 정의

  • 시스템 작업을 서비스로 배정 : 요청의 진입점 결정
  • 서비스 간 협동 지원에 필요한 API 확정

참조