고딩왕 코범석

2장 아키텍처 개요 본문

Book Lounge/도메인 주도 개발 시작하기

2장 아키텍처 개요

고딩왕 코범석 2022. 7. 1. 23:01
반응형

2장 - 아키텍처 개요

Index

  1. 네 개의 영역
  2. 계층 구조 아키텍처
  3. DIP
  4. 도메인 영역의 주요 구성요소

네 개의 영역

표현 영역

  • 사용자의 HTTP 요청을 응용 영역으로 전달하고 응용 영역의 결과를 사용자에게 HTTP로 전달한다.
  • 이 때, 사용자는 실제 웹 브라우저 이용자가 될 수 있고, API를 호출하는 외부 시스템이 될 수 있다.

응용 영역

  • 사용자에게 제공해야할 기능을 수행하는 영역이다.
  • 기능을 구현하기 위해 도메인 영역의 도메인 모델을 사용한다.
  • 로직을 직접 수행한다기 보다는 도메인 모델에게 로직 수행을 위임한다.

도메인 영역

  • 도메인 모델들이 위치하는 영역이며, 핵심 로직이 구현되는 장소이다.

인프라스트럭쳐 영역

  • 구현하기 위해 사용하는 외부 기술에 대한 것을 다룬다.
    • RDBMS, MongoDB, Redis와 같은 데이터베이스와의 연동
    • 메시지 큐에 메시지 전송과 수신
    • SMTP를 이용한 이메일 발송 기능
    • HTTP 클라이언트를 이용해 외부의 REST API를 호출

정리

  • 도메인, 응용, 표현 영역은 구현 기술을 사용한 코드를 직접 만들지 않는다.
  • 인프라스트럭쳐 영역에서 제공하는 기능을 사용해 필요한 기능을 개발한다.

계층 구조 아키텍처

image
  • 위의 네 영역을 사용할 때 많이 사용하는 아키텍처는 ‘표현 > 응용 > 도메인 > 인프라스트럭쳐’ 로 의존 방향을 가리키게 된다.
  • 이 계층 구조는 상위 계층에서 하위 계층으로 의존만 하고, 하위 계층은 상위 계층으로 의존하지 않는다.
image
  • 위와 같이 외부 시스템과의 연동을 위해 인프라스트럭쳐 계층을 직접 의존할 수 있다.
  • 직관적으로 이해하기 쉽지만 표현, 응용, 도메인 계층이 상세한 구현 기술인 인프라스트럭쳐에 종속된다는 단점이 있다.
    • 인프라스트럭쳐에 종속되면 의존하고 있는 응용 계층만을 위한 테스트 작성이 어렵고, 구현 방식을 변경하기 어렵다는 단점이 있다.

DIP (Dependency Inversion Principel)

  • 고수준의 모듈이 저수준의 모듈에 의존하면 안된다.
  • 저수준의 모듈이 고수준의 모듈을 의존하여 테스트하기 쉽고 변경에 유연하도록 바꾼다.
image
  • 책 예제에서의 CalculateDiscountService는 할인과 관련한 일을 수행해야 한다.
    • 외부 기술이 별도의 엔진이든, 특정 데이터베이스를 무엇을 쓰는지는 알아야 할 이유가 없다.
  • 위의 그림처럼 저수준 모듈이 고수준 모듈에 의존하면 테스트하기 쉬워지고 변경에 용이한 구조가 된다.
    • 테스트의 경우 RuleDiscounter를 Mock 처리하여 단위 테스트 작성이 가능하다.
    • DroolsRuleDiscounter가 아닌 다른 구현체를 사용할 경우 DI 설정을 다른 구현체로 변경해주면 된다.
  • DIP 적용 시 적용할 하위 기능을 추상화할 때는 고수준 모듈 관점에서 추상화시킨다.
    • CalculateDiscountService 입장에서 어떤 DB를 사용하는지, 어떤 엔진을 사용하는지는 중요하지 않다.
  • DIP와 아키텍처

    image
  • 앞에서의 계층형 구조와 달리 DIP를 적용하면 위 사진과 같은 구조가 된다.
  • 인프라스트럭쳐에 위치한 구현 클래스가 도메인이나 응용 영역에 정의한 인터페이스를 상속받아 구현하는 구조가 되어 도메인과 응용 영역에 영향을 주지 않거나 최소화하여 구현 기술에 대해 변경이 가능한 구조이다.
  • image

    도메인 영역의 주요 구성요소

    요소 설명
    Entity 고유의 식별자를 갖는 객체로 자신만의 라이프사이클을 갖는다. 도메인의 고유한 개념을 표현한다. 도메인 모델의 데이터를 표현하며 해당 데이터와 관련된 기능을 함께 제공한다.
    Value 고유의 식별자를 갖지 않는 객체이며 개념적으로 하나인 값을 표현할 때 사용된다.
    Aggregate 연관된 엔티티와 밸류 객체를 개념적으로 하나로 묶은 것을 의미한다.
    Repository 도메인 모델의 영속성을 처리한다.
    Domain Service 특정 엔티티에 속하지 않은 도메인 로직을 제공한다. ’할인 금액 계산’은 상품, 쿠폰, 회원 등급, 구매 금액 등 다양한 조건을 이용해 구현하는데, 도메인 로직이 여러 엔티티와 밸류를 필요로 하면 도메인 서비스에서 로직을 구현하면 된다.

    엔티티와 밸류

    • 도메인 엔티티와 DB 관계형 모델의 엔티티는 다르다.
    • 가장 큰 차이점은 도메인 엔티티는 도메인 기능을 클래스에서 함께 제공한다.
    • RDBMS에서 표현하기 어려운 밸류 타입을 도메인 엔티티에서는 밸류 타입으로 선언한다.
      • 이 때, 밸류 타입은 불변 타입으로 선언하고, 교체할 경우 새 객체로 교체하는 것을 권장한다.

    애그리거트

    • 도메인 모델은 개별 객체 뿐만 아니라 상위 수준에서 모델을 볼 수 있어야 전체 모델의 관계와 개별 모델을 이해하는데 도움이 된다.
      • 주문 도메인의 경우 주문, 배송지 정보, 주문자, 주문 목록, 총 결제 금액과 같은 하위 모델로 구성된다. 이 하위 개념을 표현한 모델을 하나로 묶어 주문이라는 상위 개념으로 표현할 수 있다.
    • 애그리거트는 군집에 속한 객체를 관리하는 루트 엔티티를 갖는다.
      • 루트 엔티티는 애그리거트에 속한 엔티티와 밸류 객체를 이용해 애그리거트가 구현할 기능을 제공한다.
      • 루트 엔티티에 속한 엔티티나 밸류 객체에 접근할 때는 루트 엔티티를 통해 접근하도록 해야한다.
        • 이는 구현을 캡슐화할 수 있도록 돕는다.

    리포지토리

    • 도메인 객체를 지속적으로 사용하려면 물리적인 저장소에 엔티티를 보관해야한다.
    • 이를 위한 도메인 모델이 Repository이다.
    • 응용 서비스는 도메인 객체를 구하거나 저장할 때 리포지터리를 사용한다.
    • 또한 응용 서비스는 트랜잭션을 관리하는데, 트랜잭션 처리는 리포지터리 구현 기술에 영향을 받는다.
    반응형