표현,응용,도메인,인프라스트럭처 는 아키텍처를 설계할 때 출현하는 전형적인 4개의 영역이다.
- 표현: 사용자의 요청 -> 응용 영역(서비스) -> 사용자 응답
- 응용: 응용 서비스는 로직을 직접 수행하기보다는 도메인 모델에 로직 수행을 위임. 밑 코드도 주문 취소 로직을 직접 구현하지 않고 Order 객체에 취소 처리를 위임하고 있다.
public class CancelOrderService {
@Transactional
public void cancelOrder(String orderId){
Order order = findOrderById(orderId);
if (order == null) throw new OrderNotFoundException(orderId);
order.cancel();
}
...
}
- 도메인: 도메인의 핵심 로직을 도메인 모델에서 구현한다. ex) 위와 같은 order의 cancle();
- 인프라스트럭처: 구현기술 관련(DB 연동, 데이터 연동, SMTP서버 연결 등등)
Domain 영역 주요 구성요소
- Entity(엔티티): 도메인 모델의 데이터를 포함하며 데이터와 관련된 로직 및 기능을 함께 제공( ex: Order-주문, Member-회원)
- Value(밸류): 개념적으로 하나의 값을 표한 할때 사용(ex: Member의 name,gender 등)
- Aggregate(애그리거트): 연관된 엔티티와 밸류 객체를 개념적으로 하나로 묶음 ( ex: 주문과 관련된 Order 엔티티, OrderLine 밸류, Orderer 밸류 객체를 '주문(Order)' 애그리거트 로 묶을 수 있다.
- Repository(리포지터리): 도메인 모델의 영속성(* 데이터를 영구적으로 저장 )을 처리. DBMS를 통해 엔티티 객체를 로딩하거나 저장하는 기능을 제공.
- Domain Service(도메인 서비스): 특정 엔티티에 속하지 않은 도메인 로직. '할인 금액 계산' 은 상품, 쿠폰,회원 등급, 구매 금액 등 다양한 조건을 이용해서 구현하게 되므로 특정 엔티티에 속할 수 없다. 도메인 로직이 여러 엔티티와 밸류를 필요로하면 도메인 서비스에 로직이 분리된다.
// 주문 도메인
public class Order {
private int orderNo; // 주문 번호
private Orderer orderer; // 주문자
private ShippingInfo shipppingInfo; // 배송지 주소
// 배송지 주소 바뀌는 도메인 기능
public void changeShippingInfo(ShippingInfo new ShippingInfo){
...
}
}
// 주문자 도메인
public class Orderer {
private String name;
private String email;
...
}
DB 테이블의 엔티티와 도메인 모델의 엔티티는 다르다. 도메인 모델의 엔티티는 단순히 데이터를 담고 있는 데이터 구조보다는 데이터와 함께 기능이 제공된다. 도메인 관점에서 기능을 구현하고 기능 구현을 캡슐화해서 데이터가 임의로 변경되는걸 막는다. 또한 도메인 모델의 엔티티는 두개 이상의 데이터가 개념적으로 하나인 경우 밸류 타입을 이용해서 표현할 수 있다. 위처럼 주문 도메인안에 여러개의 데이터를 갖고있는 주문자 도메인을 하나의 밸류 타입으로 참조하고 있다.
모듈 구성
- 도메인 모듈은 도메인에 속한 애그리거트를 기준으로 패키지를 구성한다. 예를 들어 카탈로그 하위 도메인이 상품 애그리거트와 카테고리 애그리거트로 구성될경우 밑과 같이 구성할 수 있다.
애그리거트, 모델, 리포지터리는 같은 패키지에 위치시킨다. 예를 들어 상품과 관련된 Product,Manufacturer,ProductRepository등은 com.myshop.catalog.product.domain 패키지에 위치 시킨다.
도메인이 복잡하면 도메인 모델과 도메인 서비스를 다음과 같이 별도 패키지에 위치 시킬수 있다.
- com.myshop.catalog.domain.catalog: 애그리거트 위치
- com.myshop.catalog.domain.service: 도메인 서비스 위치
응용 서비스도 다음과 같이 도메인 별로 패키지를 구분할 수 있다.
- com.myshop.catalog.application.product
- com.myshop.catalog.application.category
모듈 구조를 얼마나 세분해야하는지에 대한 정답이나 구축은 없다. 다만 너무 몰려서 찾을 때 불편한 정도만 아니면 된다. 개인적으로 한 패키지에 10~15개 미만으로 타입 개수를 유지하려고 노력하고 만약 이 수를 넘어가면 패키지를 더 나은 구조로 분리하는 시도를 해야한다.
결론
- 패키지 구조를 정할 때는 도메인 부터 분석을 하고 루트 도메인과 하위 도메인을 애그리거트로 잘 구분 지어 도메인 관점에 따라 4가지 영역(표현,응용,도메인,인프라스트럭쳐)를 잘 구분하여 구조를 결정해야겠다. 또한, 최대한 DIP를 잘 활용하여 고수준 모듈이 저수준 모듈에 의존을 하지않게 설계하는게 중요한거 같다. 절대적으로 가독성이 좋은 패키지 구조로 만들어야겠다.
reference
- 도메인 주도 개발 시작하기 by 최범균 (http://www.yes24.com/Product/Goods/108431347)
'책 > 도메인 주도 개발' 카테고리의 다른 글
[DDD] 도메인 주도 개발 시작하기 CH_5. 스프링 데이터 JPA를 이용한 조회 기능 (0) | 2023.02.18 |
---|---|
[DDD] 도메인 주도 개발 시작하기 CH_4. 리포지터리와 모델 구현 2편 (0) | 2023.02.13 |
[DDD] 도메인 주도 개발 시작하기 CH_4. 리포지터리와 모델 구현 1편 (0) | 2023.02.10 |
[DDD] 도메인 주도 개발 시작하기 CH_3.Aggregate(애그리거트) (0) | 2023.02.06 |
[DDD] 도메인 주도 개발 시작하기 CH_1. 도메인 모델 (0) | 2023.01.29 |