Skip to content

Files

Latest commit

 

History

History

ddd

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Abstract

DDD (Domain Driven Design) 은 Domain 을 중심으로 System 을 Design 하는 것이다. 보통 Event storming 을 통해 Bounded Context 들을 구성한다. Boris Diagram, SnapE 의 과정을 거쳐 MSA (Micro Service Architecture) 를 디자인 한다.

도메인 주도 설계 (DDD, Domain-Driven Design)는 소프트웨어 개발 방법론으로, 핵심 비즈니스 도메인을 이해하고 모델링하는 것의 중요성을 강조한다. 여기서 비즈니스 도메인이란 소프트웨어가 다루고자 하는 주제 영역 또는 문제 범위를 말한다. DDD는 공통 언어, 모델, 패턴을 활용하여 실제 도메인의 필요 사항, 개념, 규칙을 정확하게 반영하는 소프트웨어를 만드는 데 초점을 맞춘다.

DDD는 도메인 전문가(비즈니스 이해 관계자와 같은)와 소프트웨어 개발자 간의 긴밀한 협력이 필요하며, 이를 통해 도메인 지식이 소프트웨어 설계에 효과적으로 반영되도록 한다. DDD의 주요 측면은 다음과 같다.

  • 유비쿼터스 언어(Ubiquitous Language): 도메인 전문가와 개발자가 도메인 개념, 규칙, 프로세스를 설명하는 데 사용하는 공유되고 일관된 언어. 이 언어는 오해를 방지하고 팀원 간의 의사소통을 개선하는 데 도움이 된다.
  • 유한한 경계(Bounded Context): 도메인의 특정한 부분을 캡슐화하는 논리적인 경계로, 다른 부분들로부터 분리하고 집중, 복잡성 저하 및 경계 범위 안의 일관성을 보장한다. 유한한 경계는 다른 팀이나 응용 프로그램의 부분이 독립적으로 발전할 수 있게 한다.
  • 엔티티, 값 객체, 그리고 집합체: 도메인 모델을 만들기 위한 구성 요소들이다. 엔티티는 독특한 신원을 가진 객체들 (예: 고객, 제품)이며, 값 객체는 불변하고 속성들에 의해서만 정의된다 (예: 색, 가격). 집합체는 관련된 객체들의 묶음으로 하나의 루트 엔티티가 상호 작용의 진입점 역할을 한다.
  • 리포지토리와 팩토리: 리포지토리는 엔티티와 집합체의 인스턴스를 저장, 검색, 관리하는 데 사용되며, 데이터 지속성 세부 정보를 추상화해준다. 팩토리는 복잡한 도메인 객체나 집합체를 생성하고 객체 인스턴스화 로직을 캡슐화한다.
  • 도메인 이벤트: 도메인 상태의 변화 또는 비즈니스 프로세스의 중요한 발생을 나타내는 이벤트로, 시스템의 다른 부분에서 작업이나 부작용을 실행할 수 있다.

도메인 주도 설계는 도메인에 대한 명확한 이해와 정확한 표현이 매우 중요한 복잡하고 변화하는 소프트웨어 시스템에 특히 유용하다. 도메인에 대한 깊은 이해를 바탕으로 팀원 간의 효과적인 의사 소통을 촉진하고, 잘 정의된 모델과 패턴을 활용함으로써 유지 관리가 쉬운, 유연하고, 비즈니스 중심적인 소프트웨어 솔루션을 만들 수 있다.

References

Materials

Basic

Terms

Term Description
Domain 해결하고자 하는 문제영역
Domain Model Domain 을 개념적으로 표현한 것. 주로 UML (Class, Activity, Sequence Diagram) 로 표현한다.

DDD Tutorial

  • [Requirement] 요구사항을 파악한다. 파악한 것을 그림 및 글로 정리한다. 개념모델을 구현모델로 바꾸어 간다.
    • 도메인 규칙을 글로정리해본다. Access pattern 도 정리한다.
    • 도메인 용어 사전을 작성하여 기획자와 sync-up 한다.
    • Context Map 을 그려본다. 하나의 Bounded Context 는 여러 Aggregate 으로 구성된다.
    • 하나의 Aggregate 는 여러 Domain Model 즉 Entity, Value 로 구성된다. Entity, Value 는 Class 로 구현한다. Aggregate 는 하나의 Aggregate Root 즉 Root Entity 를 갖는다.
  • [Design] Layered Architecture 를 참고하여 설계한다.
    • Class Diagram 을 작성한다. Class 별로 Field, Method, Relation 을 정리한다.
    • Activity Diagram, Sequence Diagram 을 작성한다.
  • [Development] 구현한다.
    • Entity, Value 를 Class 로 구현한다.
    • JPA 를 사용한다면 Entity 는 Interface, Class 로 구현한다. Interface 는 Domain Layer 에 @Entity Class 는 Infrastructure Layer 에 구현한다.
  • [Validation] 통합테스트 및 디버깅한다.

Layered Architecture


Layer Description
Presentation User 에 보여지는 화면 또는 데이터를 구현한다.
Application User 가 원하는 기능을 Domain layer 를 조합하여 구현한다.
Domain Domain model 을 구현한다.
Infrastructure RDBMS, MQ 와 같은 외부시스템 연동을 구현한다.

Domain Layer

