코딩공작소

1. 도메인 모델이란? 본문

어플리케이션개발/DDD

1. 도메인 모델이란?

안잡아모찌 2025. 3. 27. 21:45

도메인이란 무엇일까?

소프트웨어로 해결하고자 하는 문제 영역, 그것이 도메인이다.
또한, 도메인은 여러 하위 도메인으로 구성된다.

 

애초부터 도메인을 잘 설계하기 위해서는 일단 요구사항의 정확한 이해가 필요하다.

이를 위해선, 개발자와 전문가가 직접 대화를 하며 정보의 왜곡과 손실을 방지해야 한다.

 

 

도메인 모델 : 특정 도메인을 개념적으로 표현한 것

객체 기반 주문 도메인 모델
상태 다이어그램을 이용한 주무 상태 모델링

도메인 모델은 기본적으로 무엇을 사용하든,
도메인 자체를 이해하기 위한 개념 모델이다.

구현 기술을 위해서는 구현 모델이 따로 필요하다.

객체 기반 모델을 기반으로 도메인을 표현했다면
객체 지향 언어를 이용해 개념 모델에 가깝게 구현할 수 있다.

 

 

도메인 모델 패턴

  • 인프라스트럭처 : 데이터베이스나 메시징 시스템과 같은 외부 시스템과의 연동 처리
  • 도메인 : 도메인 규칙을 구현
  • 응용 : 요청 기능 실행. 업무 로직을 직접 구현하지 않으며 도메인 계층을 조합해서 기능을 실행
  • UI / UX : 사용자의 요청 처리 및 정보 노출

도메인 모델은 아키텍처 상의 도메인 계층을 객체 지향 기법으로 구현하는 패턴이며, 도메인 계층은 도메인의 핵심 규칙을 구현한다.

결국, 도메인의 규칙들에 대한 로직들은 도메인 단에 구현하는 것이 핵심이다.

 

 

엔티티와 밸류

도출한 모델을 나타낼 때는 크게 2가지로 나누어 나타낼 수 있다.

  • 엔티티 : 고유의 식별자를 가지며, 생성하고 속성을 바꾸고 삭제할 때까지 식별자는 그대로 유지
  • 밸류 : 개념적으로 완전한 하나를 잘 표현할 수 있는 타입

 

엔티티 (식별자 생성 규칙)

  • 특정 규칙에 따라 생성
  • UUID나 Nano ID와 같은 고유 식별자 생성기 사용
  • 값을 직접 입력
  • 일련번호 사용

 

밸류

public class ShippingInfo
{

	//받는 사람
    private String receiverName;
    private String receiverPhoneNumber;
    
    //주소
    private String shippingAddress1;
    private String shippingAddress2;
    private String shippingZipcode;
    
    ...
    생성자, getter
}

받는 사람과 주소는 개념적으로 하나다.

ShippingInfo를 표현하기 위해 받는 사람과 주소를 밸류 타입으로 나타낼 수 있다.

public Receiver
{
	private String name;
    private String phoneNumber;
    
    public Receiver(String name, String phoneNumber){
    	this.name = name;
        this.phoneNumber = phoneNumber;
    }
    
    ...
    getter
}
public class Address {
	private String address1;
    private String address2;
    private String address3;
    
    public Address(String address1, String address2, String zipcode){
    	this.address1 = address1;
        this.address2 = address2;
        this.zipcode = zipcode;
    }
]

 

이 2개의 밸류 타입을 통해 ShippingInfo를 새롭게 표현할 수 있다.

public class ShippingInfo{
	private Receiver receiver;
    private Address address;
    
    ...생성자, get 메서드
}

이렇듯 꼭 두 개 이상의 데이터를 가져와야 하는 건 아니다.

 

 

의미를 명확하게 표현하기 위해 밸류 타입을 사용하는 경우도 있다.

public class OrderLine{
	private Produdct product;
    private Money price;
    private int quantity;
    private Money amounts;
    ...
}


public class Money{
	private int value;
    
    ...생성자, getValue()
    
    //일부 기능 추가
    public Money add(Money money){
    	return new Money(this.value + money.value);
    }
    
    public Money multiply(int multiplier){
    	return new Money(value * multiplier);
    }
}

Money라는 밸류 타입을 통해 돈이라는 정확한 의미를 표현할 수 있으며, add, multiply라는 기능도 그 안에 구현할 수 있다.
밸류 객체의 데이터를 변경할 때에는 기존 데이터를 변경하기보다는 변경한 데이터를 갖는 새로운 배률 객체를 생성자로 갖는 방식이 선호된다.
이렇게 불변으로 구현하게 되면 안전한 코드를 작성할 수 있게 된다.

 

 

또한, 엔티티의 식별자 자체를 밸류 타입으로 만들게 되면 의미를 더욱 명확히 할 수 있다는 특징도 있다.

 

 

도메인 모델에는 set 메서드를 넣지 않는 것이 좋다.

도메인 모델에 set 메서드를 넣으면 핵심 개념이나 의도를 코드에서 사라지게 한다.
또한, 도메인 객체가 불완전한 상태로 사용되는 것을 막으려면 생성 시점에 필요한 것을 전달해주어야 힌다.
즉, 생성자를 통해 필요한 데이터를 모두 받아야 한다.

 

Order order = new Order(orderer, lines, shippingInfo, OrderState.PREPARING);

이렇게 코딩을 하게 되면 생성자를 호출하는 시점에 필요한 데이터가 올바른지 검사할 수 있다.
불변 밸류 타입을 사용하면 자연스럽게 밸류 타입에는 set 메서드를 구현하지 않는다.

 

 

도메인 용어와 유비쿼터스 언어

도메인을 작성하다 보면 가장 중요한 것 중 하나가 용어이다.
도메인에서 사용하는 용어를 최대한 코드에 반영해야 한다.

public enum OrderState{
	PAYMENT_WAITING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED;
}

예를 들어, 각 단계를 나타낼 때 의미를 분명하게 만들어주는 용어들을 사용해야 한다.

'어플리케이션개발 > DDD' 카테고리의 다른 글

2. DDD 아키텍쳐 전반적인 개요  (1) 2025.05.19