도메인 주도 설계(Domain-Driven Desgin)란?(feat.<도메인 주도 설계란 무엇인가?>)

devdo·2022년 5월 26일
1

Architecture

목록 보기
1/2

아키텍쳐 공부 중에 DDD(도메인 주도 설계) 얘기가 늘 나온다. 계속 한번쯤은 제대로 정리하고 싶었는데 늦은 밤 잠도 안올 때 바로 정리해본다.

도메인이란?

소프트웨어로 해결해야할 문제의 영역입니다.

예를 들어 고객이 원하는 상품을 어떻게 잘 제공할 것인가? 의 대한 문제는 커머스라는 도메인이 있습니다.

커머스 도메인의 하위 도메인으로 판매자가 무엇을 판매할 것인가? 의 대한 문제는 상품이라는 도메인이 있고,

공통된 상품에 대해서 어떻게 공통 정보를 제공할 것인가? 의 대한 문제는 카탈로그 도메인이 있습니다.

그 밖에 판매자, 사용자, 카테고리, 주문, 배송 등 많은 도메인들이 문제들이 나올 때마다 줄줄이 나올수 있습니다.


소프트웨어 해결의 존재 가치

소프트웨어의 본질은 해당 소프트웨어의 사용자를 위해 도메인에 관련된 문제를 해결하는 능력에 있습니다.

아무리 기술적으로 정교하고 뛰어난 성능을 갖추더라도 당면한 문제를 해결하지 못하는 소프트웨어는 실패한 소프트웨어라고 할 수 있습니다. 얼마나 빠른가, 얼마나 많이 처리할 수 있나, 얼마나 많은 사람이 붙어서 사용할 수 있나 등은 나중 이야기입니다.


왜 도메인 주도 설계 방식이 나왔나?

DDD 의 목표는 기술보다는 도메인에 대한 모델에 집중해 더 나은 소프트웨어를 만들어내는 것이다 - DDD 154p

기존 개발의 문제점(비즈니스 로직의 위치)

1) 데이터베이스 위주의 개발

이 개발방식은 데이터베이스 모델링을 중요시합니다. 그래서 이 개발 방식의 서비스에는 흐름제어 로직밖에 없고 비즈니스 규칙과 개념들은 SQL에 존재합니다.

이렇게 비즈니스 로직과 저장 기술이 강하게 결합되어 있는 구조인 경우, 저장소를 변경하기 쉽지 않습니다. 또한 성능 측면에서 성능을 데이터베이스에 의존하게 됩니다.

이러면 데이터가 많아졌을 때 데이터베이스의 성능은 지속적으로 떨어지고 이를 최적화 하기 위해 데이터베이스 서버의 사양과 용량을 계속 증가시키고 쿼리 튜닝에 몰두할 수 밖에 없습니다. 클라우드 인프라를 사용한 자동 스케일 아웃은 하지도 못하겠죠.

정작 바쁜 것은 데이터베이스이기 때문에 어플리케이션 관리가 쿼리 튜닝에 중점이 되게 됩니다.

2) 트랜잭션 스크립트 패턴

하나의 트랜잭션으로 구성된 로직을 단일 함수 또는 단일 스크립트에서 처리하는 구조이다.

예로, 서비스(Spring에서 사용되는 Service를 말함)에 모든 비즈니스 로직이 있고 비즈니스 절차에 따라 도메인 객체를 이용해 처리합니다. 도메인 객체는 단지 속성값만 이용되는 정보 묶음의 역할만 하게 된다.

서비스는 유스케이스(UseCase) 처리의 단위이고 대부분의 비즈니스 로직 처리가 서비스에서 이뤄지므로 비슷한 유스케이스의 경우 서비스에 중복되는 코드가 계속 생겨날 수 있는 단점이 있습니다. 이런한 점이 유지보수를 어렵게 합니다. 비즈니스 로직을 테스트하기 위해 Mocking을 해야하고 이는 테스트의 복잡성을 높이고 관리하기 어려운 테스트 코드를 발생시킬 여지가 크게 됩니다.

