2021. 8. 14. 17:12ㆍDDD
도메인이란?
도메인이란 소프트웨어로 해결하고자하는 문제의 영역을 말합니다.
도메인은 여러 하위 도메인들로 구성됩니다.
주문 도메인을 예를 들면, 주문 도메인 하위 도메인들로 결제, 정산, 배송, 할인, 리뷰 등이 존재합니다.
도메인 모델
도메인 모델은 특정 도메인을 개념적으로 표현한 것입니다.
표현 방식에는 필드와 메서드를 가진 객체들간의 매핑을 나타낸 객체 기반 방식이나 상태 전이의 흐름도를 나타낸 상태 다이어그램 방식 등이 있는데 도메인을 이해하기 위한 목적이라면 어떠한 방식이라도 상관 없습니다.
단, 여러 하위 도메인들로 구성된 도메인 모델을 하나의 다이어그램으로 표현하면 안되고 하위 도메인들마다 별도로 모델을 만들어야 합니다.
예를 들어서 주문 도메인 모델안에 결제, 정산, 배송, 할인, 리뷰 등의 하위 도메인들을 하나의 다이어그램으로 표현한다면, '배송'에 관한 도메인만 이해하려고 할 때 주문 도메인을 함께 조회해야해서 이해하기 어려울겁니다.
도메인 모델 아키텍처
DDD(Domain Driven Design)을 따르는 애플리케이션의 아키텍처는 다음의 네가지 계층으로 구성됩니다.
1. 표현
사용자의 요청을 받고 응용 계층에 넘기는 역할
2. 응용
사용자가 요청한 기능을 실행하는 역할
3. 도메인
시스템이 제공할 도메인 규칙을 구현
4. 인프라 스트럭처
DB같은 외부 시스템과의 연동을 처리
서론에서 말한 도메인 모델(개념 모델)은 도메인을 개념적으로 표현한 것이라고 했는데,
앞으로 나올 도메인 모델은 도메인 계층을 객체 지향, 트랜잭션, DB, 성능 등을 고려하여 코드로 구현한 핵심 규칙을 의미합니다.
따라서 개념 모델은 소프트웨어 전반과 윤곽을 이해하기 위한 목적으로 작성하고,
도메인 모델은 개발 과정에서 점진적으로 발전시켜나가면서 개발한다고 생각하면 되겠습니다.
도메인 모델은 Entity 객체와 Value 객체로 구성됩니다.
Entity 객체
엔티티 객체는 고유 식별자를 가진 도메인 구성 객체입니다.
엔티티 식별자가 같다면 같은 객체라고 판단할 수 있습니다.
필드 뿐만 아니라 엔티티의 기능을 나타내는 메서드로 구성됩니다.
엔티티 식별자를 생성하는 방법은 다음의 네가지가 존재합니다.
- 특정 비즈니스 규칙에 따라 생성
- UUID 사용
- 사용자가 직접 입력
- DB의 시퀀스나 auto_increment 사용
특정 비즈니스 규칙에 따라 생성하는 것은 운송장 번호나 카드 번호 같이 도메인 특성에 따른 환경과 규칙을 조합해서 고유 식별자를 생성하는 방법입니다.
UUID(Universally Unique Identifier)는 자바 표준에서 제공하는 방식입니다. java.util.UUID 클래스를 사용하면 생성 가능합니다.
UUID uuid = UUID.randomUUID();
String strUuid = uuid.toString();
사용자 직접 입력은 중복의 위험이 있기 때문에 추천하지 않습니다.
DB 시퀀스나 auto_increment는 사용하는 DBMS에서 제공하는 식별자 생성방식을 가져다 쓰는 방법인데 DB에 추가되고 나서야 비로소 식별자를 알 수 있다는 점을 고려해야 합니다.
Value 객체
개념적으로 완전한 하나를 표현할 때 사용하는 객체입니다.
Value 객체를 사용하면 엔티티 객체의 멤버 중에서 두 개 이상의 필드들을 하나의 Value 객체로 묶어서 표현 가능하여 코드를 간략화할 수 있습니다.
또한 int, double, String, localTime과 같은 java 표준 타입이 아닌 Value 타입으로 Entity 객체의 필드를 구성하면 코드의 가독성을 높일 수 있습니다.
class ShippingInfo{
private String receiverName;
private String receiverPhoneNumber;
private String shippingAddress1;
private String shippingAddress2;
private String shippingZipCode;
}
위의 ShippingInfo 엔티티 객체를 두개의 Value 객체를 추가한 코드 입니다.
public ShippingInfo{
private Receiver receiver;
private Address address;
}
Value 객체는 immutable(불변) 특성을 가져서 setter 메서드가 없고 Value 객체의 멤버의 값을 변경하려면, 생성자를 재호출해서 객체를 다시 생성해야합니다.
public ShippingInfo{ //Entity 객체
private Receiver receiver;
private Address address;
public void changeReceiverName(String name){
// Value 객체는 immutable!!, Value 객체 설계 원칙 위반
receiver.setName(String name); //NO
}
public void changeReceiver(Receiver newReceiver){
this.receiver = newReceiver //OK
}
}
밸류 타입을 불변으로 구현하는 가장 중요한 이유는 안전한 코드를 작성하기 위함입니다.
불변 객체는 참조 투명성(외부에 영향을 받지 않음)과 스레드에 안전(여러 스레드가 동시 실행되도 출력되는 결과는 같음)한 특징을 가집니다.
외부에서 밸류 타입 객체를 set 메서드로 변경할 수 있다면 객체를 안전하게 사용할 수 없을 겁니다.
습관적 get/set 메서드 생성의 문제점
일부 개발자들 중에 무지성으로 클래스에 getter/setter를 생성하는 버릇이 있는데, 도메인 주도 개발에선 이를 지양해야합니다.
아래와 같은 두가지 문제점이 있습니다.
- 도메인 모델의 핵심 개념이나 의도를 사라지게 합니다.
- 도메인 객체가 생성시점에 불완전한 상태일 수 있습니다.
도메인 모델은 도메인의 핵심 규칙과 기능만 존재해야하는데, set 메서드는 필드를 변경하고 끝나는 경우가 많기 때문에 도메인 설계 원칙과 맞지 않습니다.
또한 set 메서드를 사용한다는 것은 객체 생성 시점에 멤버를 초기화하지 않고 이후에도 수정할 수 있기 때문에 도메인 객체가 불완전한 상태로 사용될 수 있는 여지를 줍니다.
부득이하게 사용하게 될 경우 접근제어자를 public이 아닌 private을 사용해서 외부로부터의 접근을 막아야합니다.
Ref.
- 'DDD START! 도메인 주도 설계 구현과 핵심 개념 익히기' - 최범균
'DDD' 카테고리의 다른 글
[DDD] Chap 06 응용 영역과 표현 영역 (0) | 2021.09.21 |
---|---|
[DDD] Chap 04 리포지터리와 JPA중심 모델 구현 (0) | 2021.08.21 |
[DDD] Chap 03 Aggregate (0) | 2021.08.15 |
[DDD] Chap 02 아키텍처 개요 (0) | 2021.08.14 |