책너두 (도메인 주도 설계로 시작하는 마이크로서비스 개발) 12일차 (~101p)

요약

  • 마이크로서비스의 애플리케이션 아키텍처의 나머지 부분에 대해 이해함.
    • 마이크로서비스의 내부 구조 정의
      • 클린 마이크로서비스
        • 마이크로서비스 시스템에서는 각 서비스가 목표와 활용도에 따라 분리되어야 함
        • 적절한 개발 언어, 저장소, 내부 아키텍처를 정의해야 함.
        • 복잡한 비즈니스 규칙을 가진 서비스는 헥사고날 아키텍처나 클린 아키텍처를 기반으로 정의하는 것이 좋음.
        • 외부 영역과 내부 영역으로 구분하며, 내부 영역에는 도메인과 도메인을 감싸는 서비스가 존재함.
        • 서비스 인터페이스와 리포지토리 인터페이스를 통해 외부 영역과 연계함.
        • 의존 관계 역전 원칙을 적용하여 유연성과 확장성을 지원하는 구조를 구축할 수 있음.
      • 내부 영역 - 업무 규칙
        • 트랜잭션 스크립트 패턴
        • 도메인 모델 패턴
        • 도메인 주도 설계의 애그리거트 패턴

메모

3.3 마이크로서비스의 내부 구조 정의

  • 지금까지 살펴본 레이어드 아키텍처, 헥사고날 아키텍처, 그리고 클린 아키텍처는 모두 모노리스 애플리케이션 뿐만 아니라 마이크로서비스에도 적용 가능한 아키텍처임.
    • 이러한 아키텍처들이 최근 강조되는 이유는 이들이 마이크로서비스의 유연성확장성을 지원하는 구조이기 때문임.
    • 이제 이 아키텍처들을 참고하여 바람직한 마이크로서비스의 내부 구조를 정의해 본다.

3.3.1 바람직한 마이크로서비스의 내부 아키텍처: 클린 마이크로서비스

  • 기존의 모노리스 소프트웨어에 대한 아키텍처 고민 결과가 마이크로서비스에서도 적용되어야 함.
    • 마이크로서비스 시스템에서 정의해야 할 내부 구조는 다양할 수 있다. 폴리글랏한 내부 구조를 가질 수 있기 때문임.
  • 마이크로서비스 아키텍처에서 각 서비스는 각기 목표와 활용도에 따라 명확하게 분리되어야 하고, 각 서비스의 목적에 따라 적절한 개발 언어 및 저장소, 내부 아키텍처를 정의하는 것이 바람직함.
    • 비즈니스 규칙이 복잡한 서비스는 헥사고날 아키텍처나 클린 아키텍처의 구조를 기반으로 정의하는 것이 바람직함.

  • 바람직한 마이크로서비스의 내부 구조를 정의하기 위해 3가지 아키텍처가 지향하는 원칙들을 정리해야 함.
    • 이를 통해 위 그림과 같은 마이크로서비스 아키텍처 구조를 정의할 수 있음.
    • 외부 영역과 비즈니스 로직을 표현하는 내부 영역으로 구분한다.
  • 내부 영역에서는 도메인이 존재하고 도메인을 서비스가 감싼다.
    • 도메인에는 핵심 비즈니스 개념과 규칙을 구현하며, 서비스에서는 도메인을 호출해서 업무를 처리하는 절차를 기술함.
    • 외부 영역과 연계하기 위해 서비스 인터페이스를 보유함.
  • 내부 영역에 있는 또 다른 인터페이스는 리포지토리(Repository) 인터페이스임.
    • 외부 영역에서 정의하지 않고 내부 영역에서 정의하는데, 비즈니스를 처리하는 데 필요한 기본적인 저장소 처리 사항을 추상화해 정의함.
    • 외부 영역에는 다양한 인바운드, 아웃바운드를 처리하는 어댑터가 위치함.
  • 이러한 원칙을 준수하면서 마이크로서비스 아키텍처 구조를 정의한다.
    • 이를 통해 유연성과 확장성을 지원하는 클린 마이크로서비스 아키텍처를 구축할 수 있음.
    • 이 구조에서 외부 영역의 저장소 처리 어댑터, 이벤트 발행 어댑터, API 호출 프락시 어댑터 등 모든 아웃바운드 어댑터는 의존 관계 역전의 원칙을 적용해 외부 영역에서 내부 영역에 의존하도록 설계함.

