본문 바로가기

Spring

DDD - 이벤트의 장점, 용도 그리고 구조

포스팅은 도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지에 기반하여 작성되었습니다.

 

목차

1. 이벤트 사용 시 장점

2. 이벤트 용도

3. 이벤트 구조

 

 

이벤트 사용 시 장점


정답이 아닐수도 있지만 팀 프로젝트, 개인 프로젝트를 진행하면서 느낀 이벤트를 사용하는 이유이다.

 

이벤트를 사용하면 도메인간 의존성을 제거할 수 있다. 도메인간 의존성을 제거하면 무엇이 좋을까?

프로젝트를 분리할 때 유리하다. 예를 들어 내가 진행하는 프로젝트의 Group 모듈의 복잡도 상승 및 트래픽이 증가해 해당 모듈을 분리하기로 했다고 해보자. 만약 Group 모듈이 다른 도메인을 많이 의존하고 있다면 프로젝트를 통채로 들고가야할 수도 있을 것이다. 

 

덤으로 비동기 처리를 구현하기 용이하다.(물론 관리하는건 어렵겠지만...) 만약 Task가 A, B, C  순으로  있다고 해보자. 동기/블락킹 구조에서는 순서대로 하는 것이 법이다. A가 끝나지 않으면 블락킹이 걸려있기 때문에 B, C를 수행 할 수 없다. 비동기 처리는 A, B, C 작업의 결과를 기다리지 않아도 된다. 기다리지 않아도 되기 때문에 시간적인 측면에서 성능이 향상될 수 밖에 없다. 그렇다고 모든 로직을 비동기 처리 할 수는 없다. 전후 순서가 중요한 로직에서는 동기처리를 해야한다.

 

 

이벤트 용도


책에 따르면 이벤트는 크게 두 가지 용도로 사용된다고 합니다.

 

첫째는 트리거입니다. 도메인의 상태가 바뀔 때 다른 후처리가 필요하면 후처리를 위한 트리거로 이벤트를 사용할 수 있습니다. 예를 들어 주문을 취소하면 일반적으로 환불이 일어난다. 환불 처리를 위해 주문 취소 이벤트를 트리거로 사용할 수 있습니다.

 

둘째는 서로 다른 시스템 간의 데이터 동기화입니다. 배송지를 변경하면 외부 배송 서비스에 바뀐 배송지 정보를 전송해야 합니다. 주문 도메인은 배송지 변경 이벤트를 발생시키고 이벤트 핸들러는 외부 배송 서비스와 배송지 정보를 동기화 할 수 있습니다.

 

 

이벤트 구조


잘 모르는 입장에서 봤을 때 이벤트 구조는 옵저버 패턴, Pub/Sub 패턴과 비슷한 것 같습니다. 찾아보면 분명 차이가 존재하지만 이것들 중 하나라도 알고 있다면 이벤트 구조를 이해하는데 수월할 것 같습니다.

 

2023-06-23 내용 추가

스프링 환경에서 이벤트는 옵저버 패턴을 통해 이벤트를 처리합니다. 여기에 사용되는 것이 ApplicationListener & ApplicationEvent입니다. 스프링 공식 문서 - Standard and Custom Events 

이벤트는 이벤트 생성 주체에서 생성되고 퍼블리셔에 의해 발행되어 이벤트 핸들러에 전달되어 처리됩니다. 각 구성 요소의 역할을 알아봅시다.

 

이벤트 생성 주체

직역하는  그대로 저기 위에 보이는 빨간이벤트를 생성하는 주체를 의미합니다.

제 프로젝트에서는 컨트롤러가 이벤트 생성주체입니다.

 

참고) DDD 책에서는 이벤트 생성 주체가 엔티티, 밸류, 도메인 서비스와 같은 도메인 내 객체여야 한다고 설명합니다.

 

이벤트 생성 주체가 이벤트를 생성하는 것은 알았습니다. 위 이벤트 용도에서 설명했듯이 특정 트리거, 동기화 등이 필요할 때 사용하면 됩니다.

 

이벤트

이벤트는 발생한 이벤트에 대한 데이터를 보유하는 역할을 합니다. 

 

이벤트를 처리하는데 필요한 데이터를 담고 있으면 됩니다. 제 프로젝트에서는 통계엔티티를 업데이터하기 위해 사용자 식별자, 스터디 상품 식별자가 필요해서 두 데이터를 담은 것입니다.

 

 

이벤트 퍼블리셔

이벤트 퍼블리셔는 이벤트 생성 주체와 이벤트 핸들러를 연결해 주는 역할을 합니다.

이벤트 생성 주체는 이벤트 퍼블리셔에 이벤트를 전달합니다. 이후 이벤트 퍼블리셔는 이벤트를 처리할 수 있도록 핸들러에 이벤트를 전파합니다.

 

이벤트 퍼블리셔는 그 역할이 복잡하지만 반복적인 구조인 만큼 스프링에서 제공합니다!

ApplicationEventPublisher

 

제가 생성 주체로 설정한 컨트롤러에서 이벤트 퍼블리셔에서 publishEvent() 메서드를 통해 이벤트를 전달하고 있습니다. 

 

 

이벤트 핸들러

이벤트 핸들러는 이벤트 생성 주체가 발생한 이벤트에 반응하여 이벤트에 담긴 데이터를 이용해 기능을 실행합니다. 

 

@EventListener를 통해 이벤트를 처리하는 핸들러 메서드임을 명시해줍니다. 해당 메서드는 인자로 이벤트를 받습니다. 그리고 이벤트 데이터를 바탕으로 로직을 실행합니다. 

 

대략적으로 설명하면 이벤트에서 그룹 도메인 내부에 접근해서 사용자의 특정 스터디 상품에 대한 진행률을 계산해온 상태입니다. 

 

진행률을 바탕으로 통계 정보가 작성되는데요. 그룹 도메인 내 사용자의 스터디 상품 진행률과 통계에 기록된 진행률을 비교해서 변경사항이 있으면 반영합니다.