이벤트 구성 요소
- 이벤트(Event)
- 도메인 모델의 상태 변화를 나타내는 사건
- 이벤트 생성 주체(Event Creator)
- 엔티티, 밸류, 도메인 서비스 등의 도메인 객체로, 도메인 로직을 수행해서
- 상태가 변경될 때 관련 이벤트를 발생시킴.
- 이벤트 디스패처(Event Dispatcher/Publisher)
이벤트 생성 주체
가 발생시킨 이벤트를 적절한이벤트 핸들러
에게 전달하는 역할
- 이벤트의 생성과 처리를 동기 또는 비동기 방식으로 선택적으로 처리가능
- 이벤트 핸들러(Event Handler/Subscriber)
- 이벤트에 반응하여 특정 기능을 수행하는 구성요소
주문 취소됨 이벤트
를 받는 이벤트 핸들러의 경우- 주문 취소 사실을 주문자에게 SMS 으로 전달이 가능하다.
이벤트예시
- 이벤트 의 구성 요소
- 이벤트 종류
- 이벤트 발생 시간
- 추가 데이터
public class ShippingInfoChangedEvent { private String orderNumber; private long timestamp; private ShippingInfo newShippingInfo; // 생성자, getter... }
- 일반적으로 이벤트는
Changed
라는 과거시제를 사용한다.- 이벤트가 과거에 발생한 것이기 때문에 과거를 기준으로 이벤트 이름을 사용한다고 합니다
- 이벤트의 발생 주체
- 이벤트를 발생시키는 주체는
Order
애그리거트와 같은 도메인 객체이다.public class Order { public void changeShippingInfo(ShippingInfo newShippingInfo) { verifyNotYetShipped(); setShippingInfo(newShippingInfo); Events.raise(new ShippingInfoChangedEvent(number, newShippingInfo)); // 이벤트 핸들러 등록 } }
- 예를 들어 배송지 정보 변경 기능을 구현한 메소드는 다음과 같이 이벤트를 발생시킬 수 있음
- 이벤트를 발생시키는 주체는
- 이벤트 핸들러
ShippingInfoChangedEvent
를 처리하는 핸들러는 이벤트를 받아 필요한 작업을 수행합니다.public class ShippingInfoChangedHandler { @EventListener(ShippingInfoChangedEvent.class) public void handle(ShippingInfoChangedEvent evt) { shippingInfoSynchronizer.sync(evt.getOrderNumber(), evt.getNewShippingInfo()); } }
shippingInfoSynchronizer
는- 이름만 거창해 보이지 그냥 서비스를 수행의 역할을 하는 것 같다.
이벤트 핸들러 비동기 처리 방식
- @EnableAsync 설정으로 스프링의 비동기 메서드 실행 기능을 활성화 가능함.
@Async
어노테이션이 붙은 메서드를 비동기적으로 실행이 가능하다.
- 비동기 메서드는
@SpringBootApplication
@EnableAsync
public class AsyncMethodApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncMethodApplication.class, args).close();
}
@Service
public class AsyncService {
@Async
public CompletableFuture<String> processAsync() {
// 비동기로 처리할 로직
String result = doSomeHeavyLifting();
return CompletableFuture.completedFuture(result);
}
private String doSomeHeavyLifting() {
// 시간이 많이 걸리는 작업
return "작업 완료";
}
}
- AsyncService #processAsync
- 메서드는 비동기로 수행되며,
- #doSomeHeavyLifting 는 작업을 별도의 스레드에서 처리함,
CompletableFuture.completedFuture
- 작업 결과를 즉시 반환할 수 있음
- 원래 비동기라 결과를 즉시 반환하기 어려움.
void
와Future
타입만 반환가능하다.
이벤트 용도
트리거로서의 이벤트
- 도메인의 상태가 변경되는 경우
- 후처리를 작업하기 위한 트리거로서의 이벤트로 활용이 가능
- 예
- 주문 시스템에서
주문 취소 이벤트
는환불 처리를 위한 트리거
로 사용가능
- 주문 시스템에서
- 주문 취소와 환불 처리
Order
클래스에서 주문 취소 시OrderCanceledEvent
를 발생
EventDispatcher
가 이벤트를 감지하고 관련된EventHandler
에 전달합니다.
OrderCanceledEventHandler
는RefundService
를 호출하여 환불 처리를 수행합니다.
서로 다른 시스템 간의 데이터 동기화로서의 이벤트
- 배송지가 변경된 경우
- 주문 도메인
배송지 변경 이벤트 발생
- 이벤트 핸들러
외부 배송 서비스와 데이터를 동기화를 담당
한다.
- 주문 도메인
이벤트의 장점
- 개요
- 도메인 로직의 분리와 기능 확작성을 제공하는 중요한 방법론
- 서로 다른 도메인 로직이 섞이는 것을 방지.
- 시스템의 결합도를 낮출 수 있다.
도메인 로직의 분리
- 주문 취소 로직에 환불 처리 로직을 직접 포함 X
- 의존 제거
@
- 주문 취소 이벤트를 발생시켜 이벤트 핸들러가 환불 처리를 담당하도록 할 수 있음
전통적인 방식
public class Order { public void cancel(RefundService refundService) { verifyNotYetShipped(); this.state = OrderState.CANCELED; this.refundStatus = State.REFUND_STARTED; try { refundService.refund(getPaymentId()); this.refundStatus = State.REFUND_COMPLETED; } catch(Exception ex) { // 예외 처리 로직 } } }
이벤트 기반 방식
public class Order { public void cancel() { verifyNotYetShipped(); this.state = OrderState.CANCELED; Events.raise(new OrderCanceledEvent(number.getNumber())); } }
- cancel 메서드는 주문 상태를 변경하고,
OrderCanceledEvent
를 발생시키는 역할만 수행함.
- 환불 처리 로직은 이벤트 핸들러에서 담당한다.
출처
Getting Started | Creating Asynchronous Methods (spring.io)
Async (Spring Framework 6.1.3 API)
Uploaded by N2T
'도메인주도개발' 카테고리의 다른 글
이벤트 개요 (0) | 2024.01.27 |
---|---|
[DDD] 도메인 서비스 (0) | 2024.01.25 |
[DDD] 외부 시스템 연동과 도메인 서비스 (0) | 2024.01.25 |
[DDD] 오프라인 선점 잠금 (0) | 2024.01.25 |
[DDD] 오프라인 선점 잠금 관련 LockManager 인터페이스와 관련 클래스 (0) | 2024.01.25 |