여기서 비즈니스 로직을 도메인 객체에 넣으면 서비스의 중복성을 줄여 응집도가 높아져 유지보수하기 좋아집니다. 이런 방식을 도메인 모델 패턴이라고 합니다.


그래서 도메인 모델 패턴

도메인 모델 패턴은 이렇습니다.

  • 도메인 객체가 속성뿐만 아니라 비즈니스 행위를 가지고 있어 책임을 수행하게 된다.
  • 서비스의 책임들이 도메인으로 분산되기 때문에 서비스의 메서드는 단순해진다.
  • 거대한 서비스 클래스 대신 각기 적절한 책임을 가진 여러 클래스로 구성되므로 이해하기 쉽고 관리 및 테스트하기 쉽다.
  • 잘 정의된 도메인 모델은 코드양을 줄이고 재사용성도 높다.
  • 도메인 모델 패턴은 도메인 주도 설계의 애그리거트 패턴을 적용할 수 있는 구조이다.

도메인 주도 설계의 흐름

DDD 에서 도메인 모델을 정의하고 구현하는 layer 는 domain layer 이기 때문에 DDD 에서는 domain layer 가 핵심입니다.

도메인 주도 설계는 크게 전략적 설계전술적 설계로 나뉩니다.

  • 전략적 설계 - 도메인 전문가 및 기술팀이 함께 모여 유비쿼터스 언어를 통해 도메인 지식을 공유 및 이해하고 이를 기준으로 개념과 경계를 식별해 바운디드 컨텍스트(bounded context)로 정의하고 경계의 관계를 컨텍스트 맵(context map)으로 정의하는 활동

  • 전술적 설계 - 전략적 설계에서 도출된 바운디드 컨텍스트와 도메인을 이용하여 애그리거트 패턴, 엔티티와 값 객체, 레포지토리 등을 구성하고 구현하는 활동


전략적 설계

: 도메인서브도메인을 만든다

  • 도메인은 한 조직이 행하는 일과 그 조직 안의 세계를 의미합니다.

  • 서브 도메인은 어떤 도메인 영역의 상위 도메인이 있는 것을 강조하기 위해 사용하는 용어입니다.

  • 서브 도메인은 중요도에 따라 핵심 서브도메인, 지원 서브도메인, 일반 서브도메인으로 나눕니다.

  • 핵심 서브도메인 - 다른 경쟁자와 차별화를 만들 비즈니스 영역이기 때문에 기업의 프로젝트 목록에서 높은 우선순위를 갖는 영역이자 소프트웨어 개발에서 전략적으로 가장 큰 투자가 필요한 영역. 예) 커머스 도메인에서 핵심 서브도메인은 주문, 결졔, 상품, 카테고리 등

  • 지원 서브도메인 - 비즈니스에 필수적이지만 핵심은 아닌 부분으로 볼 수 있다. 그러나 핵심 도메인을 성공시키기 위해서는 반드시 필요한 영역. 핵심 서브도메인 다음으로 중요한 영역. 예) 커머스 도메인에서 지원 서브도메인은 카탈로그, 쿠폰 등

  • 일반 서브도메인 - 비즈니스적으로 특화된 부분은 아니지만 전체 비즈니스 솔루션에는 필요한 부분으로 기존 제품을 구매해서 대체할 수 있다. 예) 커머스 도메인에서 일반 서브도메인은 파일관리, 인증관리, 결세 서비스 등

  • 예시로 든 서브 도메인들은 커머스 도메인이라고 할지라도 회사마다 중요하게 보는 것이 다르기 때문에 달라질 수 있음


유비쿼터스 언어

