Skip to content

Latest commit

 

History

History
138 lines (72 loc) · 5.31 KB

File metadata and controls

138 lines (72 loc) · 5.31 KB

정리

도메인 서비스는 애그리거트의 상태를 변경하거나 상태 값으르 계산한다.

도메인 서비스는 다음과 같이 도메인 영역에 위치한 도메인 로직을 표현할 때 사용한다.

  • 계산 로직 - 여러 애그리거트가 필요한 계산 로직이나 한 애그리거트에 넣기에는 다소 복잡한 계산 로직
  • 외부 시스템 연동이 필요한 도메인 로직 - 구현하기 위해 타 시스템을 사용해야 하는 도메인 로직

계산 로직과 도메인 서비스

응용 서비스가 응용 로직을 다룬다면 도메인 서비스는 도메인 로직을 다룬다.

도메인 영역의 애그리거트나 밸류와 같은 구성요소와 다른 점은 도메인 서비스는 상태 없이 로직만 구현한다.

도메인 서비스를 사용하는 주체는 애그리거트가 될 수도 있고 응용 서비스가 될 수도 있다.

애그리거트 객체에서 도메인 서비스를 사용한다면 응용 서비스가 애그리거트 객체로 도메인 서비스를 전달한다.

public class OrderService {
	private DiscountCalculationService discountCalculationService;

	@Transactional
	public OrderNo placeOrder(OrderRequest orderRequest) {
		OrderNo orderno = orderRepository.nextId();
		Order order = createOrder(orderNo, orderRequest);
		orderRepository.save(order);
		// 응용 서비스 실행 후 표현 영역에서 필요한 값 리턴
		return orderNo;
	}

	private Order createOrder(OrderNo orderNo, OrderRequest orderReq) {
		Member member =findMember(orderReq.getOrdererId());
		Order order = new Order(orderNo, orderReq.gerOrderLines(),
							orderReq.getCoupons(), createOrderer(member),
							orderReq.getShippingInfo());
		order.calculateAmounts(this.discountCalculationService, member.getGrade());
		return order;
	}
	...
}

애그리거트의 메서드를 실행할 때 도메인 서비스를 파라미터로 전달하는 것은 애그리거트가 도메인 서비스에 의존한다는 것을 의미한다.

DI와 AOP에 빠져 있으면 이 상황을 의존 주입으로 처리하고 싶어진다.

하지만 도메인 객체는 필드로 구성된 데이터와 메서드를 이용해 개념적으로 하나인 모델을 표현한다.

하지만 데이터 자체와 관련이 없는 도메인 서비스를 필드로 주입하는 것은 욕심에 불과하다.

반대로 다음과 같이 도메인 서비스 기능을 실행할 때 애그리거트를 전달하기도 한다.

public class TransgerService {

	public void transfer(Account fromAcc, Account toAcc, Money amounts) {
		fromAcc.withdraw(amounts);
		toAcc.credit(amounts);
	}
	...
}

Tips

도메인 서비스 vs 응용 서비스

  • 도메인 서비스 - 애그리거트의 상태 변경 or 애그리거트의 상태 값 계산
  • 응용 서비스 - 트랜잭션 처리 or 흐름 제어

외부 시스템 연동과 도메인 서비스

외부 시스템이나 타 도메인과의 연동 기능도 도메인 서비스가 될 수 있다.

시스템 간 연동은 HTTP API 호출로도 가능하지만 해당 도메인 입장에서는 도메인 로직으로 볼 수 있다.

따라서 도메인 서비스로 표현할 수 있는데, 이때 타 시스템과 연동한다는 관점으로 보는 것이 아니라 도메인 로직 관점에서 바라봐야 한다.

도메인 서비스의 패키지 위치

도메인 서비스는 도메인 로직을 표현하므로 다른 도메인 구성요소와 동일한 패키지에 위치한다.

스크린샷 2020-11-19 오전 12 05 52

도메인 서비스의 개수가 많거나 엔티티나 밸류와 같은 다른 구성요소와 명시적으로 구분하고 싶다면 domain 패키지 밑에

  • domain.model
  • domain.service
  • domain.repository

와 같이 하위 패키지를 구분하여 위치시켜도 된다.

도메인 서비스의 인터페이스와 클래스

도메인 서비스의 로직이 고정되어 있지 않은 경우 도메인 서비스를 인터페이스로 구현할 수 있다.

도메인 로직을 외부 시스템이나 별도 엔진을 이용해 구현할 때 인터페이스는 도메인 영역에, 구현체는 인프라스트럭쳐 영역에 위치한다.

도메인 서비스의 구현이 특정 구현 기술에 의존하거나 외부 시스템의 API를 실행한다면 도메인 서비스는 인터페이스로 추상화해야 한다.

스크린샷 2020-11-19 오전 12 09 21

느낀점

도메인 서비스와 응용 서비스의 역할이 명확하게 구분하는 것은 쉽지 않을 수도 있다.

그럴 때 도메인 서비스는 도메인 로직(애그리거트 상태 변경)을, 응용 서비스는 응용 로직(흐름 제어)을 다룬다는 점을 생각하면 될 것 같다.

외부 시스템이나 다른 애그리거트와의 교점이 생길 경우 도메인 로직 관점에서 바라보아야 도메인에 대한 표현이 풍부해진다.

도메인 서비스를 인터페이스로 만드는 것은 마치 리포지토리를 인터페이스로 만들어 인프라스트럭처 영역에서 구현하는 것과 똑같다.