티스토리 뷰
'도메인 주도 개발 시작하기'와 '도메인 주도 설계'를 정리한 글입니다.
도메인
- 소프트웨어로 해결하고자 하는 문제 영역
- ex
- 카탈로그 : 고객에게 구매할 수 있는 상품 목록 제공
- 주문 : 고객의 주문 처리
- 혜택 : 쿠폰이나 특별 할인 같은 서비스 제공
- 배송 : 고객에게 구매한 상품을 전달하는 일련의 처리 과정
- ex
- 하나의 하위 도메인은 다른 하위 도메인과 연동하여 완전한 기능을 제공한다.
- ex. 고객이 물건을 구매한다 → 주문, 결제, 배송, 혜택 기능이 엮인다.
도메인 모델
- 특정 도메인을 개념적으로 표현한 것
- 도메인 모델은 목적을 위해 현실 세계에 존재하는 것을 가공하고 편집하여 우리에게 정보를 제공한다.
- 특정 다이어그램이 아니라 다이어그램으로 전달하려는 아이디어이자 목적을 가진 의사소통 수단
- 이 의사소통 수단은 회의, 기획, 디자인, 개발에 사용되어야 한다.
도메인 영역 내 구성요소
엔티티(Entity)
- 고유의 식별자를 갖는 객체
- 엔티티는 자신의 생명주기를 갖는다.
- 생명주기 동안 형태와 내용이 바뀔 수도 있지만 연속성은 유지해야 한다.
- 도메인 모델의 데이터를 포함하며, 해당 데이터와 관련된 기능을 제공한다.
- 한 객체가 속성보다는 식별성으로 구분될 경우 모델 내에서 이를 해당 객체의 주된 정의로 삼아라.
- 클래스 정의를 단순하게 하고 생명주기의 연속성과 식별성에 집중하라.
- 객체의 형태나 이력에 관계없이 각 객체를 구별하는 수단을 정의하라.
- 객체의 속성으로 객체의 일치 여부를 판단하는 요구사항에 주의하라.
- 각 객체에 대해 유일한 결과를 반환하는 연산을 정의하라.
- 모델은 동일하다는 것이 무슨 의미인지 정의해야 한다.
- DB 모델의 엔티티 ≠ 도메인 모델의 엔티티
- 차이점
- 도메인 모델의 엔티티는 데이터와 함께 도메인 기능을 함께 제공한다.
- 예) 주문 엔티티 : 주문과 관련된 데이터 뿐만 아니라 배송지 주소 변경을 위한 기능을 함께 제공한다.
- 도메인 모델의 엔티티는 두 개 이상의 데이터가 개념적으로 하나인 경우 값 객체 타입을 이용해서 표현할 수 있다.
- 도메인 모델의 엔티티는 데이터와 함께 도메인 기능을 함께 제공한다.
- 차이점
public class Order {
// 주문 도메인 모델의 데이터
private OrderNo number;
private Orderer orderer;
private ShippingInfo shippingInfo;
// 도메인 모델 엔티티는 도메인 기능도 함께 제공
public void changeShippingInfo(ShippingInfo newShippingInfo) {
checkShippingInfoChangeable();
setShippingInfo(newShippingInfo);
}
private void setShippingInfo(ShippingInfo newShippingInfo) {
if (newShippingInfo == null) throw new IllegalArgumentException();
// 밸류 타입의 데이터를 변경할 때는 새로운 객체로 교체한다.
this.shippingInfo = newShippingInfo;
}
}
값 객체(Value Object)
- 고유의 식별자를 갖지 않는 객체
- 주로 개념적으로 하나의 값을 표현할 때 사용된다.
- 엔티티의 속성으로 사용할 뿐만 아니라 다른 값 객체 타입의 속성으로도 사용할 수 있다.
public class ShippingInfo {
private Address address;
private String message;
private Receiver receiver;
}
- 모델에 포함된 어떤 요소의 속성에만 관심이 있다면 그것을 VALUE OBJECT로 분류하라.
- VALUE OBJECT에서 해당 VALUE OBJECT가 전하는 속성의 의미를 표현하게 하고 관련 기능을 부여하라.
- 또한 VALUE OBJECT는 불변적(immutable)으로 다뤄라.
- VALUE OBJECT에는 아무런 식별성도 부여하지 말고 ENTITY를 유지하는 데 필요한 설계상의 복잡성을 피하라.
애그리거트(Aggregate)
- 연관된 엔티티와 값 객체를 개념적으로 하나로 묶은 것
- 일관성을 관리하는 기준이 된다.
- 애그리거트는 군집에 속한 객체를 관리하는 루트 엔티티를 갖는다.
- 루트 엔티티 : 애그리거트에 속해 있는 엔티티와 값 객체를 이용해서 애그리거트가 구현해야 할 기능을 제공한다.
- 애그리거트를 사용하는 코드는 애그리거트 루트가 제공하는 기능을 실행하고 애그리거트 루트를 통해서 간접적으로 애그리거트 내의 다른 엔티티나 값 객체에 접근한다. → 애그리거트의 내부 구현을 숨겨서 애그리거트 단위로 구현을 캡슐화할 수 있도록 돕는다.
- 애그리거트에 속한 객체는 유사하거나 동일한 라이프 사이클을 갖는다.
- ENTITY와 VALUE OBJECT를 AGGREGATE로 모으고 각각에 대해 경계를 정의하라.
- 한 ENTITY를 골라 AGGREGATE의 루트로 만들고 AGGREGATE 경계 내부의 객체에 대해서는 루트를 거쳐 접근할 수 있게 하라.
- AGGREGATE 밖의 객체는 루트만 참조할 수 있게 하라.
- 내부 구성요소에 대한 일시적인 참조는 단일 연산에서만 사용할 목적에 한해 외부로 전달될 수 있다.
- 루트를 경유하지 않고는 AGGREGATE의 내부를 변경할 수 없다.
- 이런 식으로 AGGREGATE의 각 요소를 배치하면 AGGREGATE 안의 객체와 전체로서의 AGGREGATE의 상태를 변경할 때 모든 불변식을 효과적으로 이행할 수 있다.
도메인 서비스(Service)
- 특정 엔티티에 속하지 않은 도메인 로직을 제공
- 도메인 로직이 여러 엔티티와 밸류를 필요로 하면 도메인 서비스에서 로직을 구현한다.
- ex. 계산 로직 : 여러 애그리거트가 필요한 계산 로직이나, 한 애그리거트에 넣기에는 다소 복잡한 계산 로직
- 할인 금액 계산 → 상품, 쿠폰, 회원 등급, 구매 금액 등 다양한 조건을 이용해 구현한다.
- ex. 외부 시스템 연동이 필요한 도메인 로직 : 구현하기 위해 타 시스템을 사용해야 하는 도메인 로직
- 도메인의 중대한 프로세스나 변환 과정이 ENTITY와 VALUE OBJECT의 고유한 책임이 아니라면 연산을 SERVICE로 선언되는 독립 인터페이스로 모델에 추가하라.
- 모델의 언어라는 측면에서 인터페이스를 정의하고 연산의 이름을 UBIQUITOUS LANGUAGE의 일부가 되게끔 구성하라.
- SERVICE는 상태를 갖지 않게 만들어라.
리포지터리(Repository)
- 도메인 모델의 영속성을 처리한다.
- 리포지터리는 애그리거트 단위로 도메인 객체를 저장하고 조회하는 기능을 정의한다.
public interface OrderRepository {
Order findByNumber(OrderNumber number);
void save(Order order);
void delete(Order order);
}
참고자료
- 도메인 주도 개발 시작하기(https://product.kyobobook.co.kr/detail/S000001810495)
- 도메인 주도 설계 (https://www.yes24.com/product/goods/5312881)
- Total
- Today
- Yesterday
- tcp커넥션
- 문자집합변경
- jpa 쿼리 로그
- AOP
- utf8mb3
- 이모지입력오류
- github actions 구성요소
- 엔티티와값객체
- 4Way Handshake
- 쿼리 파라미터 바인딩
- 콜레이션
- file
- TCP연결
- opencsv
- spring boot3 쿼리 로그
- csv to bean
- 코프링
- mysql 이모지
- read timeout
- hibernate 쿼리 로그
- csv 라이브러리
- github actions components
- spring retry
- github actions 기초
- http커넥션
- online ddl
- CGLIB프록시
- 콜레이션변경
- 도메인구성요소
- mysql 온라인 ddl
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |