[DDD] 아키텍처 개요 -3

2025. 4. 24. 00:59·📚 개발자의 서재/도메인 주도 개발 시작하기
해당 포스팅은 최범균 작가님의  도메인 주도 개발 시작하기 (P. 80~89)를 읽고 정리한 글입니다.

 

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

도메인 영역의 모델은 도메인의 주요 개념을 표현하며 핵심 로직을 구현한다. 도메인은 아래 표에 나와 있는 것처럼 여러 구성 요소로 이루어져 있다.

요소 설명
엔티티
(ENTITY)
고유 식별자를 갖는 객체로 자신의 라이프 사이클을 갖는다. 도메인의 고유한 개념을 표현하며, 도메인 모델의 데이터를 포함하며 해당 데이터와 관련된 기능을 제공한다.
밸류
(VALUE)
고유의 식별자를 갖지 않는 객체로 주로 개념적으로 하나인 값을 표현할 때 사용된다. 엔티티의 속성으로 사용할 뿐만 아니라 다른 밸류 타입의 속성으로도 사용할 수 있다.
애그리거트
(AGGREGATE)
연관된 엔티티와 밸류 객체를 개념적으로 하나로 묶은 것이다.
리포지터리
(REPOSITORY)
도메인의 영속성을 처리한다.
도메인 서비스
(DOMAIN SERVICE)
특정 엔티티가 속하지 않은 도메인 로직을 제공한다. '할인 금액 계산'은 상품, 쿠폰, 회원 등급, 구매 금액 등 다양한 조건을 이용해서 구현하게 되는데, 이렇게 도메인 로직이 여러 엔티티와 밸류를 필요로 하면 도메인 서비스에서 로직을 구현한다.

 


엔티티와 밸류

실제 도메인 모델의 엔티티와 DB 관계형 모델의 엔티티는 서로 다르다. 이 두모델의 가장 큰 차이점은 도메인 모델의 엔티티는 데이터와 함께 도메인 기능을 함께 제공한다는 점이다. 도메인 모델의 엔티티는 단순히 데이터를 담고 있는 데이터 구조라기보다는 데이터와 함께 기능을 제공하는 객체이다.

public class Order{
	// 주문 도메인 모델의 데이터
    private OrderNo number;
    private Orderer orderer; 
    private ShippingInfo shippingInfo; 
    
    // 도메인 모델 엔티티는 도메인 기능도 함께 제공
    public void changeShippingInfo(ShippingInfo new ShippingInfo){
    	...
    }
}

 

또 다른 차이점은 도메인 모델의 엔티티는 두 개 이상의 데이터가 개념적으로 하나인 경우 밸류 타입을 이용해서 표현할 수 있다는 것이다. 관계형 데이터베이스는 밸류 타입을 제대로 표현하기 힘들다. Order 객체의 데이터를 저장하기 위한 테이블은 Orderer의 개별 데이터를 저장하거나 별도 테이블로 분리해서 저장해야 한다.

 

밸류는 불변으로 구현할 것을 권장하며, 이는 엔티티의 밸류 타입데이터를 변경할 때는 객체 자체를 완전히 교체한다는 것을 의미한다. 밸류를 불변객체로 사용하게 되면 참조 투명성(동일한 입력값에 대해 항상 동일한 결과를 반환)와 스레드 안정성을 가질 수 있다.


애그리거트

도메인이 커질수록 개발할 도메인 모델도 커지면서 많은 엔티티와 밸류가 출현하게 되고 모델의 복잡성도 높아지게 된다. 하지만 개별 요소에만 초점을 맞추다 보면, 큰 수준에서 모델을 이해하지 못해 큰 틀에서 모델을 관리할 수 없는 상황에 빠질 수 있다. 

 

개별 객체뿐만 아니라 상위 수준에서 모델을 볼 수 있어야 전체 모델의 관계와 개별 모델을 이애하는 데 도움이 된다. 도메인 모델에서 전체 구조를 이해하는 데 도움이 되는 것이 바로 애그리거트다. 애그리거트는 관련 객체를 하나로 묶은 군집이다.

 

