DDD 아키텍처

2023. 4. 29. 13:57개발 관련 책 읽기/DDD 시작하기

✅ 아래 내용들에 대해서 알아보자

- 도메인이란?
- DDD 아키텍처
- DIP
- 도메인 영역의 주요 구성요소
- 모듈 구성

 

 

도메인이란

 도메인이란 소프트웨어로 해결하고자 하는 문제영역을 의미한다. 온라인 서점으로 예를 들면 상품 조회, 구매, 결제, 배송등의 기능이 해당된다. 쉽게 이야기하면 기능별로 쪼갠다고 이해하면 좋을 것 같네요 ㅎ

 

도메인

 

 

Order라는 주문 클래스가 있다고 가정하겠습니다.

 

기존의 서비스 로직에서 해당 로직들을 처리하는 프로세스와 다르게 주문 클래스에 비즈니스 로직을 위임함으로써 도메인에 종속된 로직들은 Order객체에 위임하고 있다. (DDD는 도메인 클래스에 연관된 로직을 넣는다는 느낌? ㅎㅎ)

 

 

기존 서비스 레이어에 로직을 실행하던 방식

public class OrderService {

   private final OrderRepository orderRepository;

    /**
     * 배송지 변경
     */
    public void changeShippingInfo(Long orderId,ShippingInfo newShippingInfo) {
        Order order=orderRepository.findById(orderId);
        
        if(order != null)
             로직 수행...			
    	....
        ....

    }
    
    




}

 

 

도메인 클래스에 로직을 위임하는 방식

package com.ddd.practice_ddd.order;

import java.util.List;
import java.util.Objects;
import lombok.Getter;

/**
 * 주문
 */
@Getter
public class Order {

    private String orderNumber;
    private List<OrderLine> orderLines;
    private Money totalAmounts; //총 가격

    private ShippingInfo shippingInfo;

    private OrderState state;
    private Orderer orderer;


    /**
     * 배송지 변경
     */
    public void changeShippingInfo(ShippingInfo newShippingInfo) {
        로직...
    	....
        ....

    }




}

 

 

 

DDD 아키텍처

DDD 아키텍처는 크게 4가지로 구분된다. ('표현' '응용''도메인',  '인프라스트럭처')

 

1. 표현 영역

 표현 영역은 사용자 요청을 해석하여 응용 서비스에 전달하고 응용 서비스의 실행 결과를 사용자가 이해할 수 있는 형식으로 반환하여 응답한다.

 

예를 들어, HTTP 요청을 받아 응용 서비스라 리턴한 결과를 JSON 형식으로 변환해서 웹 브라우저에 전송하는 방식이 될 수 있다.

 

 

표현 영역 설명

 

 

2. 응용 영역

 응용 영역은 시스템이 사용자에게 제공해야 할 기능을 구현하는 비즈니스 로직이 포함된 계층이라고 볼 수 있다.

예를 들어, '주문 등록', '주문 취소', '상품 상세 조회'와 같은 기능 구현을 예로 들 수 있다.

 

 

응용 영역 설명

 

 

3. 도메인 영역

  도메인 영역은 도메인 모델을 구현한다. 예를 들어, 주문(Order), 배송(Shipping)과 같은 도메인 모델이 이 영역에 위치하여 도메인의 핵심 로직을 구현한다. (결제 완료, 배송지 변경 등..)

 

 

4. 인프라스트럭처 영역

 인프라스트럭처 영역은 구현 기술에 대한 것을 다룬다. 이 영역은 RDBMS 연동을 처리하고, 메시징 큐에 메시지를 전송하거나 수신하는 기능을 구현하고, 몽고 DB나 레디스, 카프카 등 데이터 연동을 처리한다.

 

이 영역은 SMTP를 이용한 메일 발송 기능을 구현하거나 HTTP 클라이언트를 이용해서 REST API를 호출하는 것도 처리한다. 인프라스트럭처 영역은 논리 개념보다는 실제 구현을 다루는 영역이라고 이해하면 좋을 것 같다.

 

인프라 스트럭처 영역

 

 

DIP

 DIP에 대해 알기 전 계층 구조 아키텍처(Layered Architecture)에 대해서 간단하게 알아보고 가자.

 

DDD에서 레이어드 아키텍처는 표현 -> 응용 -> 도메인 -> 인프라 스트럭처 간의 의존성을 가지고 구성된다.

계층 구조는 상위 계층에서 하위 계층으로의 의존만 존재하고 하위 계층은 상위 계층에 의존하지 않는다. 예를 들어, 표현 계층(상위)은 응용 계층(하위)에 의존한다. 인프라 스트럭처 영역은 어디에도 의존하지 않는다.

 

상황에 따라 계층 구조를 유연하게 적용하기도 한다. 예를 들어, 응용 계층은 바로 아래 도메인 계층에 의존하지만 외부 시스템과의 연동을 위해 인프라 스트럭처 계층에 의존하기도 한다. 

 

 

계층 구조 아키텍처

 

하지만 인프라 스트럭처 계층에 종속된다는 단점이 생기게 되고, 이로 인해 '테스트 어려움', '기능 확장의 어려움'이 발생하게 된다. 이 두 가지 문제를 해결하는 방법이 DIP이다.

 

즉, DIP는 고수준 모듈이 저수준 모듈을 의존하지 않고, 반대로 저수준 모듈이 고수준 모듈에 의존하게 한다. 구현체에 의존하는 것이 아닌 추상화에 의존하게 된다!

 

이러한 구조로 구성하면 변경할 부분이 적어지고 다른 영역에 영향을 주지 않고, 테스트가 용이해지고 확장성이 좋아진다. 

DIP 예시

 

아래 왼쪽 그림은 DIP를 잘못 적용한 예이다. 도메인 영역의 고수준 모듈인 CalculateDiscountService가 인프라 영역에 의존하고 있다. RuleEngine 인터페이스는 고수준 모듈인 도메인 관점이 아니라 룰 엔진이라는 저수준 모듈관점에서 도출이 되었다. 

 

DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출해야 한다. CalculateDiscountService 입장에서 봤을 때 할인 금액을 구하기 위해 룰 엔진을 사용하는지 직접 연산하는지는 중요하지 않다. 단지 규칙에 따라 할인 금액을 계산한다는 것이 중요하다. 

 

즉, "할인 금액 계산"을 추상화한 인터페이스는 저수준 모듈이 아닌 고수준 모듈에 위치해야 한다.(오른쪽 그림 참고)

 

 

 

 

아래는 DIP를 적용한 구조이다

DIP를 적용한 구조

 

 

DIP를 적용하면 추가적인 요구사항이 들어와도 응용 영역의 OrderService는 변경할 필요가 없다.

인프라스트럭처 영역에서 구현 클래스를 추가하면 된다. 

 

 

 

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

 

 

 

 

 


모듈 구성

 패키지 구성 규칙에 정답이 존재하는 것은 아니지만. 영역별로 모듈이 위치할 패키지를 구성할 수 있을 것이다.

 

도메인이 큰 경우

 

 

하위 도메인을 포함한 경우

 

 

애그리거트, 모델, 리포지토리는 같은 패키지에 위치시킨다. 예를 들어 주문과 관련된 Order, OrderLine, OrderProduct 등은 domain 패키지에 위치시킨다.

 

 

 

감사합니다 😀😁😃

 

DDD 시리즈는 최범균 님의 DDD 책을 참고하여 정리하는 글입니다. 

 

반응형

'개발 관련 책 읽기 > DDD 시작하기' 카테고리의 다른 글

애그리거트  (0) 2023.05.15