DDD 에서 말하는 유비쿼터스 언어(Ubiquitous) 개념처럼 - 현업에서 사용하는 보편적인 언어를 최대한 반영해야 합니다.

  • 특정 도메인에서 특정 용어가 해당 도메인에서의 의도를 명확히 반영하고, 도메인의 핵심 개념을 잘 전달할 수 있는 언어
  • 모든 팀원이 특정 용어를 들었을 때 같은 것을 생각할 수 있는 명확하게 정의된 언어. 같은 용어에 각자 다른 생각을 하거나 같은 것을 말하지만 용어가 다른 경우가 있으면 안된다.

  • 도메인에서 사용하는 언어는 코드에 그대로 똑같이 반영되야 한다. 똑같이 반영되지 않으면 개발자는 해당 용어를 해석하고 이해해야하는 부담이 생긴다.

  • 유비쿼터스 언어를 사용함으로써 코드의 가독성을 높여 코드를 분석하고 이해하는데 시간을 절약할 수 있다.

  • 용어가 정의 될 때마다 용어 사전에 이를 기록하고 명확하게 정의 함으로써 추후 또는 다른 사람들도 공통된 언어를 사용할 수 있도록 한다.


바운디드 컨텍스트

  • 도메인 영역의 경계
  • 바운디드 컨텍스트안에서는 유비쿼터스 언어를 사용해야한다.
  • 도메인 영역의 경계의 기준은 유비쿼터스 언어를 사용했을 때, 해당 용어의 개념이 달리지는(그래서 이름도 달라지게 함) 그 곳을 기준으로 경계를 나눈다.

  • 고객이라는 도메인은 결제 도메인 입장에서는 신용카드 정보나 계좌 정보를 가진 결제자로서 사용되고 배송 도메인 입장에서는 상품을 받을 주소와 우편번호, 전화번호를 소유한 수취자를 의미한다.
  • 도메인 모델은 특정한 컨텍스트 안에서 완전한 의미를 갖는다.
  • 바운디드 컨텍스트는 여러개의 서브 도메인으로 구성되고 하나의 서브 도메인은 한 바운디드 컨텍스트에 포함된다.

아래는 회사 내부 개발 팀을 정리할 때도 BOUNDED CONTEXT로 정리될 수 있음을 보여준다.

  • 하나의 BOUNDED CONTEXT하나의 팀에만 할당되어야 한다.
  • 하나의 팀은 여러 개의 BOUNDED CONTEXT를 다룰 수 있다.
  • 각각의 BOUNDED CONTEXT는 각각의 개발 환경을 가질 수 있다.(-> MSA와도 맞닿아있는 말이다.)

컨텍스트 맵

  • 컨텍스트 경계를 식별해 내고 이들간의 관계를 표현한 그림을 컨텍스트 맵(Context Map)이라 한다
  • 컨텍스트간의 관계는 선으로 표현되고 U는 Upstream으로서 공급자, D는 Downstream으로서 수요자를 나타낸다. 즉 데이터가 흐르는 방향
  • 관계는 단방향으로 설정한다.(Http 통신방식)
  • 동기 호출은(HTTP) 실선, 비동기 호출(MQ)은 점선
  • 이렇게 도출된 바운디드 컨텍스트는 마이크로서비스 후보가 된다.
    관련 블로그 : https://engineering-skcc.github.io/microservice%20modeling/ddd-Srategic-design/

이벤트 스토밍


: 이벤트를 중심으로 이해관계자들이 모여 브레인 스토밍하는 워크숍

이벤트 스토밍 방법
왼쪽에서 오른쪽으로 시간 흐름순으로 포스트잇 붙이기

같은 시점에 비즈니스 조건에 따라 대체적으로 발생할 수 있는 이벤트는 세로로 아래쪽에 같은 선상에 붙인다.

1) 도메인 이벤트 찾기 - 오렌지색
2) 외부 시스템/외부 프로세스 찾기 - 핑크색
3) 커맨드 찾기 -파란색
4) 핫스폿 찾기 - 보라색
5) 액터(사용자/역할) 찾기 - 작은 노란색
6) 애그리거트 정의하기 - 노란색
7) 바운디드 컨텍스트 정의하기 - 마커펜 또는 라인 테이프, 정책 도출은 라일락색
8) 컨텍스트 매핑하기