3.3.2 내부 영역 - 업무 규칙

  • 내부 영역 구현에 필요한 패턴을 살펴본다.
    • 업무 규칙을 정의하는 내부 영역에는 서비스 인터페이스, 서비스 구현체, 도메인, 리포지토리 인터페이스, 도메인 이벤트 인터페이스, API 프락시 인터페이스가 존재함.
  • 서비스 인터페이스는 외부 영역이 내부 영역에 대해 너무 많이 알지 못하게 하는 역할을 함.
    • 서비스 인터페이스가 없다면 추이 종속성이 발생할 수 있다(정보 은닉 효과도 있다).
  • 리포지토리 인터페이스, 도메인 이벤트 인터페이스, API 프락시 인터페이스는 의존 관계 역전의 원칙을 지원함.
    • 더 안정된 곳인 고수준 영역에 인터페이스가 존재하고 저수준의 외부 어댑터가 이러한 인터페이스를 구현하게 함.
  • 비즈니스 로직의 핵심인 서비스와 도메인을 고려한다.
    • 서비스와 도메인은 클린 아키텍처의 유스케이스와 엔티티의 역할과 같다. 도메인은 비즈니스 개념을 표현하고 서비스는 도메인을 활용해 시스템 흐름 처리를 수행한다.
  • 내부 영역, 특히 서비스와 도메인의 관계를 구현할 때 참고할 만한 유용한 패턴은 마틴 파울러의 <엔터프라이즈 애플리케이션 아키텍처 패턴>에서 언급한 트랜잭션 스크립트 패턴과 도메인 모델 패턴임.

트랜잭션 스크립트 패턴

  • 트랜잭션 스크립트(Transaction Script) 패턴에서는 비즈니스 개념을 표현하는 도메인 객체가 행위를 가지고 있지 않음.
    • 따라서 모든 비즈니스 행위, 즉 무엇인가를 수행하는 책임은 서비스에 있음.
    • 서비스가 비즈니스 절차에 따라 절차적으로 도메인 객체를 이용해 모든 처리를 수행함.
    • 이런 방식에서는 시간이 지남에 따라 서비스가 비대해지고 도메인 객체는 점점 정보 묶음의 역할만 수행하게 될 뿐임.
  • 서비스는 유스케이스 처리의 단위이고 대부분의 비즈니스 로직 처리가 서비스에서 이뤄지므로 비슷한 유스케이스의 경우 서비스에 중복되는 코드가 계속 생겨날 수 있음.
    • 이러한 점이 유지보수를 어렵게 할 수 있음.
  • 트랜잭션 스크립트 패턴은 절차식 프로그래밍 방식과 같기 때문에 객체지향 지식이 없어도 쉽게 이해할 수 있는 구조이고 기존 데이터베이스 중심 아키텍처에 익숙하다면 더 쉽게 적응할 수 있음.
    • 이 패턴은 비즈니스가 간단한 경우에는 쉽게 적용할 수 있음.
    • 그렇지만 비즈니스가 복잡해질 경우 서비스 코드의 양이 점점 증가하는 등 데이터베이스 중심 아키텍처에서 겪었던 문제점이 발생할 여지가 큼.
    • 따라서 간단한 비즈니스를 처리할 때 적용하는 것이 좋음.

도메인 모델 패턴

  • 도메인 모델 패턴은 도메인 객체가 데이터와 비즈니스 행위를 가지며, 도메인 객체의 데이터는 해당 객체가 제공하는 행위에 의해 은닉됨.
    • 도메인 객체는 비즈니스 개념 및 행위에 대한 책임을 수행하고, 서비스는 비즈니스 유스케이스를 구현하기 위해 서비스의 행위를 도메인 객체에 일부분 위임함.
    • 서비스의 책임이 도메인으로 적절히 분산되어 서비스가 비대해지지 않고, 서비스 메서드는 단순해짐.
  • 도메인 모델 패턴은 객체지향 설계의 객체 모델이며, 거대한 서비스 클래스 대신 적절한 책임을 가진 여러 클래스로 구성되어 이해하기 쉽고 관리 및 테스트하기 쉬움.
    • 이 패턴은 도메인 주도 설계의 애그리거트 패턴을 적용할 수 있는 구조임.
    • 도메인 모델을 잘 만들면 복잡한 비즈니스 로직 처리에 유용하며, 코드의 양이 줄어들고 재사용성도 높아짐.
    • 복잡한 비즈니스 로직이 많은 마이크로서비스의 구조로 선택하기 좋음.

도메인 주도 설계의 애그리거트 패턴

  • 애그리거트 패턴은 도메인 주도 설계에서 복잡한 객체 모델링의 단점을 보완한 패턴으로, 도메인 모델링 시 객체 간 관계를 참조로 표현하게 됨.
    • 업무가 복잡해지면 참조 관계가 복잡해지고 무거워질 수 있음.
    • 이를 개선하기 위해 최상위 엔티티(Root Entity)를 중심으로 개념의 집합을 분리한 것이 애그리거트 패턴임.
    • 애그리거트는 1개 이상의 엔티티와 값 객체(Value Object)로 구성되며, 개념적으로 묶인 엔티티의 모음 전체를 의미함.
  • 애그리거트 패턴에서는 일관된 처리를 위해 다음 규칙을 부여함
    1. 애그리거트 루트만 참조
      • 애그리거트 내 상세 클래스를 바로 참조하지 않고 루트를 통해 참조해야 함.
    2. 애그리거트 간의 참조는 기본 키를 사용
      • 기본 키를 사용하면 느슨하게 연관되고 수정이 필요하지 않은 애그리거트를 함께 수정하는 실수를 방지함.
    3. 하나의 트랜잭션으로 하나의 애그리거트만 생성 및 수정
      • 이 규칙을 따르면 애그리거트의 일관성이 유지됨.

댓글

Designed by JB FACTORY