애그리거트를 사용하면 개별 객체가 아닌 관련 객체를 묶어서 객체 군집 단위로 모델을 바라볼 수 있게 된다. 애그리거트 간의 관계로 도메인 모델을 이해하고 구현하게 되며, 이를 통해 큰 틀에서 도메인 모델을 관리할 수 있다.

 

애그리거트는 군집에 속한 객체를 관리하는 루트 엔티티를 갖는다. 루트 엔티티는 애그리거트에 속해 있는 엔티티와 밸류 객체를 이용해서 애그리거트가 구현해야 할 기능을 제공한다. 애그리거트 루트가 제공하는 기능을 실행하고 애그리거트 루트를 통해서 간접적으로 애그리거트 내의 다른 엔티티나 밸류 객체에 접근한다. 이는 애그리거트의 내부 구현을 숨겨서 애그리거트 단위로 구현을 캡슐화할 수 있도록 돕는다.

 

애그리거트를 구현할 때는 고려할 것이 많다. 애그리거트를 어떻게 구성했느냐에 따라 구현이 복잡해지기도 하고, 트랜잭션 범위가 달라지기도 한다. 또한 선택한 구현 기술에 따라 애그리거트 구현에 제약이 생기기도 한다.


리포지터리

도메인 객체를 지속적으로 사용하려면 RDBMS, NoSQL, 로컬 파일과 같은 물리적인 저장소에 도메인 객체를 보관해야 한다. 이를 위한 도메인 모델이 리포지터리이다. 엔티티나 밸류가 요구사항에서 도출되는 도메인 모델이라면 리포지터리는 구현을 위한 도메인 모델이다. 리포지터리는 애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의한다.


DDD를 어렴풋이 이해했을 때는 '애그리거트'라는 용어만 외우고, 그것이 군집을 이루며 루트 엔티티를 통해 도메인에 접근한다는 개념만 알고 있었다. 그러나 그 이유에 대한 의문은 해소하지 못했었다. 이번 내용을 정리하면서 '캡슐화'라는 핵심 개념을 깨닫게 되었고, 앞으로는 도메인 주도 설계를 할 때 단순히 엔티티와 밸류 객체만을 구분하는 것이 아니라, 애그리거트 단위로 더 넓은 관점에서 설계하려고 한다.
저작자표시 비영리 변경금지

'📚 개발자의 서재 > 도메인 주도 개발 시작하기' 카테고리의 다른 글

[DDD] 아키텍처 개요 -5  (0) 2025.04.25
[DDD] 아키텍처 개요 -4  (0) 2025.04.24
[DDD] 아키텍처 개요 -2  (0) 2025.04.22
[DDD] 아키텍처 개요 -1  (0) 2025.04.21
[DDD] 도메인 모델 시작하기 -5  (0) 2025.04.20
'📚 개발자의 서재/도메인 주도 개발 시작하기' 카테고리의 다른 글
  • [DDD] 아키텍처 개요 -5
  • [DDD] 아키텍처 개요 -4
  • [DDD] 아키텍처 개요 -2
  • [DDD] 아키텍처 개요 -1
l'avenirJun
l'avenirJun
  • l'avenirJun
    오늘도 꾸준히 개발
    l'avenirJun
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • 📚 개발자의 서재 N
        • 객체지향의 사실과 오해
        • Good Code, Bad Code
        • 도메인 주도 개발 시작하기 N
      • 🔧 트러블 슈팅
      • Java
      • Spring
      • 운영체제
        • 공룡책 학습
      • 알고리즘
      • GIT
      • 면접 지식
      • Spring 단기심화 2기
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    인터페이스
    good code bad code
    코드트리
    일반화
    추상화
    매핑 구현
    타입
    도메인 모델
    책임
    DIP
    모듈화
    협력
    메시지
    코딩트리조별과제
    코딩테스트
    역할
    specification
    코드 계약
    객체
    캡슐화
    가독성
    리포지터리
    티스토리챌린지
    객체지향의 사실과 오해
    도메인 주도 개발 시작하기
    오블완
    책임-주도 설계
    유스케이스
    애그리거트
    애그리거트 루트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
l'avenirJun
[DDD] 아키텍처 개요 -3
상단으로

티스토리툴바