Published on

3. 애그리게이트 연동 학습과 실습

Authors
  • avatar
    Name
    이건창
    Twitter

Introduction

도메인 주도 설계는 크게 전략적 설계와 전술적 설계로 나뉜다. 그 중 전략적 설계를 이해하고 적용하는 방법에 대해 정리한다.

해당 글에서는 애그리게이트 연동 설계를 정리한다.

학습

언제 도메인 이벤트가 메시지 버스에서 발행되야 할까?

애그리게이트 연동에서 도메인 이벤트 발행 과정에서 트랜잭션 영역과 커밋, 롤백 여부를 구분하는 방법을 고민해야 한다. 아래처럼 극단적인 상황을 고민해야 한다.

  • 도메인 이벤트 발행 후 트랜잭션 커밋 : 트랜잭션 커밋이 실패되면 일관성이 깨진다.
  • 트랜잭션 커밋 후 도메인 이벤트 발행 : 도메인 이벤트 발행이 실패되면 일관성이 깨진다.

이런 경우를 다음 패턴으로 해결할 수 있다.

  • 아웃박스 패턴 : 상태 변경과 이벤트 발행을 동일한 트랜잭션으로 처리한다. 발행 성공하면 이벤트를 완료 표시하고 발행에 실패하면 롤백한다.
  • 사가 패턴 : 발행 단계 중 실패하면 시스템 일관성을 위해 적절한 보상 조치를 수행한다.
  • 프로세스 매니저 패턴 : 비즈니스 로직 기반 프로세스 구현한 패턴이다. 중앙 처리 장치로 프로세스 매니저는 비즈니스 시퀀스를 유지하고 다음 처리 단계를 결정한다.

아웃박스 패턴

아웃박스 패턴은 메시지 릴레이와 데이터베이스를 활용해 구현한다.

  • 데이터베이스 : 업데이트된 애그리게이트 상태와 도메인 이벤트를 동일한 트랜잭션으로 커밋한다.
  • 메시지 릴레이 : 데이터베이스에 커밋된 도메인 이벤트를 가져온다. 이벤트를 가져오는 방식은 풀 또는 푸시 방식을 사용한다.
이미지

메시지 릴레이가 풀 방식을 채택하면 데이터베이스에 지속적으로 질의한다.

사가 패턴

사가 패턴은 핵심은 트랜잭션을 애그리게이트 내 단일 인스턴스로 제한하는 것이다. 관련 이벤트를 수신하고 후속 커맨드를 발행하며 발행 단계 중 하나가 실패하면 시스템 유지를 위해 적절한 보상 조치를 수행한다.

이미지

사가 패턴은 이벤트 소싱 애그리게이트로 구현되어 수신된 이벤트와 발행된 커맨드의 전체 기록을 유지한다. 도메인 이벤트 발행은 사가 상태 전환 과정커맨드 실행 과정과 분리하며 커맨드가 안정적으로 실행될 수 있도록 관리 가능하다.

  • CommandIssuedEvent 이벤트, PublishingConfirmed, PublishingRejected 커맨드가 존재한다.
  • CommandIssuedEvent는 발행된 커맨드를 이벤트 형태로 관리한다.
  • PublishingConfirmed, PublishingRejected는 발행된 커맨드를 의미한다.
이벤트를 수행하는 경우이벤트를 롤백하는 경우
이미지이미지

커맨드 실행 로직은 도메인 이벤트가 아웃박스 패턴으로 전달하는 방식과 유사하게 패턴 자체에서 벗어나 비동기적으로 실행된다.

사가 패턴은 관련 커맨드 실행으로 두 개 트랜잭션을 원자적임을 보장하지 않는다. 그렇기에 애그리게이트 경계를 보상하기 위해 사가를 남용하지 않아야 한다.

애그리게이트 설계 원칙에서는 애그리게이트 경계 내 데이터만 강한 일관성을 가짐을 원칙으로 한다. 외부와 일관성을 유지하는 일에 몰두하지 말자.