순서는 변경될 수 있다.
관련블로그 : https://velog.io/@maketheworldwise/DevOps-도메인-주도-설계

Event Storming이 끝나고 난 뒤

1) 기능적 효과

  • 도메인을 추출할 수 있다
  • 바운디드 컨텍스트를 추출할 수 있다
  • 에그리거트를 추출할 수 있다
  • 컨텍스트 맵을 추출할 수 있다.
  • 이벤트 스토밍 결과와 헥사고날 아키텍처 구성요소와 매핑이 가능해진다.

2) 참여자들의 학습효과

  • 모두가 서로에게서 배운다.
  • 모두가 서로 소통한다.
  • 자신의 관점에서 문제를 발견하면 누구나 말할 수 있다.
  • 모두가 문제를 해결하는 방법에 대한 자신의 아이디어를 제공한다.
  • 워크숍 후에는 모두가 같은 사실을 알게 된다.

출처: https://rok93.tistory.com/170 [티끌모아 로키산맥 🏔:티스토리]


전술적 설계

: 도메인 모델링 구성 요소 정리
기존 객체 모델링은 자유도가 높아 문제 영역을 파고들수록 여러 층의 복잡한 계층 구조를 만들게 될 가능성이 높다. 전술적 설계에서는 도메인 모델링 구성 요소의 역할에 따른 유형을 정의하고 이러한 규칙에 따라 모델링하면 단순하게 설계가 가능하다.

1) 엔티티(Entity)
2) 값객체(Value Object)
3) 애그리거트(Aggregate)
4) 레포지토리(Repository)
5) 도메인서비스
6) 팩토리
7) 도메인이벤트

1) 엔티티(Entity)

  • 엔티티는 다른 엔티티와 구별할 수 있는 식별자를 가진 도메인의 실체 개념을 표현하는 객체이다.
  • 식별자는 고유하되 엔티티의 속성 및 상태는 계속 변할 수 있다.
  • 식별자가 있기 때문에 데이터베이스로 추적가능하다

2) 값객체(Value Object)
값객체는 각 속성이 개별적으로 변화하지 않는 개념적 완전성을 모델링한다.

<도메인 주도 설계 핵심>의 저자 반 버논은 값객체의 특성을 다음과 같이 정의한다.

  • 도메인 내의 어떤 대상을 측정하고, 수량화하고, 설명한다.

  • 관련 특징을 모은 필수 단위로 개념적 전체를 모델링한다.

  • 측정이나 설명이 변경될 땐 완벽히 대체 가능하다.

  • 다른 값과 등가성을 사용해 비교할 수 있다.

  • 값 객체는 일단 생성되면 변경할 수 없다.
    그 밖에 특성

  • 밸류 타입은 불변

  • 시스템이 성숙함에 따라 데이터 값을 객체로 대체

  • 밸류 객체의 값을 변경하는 방법은 새로운 밸류 객체를 할당하는 것뿐이다.

  • 정말 String으로 우편 번호를 표현할 수 있는가?

  • 항상 equals() 메서드를 오버라이드할 것을 권고한다.

equals를 재정의하려거든 hashCode도 재정의하라 - Effective Java
VALUE OBJECT는 DTO가 아니다. - Martin Fowler

