도메인이란?
[핵심] 도메인 = 주제
: 소프트웨어로 해결하고자 하는 영역
상위 도메인 (=대주제) 예시 : 쇼핑몰
하위 도메인 (=소주제) 예시 : 회원, 주문, 혜택, 카탈로그, 리뷰, 결제, 배송 *일반적으로 칭하는 도메인
외부 도메인 (=외부인용) 예시 : 외부 결제(PG), 외부 배송(물류) 등
도메인 전문가와 개발자 간 지식 공유
[핵심] 개발자는 요구사항에서 진짜 뭘 원하는지 잘 캐치해내야 함
: 개발자는 요구사항을 이해할 때 왜 이런 기능을 요구하는지, 실제로 원하는 것이 무엇인지를 도출해내야 하기때문
도메인 모델
[핵심] 스키마 디테일하고 정황하게 잘 짜라는 말 (테이블 + 멤버 + 타입 + API 등)
: 특정 도메인을 개념적으로 표현한 것
: 도메인을 이해하는데 도움이 되면 됨 (표현방식이 중요한건 X)
1. 도메인 모델 : 도메인 안에서 이루어지는 기능과 요소를 도식화
2. 다이어그램 : 도메인 안에서 이루어지는 상태변화에 대한 플로우를 도식화
* 도메인에 따라 용어 의미가 결정되며, 특정 도메인은 해당 도메인에 한정될 때 의미가 완전해지기 때문에,
각 하위 도메인마다 별도의 모델(혹은 다이어그램)을 만들어야 한다.


도메인 모델 패턴
[핵심] 아래 구성에 따르는 게 이상적인 구현
: 도메인 아키텍처 구성에 따름
* 비즈니스 계층에서 서비스 클래스는 도메인을 조합하는 구간이며,
서비스 로직 자체는 엔티티 클래스(도메인모델)안에서 메서드로 구현하거나 레포지토리의 쿼리 메서드로 구현한다.
영역 | 설명 | SpringBoot 계층 예시 |
UI 또는 표현 | 사용자의 요청을 처리하고 응답을 보여줌 여기서 사용자는 사람일 수도 있고, 외부 시스템일 수도 있음 |
컨트롤러 (API계층) |
응용(Application) | 사용자가 요청한 기능 실행 도메인 계층을 조합해서 기능 실행 |
서비스 (비즈니스 계층) |
도메인 | 도메일 모델 구현 시스템이 제공할 도메인 로직을 구현 |
레포지토리 계층 도메인 모델 = 엔티티 |
인프라 스트럭처 | DB나 메세징 시스템과 같은 외부 시스템과의 연동 처리 | JPA, 레디스 등 |