프로세스 매니저 패턴

프로세스 관리자 패턴은 비즈니스 로직 기반 프로세스 구현하기 위해 사용한다. 여러 단계로 구성된 비즈니스를 응집한다.

프로세스 매니저 패턴예시
이미지이미지

사가 패턴과 프로세스 매니저 패턴 차이가 있는데, 사가 패턴은 암시적 인스턴스화하고 프로세스 매니저 패턴은 명시적 인스턴스화한다.

  • 암시적 인스턴스화(Implicit instantiation) : 코드에 타입이 명시되지 않고 사용자가 타입을 명시하는 방식
  • 명시적 인스턴스화(Explicit instantiation) : 코드에 타입이 명시된 방식

C++에서 사용하는 단어처럼 보인다. 개인 해석으로 사가 패턴은 모든 커맨드를 처리하고 프로세스 매니저 패턴은 의도한 비즈니스 로직만 처리한다고 생각든다.

결론

  • 아웃박스 패턴은 상태 변경과 이벤트 발행을 동일한 트랜잭션으로 처리하는 방식이다.
  • 아웃박스 패턴의 단점은 중첩되는 모든 트랜잭션을 관리할 수 없을 때 발생한다.
  • 아웃박스 패턴 단점을 해소하기 위해 사가 패턴으로 경계 간 트랜잭션을 유지하지 않고 적절한 보상 조치를 수행하는 방식으로 해결할 수 있다.
  • 사가 패턴에서 보상 조치를 수행하기 위해선 각 커맨드와 커맨드 발행 이벤트 간 아웃박스 패턴으로 관리할 필요가 있다.
  • 사가 패턴으로 다중 트랜잭션에 일관성을 보장하려고 하지 말자. 애그리게이트 내 강한 일관성 보장에 목표해야지 외부와의 일관성은 목표가 아니다.

실습

방을 예약한다면 결제 후 방을 선점하는 과정을 아웃박스 패턴, 사가 패턴, 프로세스 매니저 패턴으로 구현했다.

아웃박스 패턴

아웃박스 패턴을 고려한다면 동일한 트랜잭션에 다수 이벤트 성공 여부를 제어해야 한다.

이미지

일관성을 유지하려면 애그리게이트 간 트랜잭션으로 엮어야 하기 때문에 애그리게이트 간 결합력을 높이는 방법으로 보인다. 아웃박스 패턴의 단점은 결합력이 중첩되는 문제가 있고 관리가 어려워진다.

사가 패턴

책에서 강조한 문장은 다음과 같다.

도메인 이벤트 발행은 사가 상태 전환 과정커맨드 실행 과정과 분리하며 커맨드가 안정적으로 실행될 수 있도록 관리 가능하다.

그래서 사가 상태 전환 과정을 관리하는 RentalPublishingSaga커맨드 실행 과정을 관리하는 Rental로 분리했다.

이미지

사가 패턴에서 보상 조치는 신경써야 할 부분처럼 느껴졌다. 네트워크 오류 같은 상황에서 대응 방법도 고려 대상이다.

수신측은 성공했지만 송신측이 응답을 받지 못한다면 보상하게 될텐데, 성공한걸 다시 취소 처리할지 아지면 재시도할지 고민할 필요가 있겠다.

프로세스 매니저 패턴

프로세스 매니저 방식은 비즈니스 로직을 응집하고 성공 실패 여부로 다음 단계를 결정하도록 구현했다.

이미지
  1. 방을 예약한다.
  2. 결제를 진행한다.
  3. 방을 선점한다.
  4. 방 예약 완료한다.

만약 결제가 실패하면 예약 철회하면 된다. 마찬가지로 방 선점 실패한다면 결제를 취소하면 된다. 방 예약을 완료하지 못한다면 이전 단계를 롤백하면 된다.

보상 방식과는 다르게 프로세스 매니저에서 직접적으로 구현하며 관리하면 된다.