3) 애그리거트(Aggregate)

  • 관련 객체를 하나로 묶은 군집(1~2개의 엔티티와, VO, 표준타입(자바에서 enum)으로 구성)
  • 애그리거트는 군집에 속한 객체들을 관리하는 루트 엔티티를 갖는다.
  • 이들 간에는 비즈니스 의존관계를 맺고 있으며 비즈니스 정합성을 맞출 필요가 있다. 따라서 애그리거트 단위가 트랜잭션의 기본 단위가 된다.
  • 애그리거트로 묶어서 바라보면 좀 더 상위 수준에서 도메인 모델 간의 관계를 파악할 수 있다.
  • 애그리거트는 응집력을 유지하고 애그리거트간에는 느슨한 결합을 유지한다.
  • 애그리거트에 속한 객체는 유사하거나 동일한 라이프사이클을 갖는다.
  • 한 애그리거트에 속한 객체는 다른 애그리거트에 속하지 않는다.
  • 두 개 이상의 엔티티로 구성되는 애그리거트는 드물게 존재한다.(대부분 애그리거트 루트만 엔티티이다. 그 밖의 엔티티가 존재하면, 정말 그 객체가 엔티티가 맞는지 의심해봐야한다. 혹은 드물게 운영상 데이터 추적 혹은 성능상의 이유로 엔티티로 만들기도 한다.)

  • 애그리거트 루트(Aggregate root)
    애그리거트 내에 있는 엔티티 중 가장 상위의 엔티티를 애그리거트 루트로 정함.
    애그리거트 루트를 통해서만 애그리거트 내의 엔티티나 값 객체를 변경할 수 있다.(퍼사드 패턴과 유사)
    애그리거트간의 참조는 직접참조하지 않고 ID참조를 한다.(ex. Order가 Buyer를 직접 참조하지 않고 BuyerID로 참조하고 있다.)
    애그리거트는 단일 트랜잭션으로 일관성을 유지하지만 애그리거트간의 일관성이 필요하다면 도메인 이벤트를 통해 다른 애그리거트를 갱신해서 일관성을 유지한다.

4) 리포지토리(Repository)

  • 엔티티나 밸류가 요구사항에서 도출되는 도메인 모델이라면 리포지터리는 구현을 위한 도메인 모델
  • 애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의한다.
  • 애그리거트를 구하는 리포지터리 메서드는 완전한 애그리거트를 제공해야 한다.
  • 리포지터리가 완전한 애그리거트를 제공하지 않으면, 필드나 값이 올바르지 않아 애그리거트의 기능을 실행하는 도중에 NullPointerException과 같은 문제가 발생하게 된다.
  • 리포지토리는 애그리거트(루트) 단위로 존재하며 테이블 단위로 존재하는 것이 아니다.(애그리거트 1 개 당 리포지토리 1 개)

5) 도메인서비스
:여러 애그리거트가 필요한 기능

ex. 결제 금액 계산 로직

  • 상품 애그리거트: 구매하는 상품의 가격이 필요하다. 또한 상품에 따라 배송비가 추가되기도 한다.
  • 주문 애그리거트: 상품별로 구매 개수가 필요하다.
  • 할인 쿠폰 애그리거트: 쿠폰별로 지정한 할인 금액이나 비율에 따라 주문 총 금액을 할인한다. 할인 쿠폰을 조건에 따라 중복 사용할 수 있다거나 지정한 카테고리의 상품에만 적용할 수 있다는 제약 조건이 있다면 할인 계산이 복잡해진다.
  • 회원 애그리거트: 회원 등급에 따라 추가 할인이 가능하다.

이 상황에서 실제 결제 금액을 계산해야 하는 주체는 어떤 애그리거트일까?

  • 한 애그리거트에 넣기 애매한 도메인 개념을 구현하려면 애그리거트에 억지로 넣기보다는 도메인 서비스를 이용해서 도메인 개념을 명시적으로 드러내면 된다.
  • 응용 영역의 서비스가 용용 로직을 다룬다면 도메인 서비스는 도메인 로직을 다룬다.
  • 도메인 영역의 애그리거트나 밸류와 같은 다른 구성요소와 비교할 때 다른 점은 상태 없이 로직만 구현한다.
  • 서비스를 사용하는 주체는 애그리거트가 될 수도 있고 응용 서비스가 될 수도 있다.
  • 특정 기능이 응용 서비스인지 도메인 서비스인지 감을 잡기 어려울 때는 해당 로직이 애그리거트의 상태를 변경하거나 애그리거트의 상태 값을 계산하는지 검사해 보면 된다.
  • 응용 서비스와 구분을 위해 통상
