TransactionalEventListener 사용

Lee hunil·2025년 3월 9일

Spring Event

목록 보기
3/3

문제 상황 정리

전 포스팅에서 비동기로 실행하여 하나의 쓰레드로 실행된 프로세스를 두개의 쓰레드로 나눠서 실행하였다. 그 결과, 프로세스 소요 시간을 줄이고, 전체 트랜잭션 롤백 문제를 해결할 수 있었다. 하지만 아직 하나의 문제가 남아있다.

  • 비동기로 실행한 프로세스는 주 프로세스가 성공하든 실패하든 작동하는 문제가 발생한 것이다. 다시 말하면 주 기능인 약속방 삭제 프로세스가 성공 유무와 상관없이 알림 프로세스는 진행된다는 것이다.

@TransactionalEventListener를 사용

이러한 문제는 @TransactionalEventListener를 사용하여 해결할 수 있다.

@TransactionalEventListener 어노테이션은 트랜잭션 이벤트 리스너를 등록하는데 사용된다. 트랜잭션의 특정한 상태(커밋, 롤백)에 따라 이벤트를 처리할 수 있다. 그 특정한 상태의 옵션을 확인해 보겠다.

@TransactionalEventListener 옵션

  1. phase = TransactionPhase.AFTER_COMMIT
    default 값이며, 트랜잭션이 commit 되었을 때 이벤트를 실행한다.

  2. phase = TransactionPhase.ROLLBACK
    트랜잭션이 rollback 되었을 때 이벤트를 실행한다.

  3. phase = TransactionPhase.AFTER_COMPLETION
    트랜잭션이 completion(commit 또는 rollback) 되었을 때 이벤트를 실행한다.

  4. phase = TransactionPhase.BEFORE_COMMIT
    트랜잭션이 commit 되기 전에 이벤트를 실행한다.

출처: https://wildeveloperetrain.tistory.com/246

@TransactionalEventListener를 적용

@Component
@RequiredArgsConstructor
@Slf4j
public class NotificationEventHandler {
    private final NotificationUtils notificationUtils;

    @TransactionalEventListener(
            classes = NotificationEvent.class,
            phase = TransactionPhase.AFTER_COMMIT)
    @Async
    public void sendNotification(NotificationEvent notificationEvent) {
        notificationUtils
                .sendNotification(
                        notificationEvent.getUser(),
                        notificationEvent.getReservationId(),
                        notificationEvent.getTitleMessage(),
                        notificationEvent.getContentMessage());
    }
}
  • classes: 어떠한 Event를 처리할 것인지 명시해준다.
  • phase: TransactionalEventListner 옵션 중 어떤 것을 사용할 것인지 명시해준다.

결과
커밋이 완료된 후에 이벤트가 발행되는 것을 확인할 수 있었다. 만약 약속방 삭제 프로세스가 정상적으로 동작이 안 될 경우에는 이벤트는 발행 되지만 이벤트리스너가 실행되지 않는다. 그럼 이제 모든 기능 구현이 완료되었다.

profile
백엔드 개발자

0개의 댓글