Domain Layer 는 Entity, Value, Aggregate, Repository, Domain Service 로 구성된다. Aggregate 가 명사로 쓰일 때는 애그리거트라고 발음한다. 동사로 쓰일때는 애그리게이트이다.

Component Description
Entity 식별자를 갖는 Domain Model 이다. 자신의 라이프사이클을 갖는다. 예를 들어 Order, Member, Product 등이 해당된다.
Value 식별자를 갖지 않는 Domain Model 이다. 주로 Entity 의 속성이다. 예를 들어 Address, Money 가 해당된다.
Aggregate 관련된 Entity, Value 객체를 개념적으로 하나로 묶은 것이다. 예를 들어, 주문 Aggregate 은 Order Entity, OrderLine Value, Orderer Value 를 포함한다.
Repository Domain Model 의 영속성을 제공한다. 예를 들어 DBMS 테이블의 CRUD 를 제공한다.
Domain Service Domain Logic 을 제공한다. 예를 들어 "할인 금액 계산" Domain Service 는 상품, 쿠폰, 회원등급, 구매 금액등 다양한 조건을 이용해서 할인된 금액을 계산한다.

DIP (Dependency Inversion Principle)

Aggregate

Aggregate 는 복잡한 Domain Model 들을 하나로 묶은 것이다. Aggregate 는 여러 Entity, Value 들로 구성된다. 하나의 Aggregate 는 하나의 Repositoty 에 대응된다.

먼저 다음과 같이 대략의 Domain Model 들을 그려본다.

그리고 상위 Domain Model 들을 하위 Domain Model 들로 나누어 본다.

하위 Domain Model 들을 다시 Aggregate 로 묶어 본다. 복잡한 Domain Model 들을 수월하게 파악할 수 있다.

Aggregate Root 는 Aggregate 의 대표 Domain Model 즉 대표 Entity 를 말한다. Aggregate 의 모든 Domain Model 은 직접 혹은 간접적으로 Aggregate Root 와 연관되어 있다. Aggregate 의 상태를 변경하고 싶다면 Aggregate Root 를 통해서 한다. 예를 들어 다음의 그림과 같이 주문 Aggregate 에서 Aggregate Root 는 Order Entity 이다.

하나의 Aggregate 에서 다른 Aggregate 를 참조할 때는 Aggregate Root 를 참조한다. 예를 들어 Order Aggregate 의 Orderer Entity 는 Member Aggregate 의 Member Entity 를 참조한다.

Bounded Context

Bounded Context 는 Domain Model 의 경계가 되는 문맥을 말한다. 예를 들어 Ctalogue Bounded Context 의 Product 와 Instock (재고) Bounded Context 의 Product 는 의미가 다르다.

하나의 Context 는 여러 Aggregate 로 구성된다. 하나의 Context 가 곧 하나의 micro service 가 될 수 있다. Bounded Context 들 끼리 ACL (Anti Coruption Layer), OHS (Open Host Service) 로 연결된다. 다음과 같이 Bounded Context 의 관계를 그림으로 표현한 것을 Context Map 이라고 한다. Bounded Context 는 대표 Aggregate 와 함께 표기한다.

ACL, OHS 는 Shared Kernel 로 연결된다. Shared Kernel 은 Google ProtoBuf, FlatBuffer, OpenAPI 등을 사용하여 구현한다.

CQRS (Command Query Responsibility Segregation)

하나의 Bounded Context 를 구현할 때 상태를 변경하는 것 (Command) 과 상태를 읽어오는 것 (Query) 을 나누어서 구현하는 방법이다.

Command 와 Query 는 다른 기술로 구현할 수도 있다. 예를 들어 다음의 그림과 같이 Command 는 DDD (Domain Driven Design) 의 Layered Architecture 로 구현하고 Query 는 Netty, MyBatis 를 포함한 DAO 로 단순하게 구현한다.

Event

Asynchronous Event 를 사용하면 System 을 Decoupling 시킬 수 있다.

예를 들어 A 라는 microservice 에서 B 라는 microservice 에게 HTTP Request 를 보낼 때를 생각해 보자. B 가 HTTP Response 를 늦게 보내줄때 A micro service 는 Blocking 되어서는 안된다. A micro service 는 상태를 변경해 놓고 비동기로 처리한다.

SAGAS


여러 하위 트랜잭션 집합으로 구성된 LLT (Long Lived Transaction) 을 SAGAS 라고 한다. 다음과 같은 특징이 있다.

  • 하위 트랜잭션들은 각각 단독 트랜잭션이다.
  • 각 하위 트랜잭션들은 서로 연관되어 있다.
  • 임의의 하위 트랜잭션이 실패하면 보상 트랜잭션을 실행한다.
  • 일부만 성공한 것은 LLT 의 성공을 의미하지 않는다.

Advanced

Event Storming


  • Orange Sticker : Domain Event, something that happended.

    • Item Added to Cart
  • Blue Sticker : Command, Request to trigger, source of domain devent.

    • Item Add to Cart
  • Yellow Sticker : Aggregate, Object which has several attributes

    @entity
    public class Item {
      private String sku;
      private String name;
      private Int quantity;
      private ProductId productId;
    }
  • Red sticker : External system

Boris Diagram

Aggreate 들 간에 synchronous, asynchronous event 들을 표기한다.

SnapE

Aggregate 는 하나의 Micro Service 에 대응된다. API, Data, Stories, Risk, UI 를 기술한다.