응용 서비스 -  @Service 어노테이션을, 
도메인 서비스 -  @Component를 사용하기도 한다.

6) 팩토리

  • 복잡한 객체를 생성해야한다면 생성 역할만 책임지는 Factory에게 그 역할을 위임할 수 있다.
  • 도메인 객체를 생성하기 위한 기존의 클라이언트 코드가 깔끔해진다.

팩토리의 생성 위치
1. 애그리거트 루트의 정적 팩토리 메서드 - 애그리거트를 생성하기 좋은 위치
2. 도메인 서비스 - 다른 애그리거트를 이용하여 생성해야한다면 고려해보자
3. 별개의 팩토리 클래스 - 구상 구현체나 생성과정의 복잡성등을 감춰야 하는 경우(?)

Factory는 자신의 생성물과 가장 밀접한 관계에 있는 위치에 있어야 한다. (만들어내는 객체와 매우 강하게 결합돼 있으므로)

7) 도메인이벤트

  • 서비스간 정합성을 일치시키기 위해 단위 애그리거트의 주요 상태 값을 담아 전달되도록 모델링한다.
  • 이벤트의 용도는 후처리, 데이터 동기화 등
  • 도메인 이벤트를 사용하면 애그리거트간, 바운디드 컨텍스트간, 외부 서비스와의 결합을 느슨하게 한다.(도메인 로직이 섞이는 것을 방지)
  • 도메인 모델에서 이벤트 주체는 엔티티, 밸류, 도메인 서비스와 같은 도메인 객체이다.
  • 도메인 객체는 도메인 로직을 실행해서 상태가 바뀌면 관련 이벤트를 발생한다.
  • 스프링에서 제공하는 AbstractAggregateRoot를 애그리거트 루트에 확장하면 애그리거트 루트 내에서 직접 이벤트를 발생할 수 있다(기존의 ApplicationEventPublisher을 사용하면 어플리케이션 레이어에서 이벤트를 발행해야한다)
  • 이벤트 핸들러는 서비스 레이어에서 구현하면 된다.

도메인 주도 설계 아키텍쳐

기존 레이어드 아키텍처의 문제점

  • 도메인 레이어가 인프라 레이어에 의존하고 있다.
  • 이는 고수준 모듈(추상화 모듈)이 저수준 모듈(구현 모듈)에 의존하는 것이다.

여기서 의미가 있는 기능이라는 것은 무엇일까? 바로 비즈니스로직!

  • 도메인 주도 설계에서 비즈니스 로직을 담당하는 도메인 레이어가 고수준 모듈이다.

  • 나머지 저장 기능, 인증 기능 등은 비즈니스 기능에 비해 저수준 모듈이다.

  • 우리는 이 도메인 레이어를 보호해야할 필요가 있다.

  • 저수준 모듈이 고수준 모듈에 의존한다고 해서 이를 DIP(Dependency Inversion Principle, 의존 역전 원칙)라고 부른다.

  • 인프라스트럭처 영역에 의존할 때 발생했던 구현 교체가 어렵다는 문제와 테스트가 어려운 문제를 해소할 수 있다.

  • 고수준 모듈은 더 이상 저수준 모듈에 의존하지 않고 구현을 추상화한 인터페이스에 의존한다.

  • DIP를 적용할 때 하위 기능을 추상화한 인터페이스는 고수준 모듈 관점에서 도출한다.

  • 추상화한 인터페이스는 저수준 모듈이 아닌 고수준 모듈에 위치한다.

헥사고날 아키텍처와 클린 아키텍처

그러나 레이어드 아키텍처에 DIP를 적용해도 한계가 있다.

