# 트랜잭셔널 아웃박스 패턴

  • 분산 시스템에서 단일 작업에 DB 쓰기 작업과 메시지 혹은 이벤트 발행이 모두 포함된 경우 발생하는 이중 쓰기 문제를 해결하기 위한 방법
@Transacational
public void sendNotification() {
    Notification noti = new Notification("댓글 알림");
    notificationRepository.save(noti);
    eventPublisher.publish(new NotificationEvent(noti.getId()));
}
  • 이런식으로 구현하면 트랜잭션은 커밋됐지만 이벤트 발행은 실패 / 이벤트 발행은 성공했지만 트랜잭션 커밋 실패하여 롤백 될 수 있음
  • 이러면 재시도를 통해 데이터가 이중으로 쓰여질 수 있어 데이터 정합성에 문제가 생기거나 서비스 장애로 이어질 수 있음

# 트랜잭셔널 아웃박스 패턴 사용

@Transacational
public void sendNotification() {
    Notification noti = new Notification("댓글 알림");
    notificationRepository.save(noti);
    notificationOutboxRepository.save(new NotificationEvent(noti.getId()));
}
  • 이런식으로 Notification 발행 이벤트를 저장하기 위한 Outbox 테이블을 따로 만들고 트랜잭션 내부에서 이벤트 저장
  • 이로써 알림과 알림 이벤트는 모두 저장되거나, 모두 저장에 실패 → 원자성 보장
  • 그리고 별도의 프로세스가 Outbox 테이블을 주기적으로 폴링하여 외부 시스템에 성공할 때까지 이벤트 발행
  • 이를 트랜잭셔널 메시징(Transactional Messaging)이라 하고 트랜잭셔널 아웃박스 패턴(Transactional Outbox Pattern)을 사용한 구현임