도메인 모델 도출
: 모델을 구성하는 핵심구성요소, 규칙, 기능을 찾는 과정
: 요구사항, 유스케이스, 기획서, 시용자 스토리를 기반으로 규칙 도출 및 문서화
엔티티와 밸류
[핵심] 엔티티 = 식별자 있는 클래스 | 밸류 = 식별자 없는 클래스 | Setter없이 구현 지향 (불변 타입 지키기)
1. 엔티티(Entity) : 식별자 있는 클래스.
1) equals()와 hashcode() 메서드 오버라이드
public class Account {
private String accountNumber; // 식별자
@Override
public boolean equals(Object acc) {
if(this == acc) return true;
if(acc == null) return false;
if(acc.getClass() != Account.class) return false;
Account other = (Account)acc;
if(this.accountNumber == null) return false;
return this. accountNumber.equals(other.accountNumber);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
reult = prime * result + ((accountNumber == null) ? 0 : accountNumber.hashCode());
return result;
}
}
2) 식별자 : 고유해야함.
구분
- 특정 규칙에 따라 생성
- UUID나 Nano ID와 같은 고유 식별자 생성기 사용
- 값을 직접 입력
- 일련번호 사용 (시퀀스나 DB 자동 증가 칼럼 사용)
방식1. UUID (Univercial Unique Identifier) 방식 : java.util.UUID 클래스 사용
import java.util.UUID;
...
UUID uuid = UUID.randomUUID();
System.out.println(uuid);
// b4667221-dba8-4bae-bb1e-5b9717082091 형식 출력
방식2. 식별자를 먼저 만들고 엔티티 객체를 생상하는 방법
String accountNumber = accountRepository.generateAccountNumber();
Account account = new Account(accountNumber, ...);
accountRepository.save(account);
2. 밸류(Value) : 식별자 없는 클래스. 객체타입
1) 장점1 : 개념적으로 완전한 하나의 객체를 표현
예시: Coffee라는 객체타입 = Coffee라는 하나의 밸류
public class Coffee {
private String korName;
private String engName;
private int price;
public Coffee(String korName, String engName, int price) {
this.korName = korName;
this.engName = engName;
this.price = price;
}
}
2) 장점2 : 각 밸류 타입을 위한 기능 추가 가능(메서드 추가)
public class Money {
private int value;
... 생성자.getValue()
// 더하기 기능 추가(add 메서드)
public Money add(Money money) {
return new Money(this.value + money.value); // 현재클래스의 value + 들어온 밸류객체인 Money의 value
}
// 곱하기 기능 추가(multiply 메서드)
public Money multiply(int multiplier) {
return new Money(value * multiplier);
}
}
3) 장점3 : 밸류타입을 불변(Immutable)로 구현하여, 안전한 코드를 작성할 수 있음 (= Setter를 만들면 안됨)***
* 만약 밸류가 불변 객체가 아니라면, 각 메서드 적용시마다 새로운 인스턴스를 생성하여 값을 입력해줘야함.
3. 엔티티 식별자와 밸류타입
: 엔티티의 식별자 타입을 밸류타입으로 지정하여 의미를 구체화 할 수 있다.
예시 : Order엔티티의 식별자를 단순히 String이 아닌, OrderNo라는 밸류 타입으로 지정해서 사용
public class Order {
private OrderNo id;
...
public OrderNo getId() {
return id;
}
}
4. 도메인 모델에 set메서드 넣지 않기(setter 지양)
: set메서드는 도메인의 핵심 개념이나 의도를 코드에서 사라지게 하므로 지양하는 것이 좋다.
: set메서드를 사용하면, 밸류타입의 값이 변경될 우려가 있으므로 불변 타입이라는 밸류의 장점이 사라진다.
: 따라서, set메서드를 사용하는 것 보단, 생성자를 사용해 새로운 인스턴스(객체)를 생성하는 것이 바람직하다.
도메인 용어와 유비쿼터스 언어
: 실제 서비스에 사용될 용어로 컨벤션 맞춰서 사용해라
1. 도메인 용어
: 도메인에서 사용하는 용어 ( =실제 서비스에서 사용될 용어 )
2. 유비쿼터스 언어 ( = 컨벤션 통일 )
: 전문가, 관계자, 개발자가 도메인과 관련된 공통의 언어를 만들고 이를 대화, 문서, 도메인 모델, 코드, 테스트 등 모든 곳에서 같은 용어를 사용하는 것
예시 코드1: 주문 클래스와 주문 상태를 변경해줄 메서드
public class Order {
public void changeShippingInfo(ShippingInfo new ShippingInfo) {
verifyStep10rStep2();
setShippingInfo(newShippingInfo);
}
private voi verifyStep10rStep2() {
if(state != OrderState.STEP1 && state != OrderState.STEP2)
throw new IllegalStateException("already shipped");
}
}
예시 코드1-1: 도메인 용어를 맞추지 않아 유비쿼터스 언어에 위배된 코드 (6단계의 상태)
public OrderState {
STEP1, STEP2, STEP3, STEP4, STEP5, STEP6
}
예시 코드1-2:실제 서비스에 이용할 용어(도메인 용어)로 작성한 코드 (5단계의 상태)
public enum OrderState {
PAYMENT_WAITTING, PREPARING, SHIPPED, DELIVERING, DELIVERY_COMPLETED;
}
'독서 > DDD' 카테고리의 다른 글
[DDD] Chapter 4. 리포지터리와 모델 구현 (0) | 2023.06.04 |
---|---|
[DDD] Chapter 3. 애그리거트 [3/11] (0) | 2023.01.13 |
[DDD] Chapter 2. 아키텍처 개요 [2/11] (0) | 2023.01.08 |