프레젠테이션 계층과 데이터 액세스 계층을 보통 저수준 계층으로 정의하는데 현대 애플리케이션은 이러한 두 가지 계층 말고도 다양한 인터페이스를 필요로 한다. 단방향 계층구조에서는 이러한 점을 지원하기 힘들다. 다방면으로 열려있는 헥사고날 아키텍처클린 아키텍처가 이런 문제점을 해결할 수 있다.


헥사고날 아키텍처

헥사고날 아키텍쳐란?

  • 사전적 의미로는 ”육각형 건축물”을 뜻함
  • 레이어 간의 원하지 않는 종속성이나 비즈니스 로직으로 인한 사용자 인터페이스 코드의 오염과 같은 객체 지향 소프트웨어 설계의 알려진 구조적 함정을 피하기 위해 Alistair Cockburn에 의해 발명
  • 포트 및 어댑터 아키텍처라고도 불림

헥사고날 아키텍처의 장점

1) 아키텍처 확장이 용이합니다.
2) SOLID 원칙을 쉽게 적용할 수 있습니다.
3) 모듈 일부를 배포하는 게 용이합니다.
4) 테스트를 위해 모듈을 가짜로 바꿀 수 있으므로 테스트가 더 안정적이고 쉽습니다.
5) 더 큰 비즈니스적 가치를 갖고 더 오래 지속되는 도메인 모델에 큰 관심을 둡니다.

헥사고날 아키텍쳐의 구성

헥사고날 아키텍처는 내부(도메인)외부(인프라)로 구분됩니다.

  • 내부 영역 - 순수한 비즈니스 로직을 표현하며 캡슐화된 영역이고 기능적 요구사항에 따라 먼저 설계
  • 외부 영역 - 내부 영역에서 기술을 분리하여 구성한 영역이고 내부 영역 설계 이후 설계

포트와 어댑터

포트는 내부 비즈니스 영역을 외부 영역에 노출한 API이고 인바운드(Inbound)/아웃바운드(Outbound) 포트로 구분됩니다.

  • 인바운드 포트 - 내부 영역 사용을 위해 노출된 API
  • 아웃바운드 포트 - 내부 영역이 외부 영역을 사용하기 위한 API

어댑터는 외부 세계와 포트 간 교환을 조정하고 역시 인바운드(Inbound)/아웃바운드(Outbound) 어댑터로 구분됩니다.

  • 인바운드 어댑터 - 외부 애플리케이션/서비스와 내부 비즈니스 영역(인바운드 포트) 간 데이터 교환을 조정
  • 아웃바운드 어댑터 - 내부 비즈니스 영역(아웃바운드 포트)과 외부 애플리케이션/서비스 간 데이터 교환을 조정

결국 이 구조의 핵심은 비즈니스 로직이 표현 로직이나 데이터 접근 로직에 의존하지 않는 것입니다.

좀 어렵게 정리가 되네요...

쉽게 정리하면 이렇게만 생각해도 괜찮을 것 같습니다.

  • 커맨드 -> REST API
  • 애그리거트 -> 도메인 모델
  • 도메인 이벤트 -> 이벤트 메시지 처리 어댑터의 처리 대상
  • 외부 시스템 -> 외부 연계 시스템(그림에선 마이크로서비스)

출처 : https://mesh.dev/20210910-dev-notes-007-hexagonal-architecture/

관련된 내용은 책<도메인 주도 설계란 무엇인가?> 에서 발취한 내용도 있음을 알려드립니다.
이 책은 DDD에 대한 내용을 에릭 에반스 분 등의 다른 DDD 선구자 분들이 다룬 내용을 요약하는 식으로 되어 있습니다.

처음 DDD를 접할 때 얇은 책이라 빨리 접하기 좋은 책인 것 같습니다.😉



출처 : https://yoonbing9.tistory.com/121
책 <도메인 주도 설계란 무엇인가> 에이벨 아브람, 플로이드 마리네스쿠

profile
배운 것을 기록합니다.

0개의 댓글