
트랜잭션 바깥에서 벌어지는 무증상 이벤트 누락 현상의 원인부터 두 가지 명쾌한 처방법까지 한 번에 정리합니다.
본 아티클은 스프링 환경에서 @TransactionalEventListener가 예상과 다르게 트랜잭션이 없는 문맥에서 동작하지 않고 이벤트를 유실하는 원인을 파헤칩니다. 일반 @EventListener 전환 시 롤백 전용(rollback-only) 표시로 인한 예외 함정을 살펴보고, 부수효과의 성격에 따라 fallbackExecution 옵션이나 명시적 트랜잭션 검사를 활용하는 구체적인 아키텍처 가이드를 제안합니다.
색인 생성이나 로그 기록처럼 멱등성이 보장되는 작업에는 fallbackExecution = true를 적용하되, 결제 확정이나 외부 알림 발송처럼 완벽한 커밋 상태에 의존하는 이벤트의 경우 트랜잭션 활성 여부를 명시적으로 검증하는 가드로직을 반드시 추가하세요.
스프링 프레임워크에서 @TransactionalEventListener를 사용할 때, 활성 트랜잭션이 없는 경로(예: 운영자 콘솔)에서 이벤트가 발행되면 리스너가 예외나 로그 없이 조용히 무시되어 검색 색인이 누락되는 등의 오작동이 발생합니다.
이벤트 발생 시 트랜잭션이 없을 때 즉시 실행하는 fallbackExecution = true 옵션을 도입하거나, 트랜잭션 의존성이 필수적인 경우에는 TransactionSynchronizationManager.isActualTransactionActive()를 활용하여 활성 트랜잭션 존재 여부를 검증하고 예외를 발생시키도록 설계했습니다.
검색 색인 갱신처럼 멱등성이 보장되는 부수효과 작업은 fallbackExecution = true 설정으로 트랜잭션 외부 호출 시에도 누락 없이 완벽히 실행되도록 처리했으며, 결과적으로 비즈니스 로직에 맞춰 가용성과 정합성을 선별적으로 확보할 수 있게 되었습니다.
Trade-off
fallbackExecution = true를 활성화할 경우 트랜잭션 외부에서 이벤트가 발행될 때 발행 즉시 동기로 실행되므로, 이벤트 발행 문장 뒤에 배치된 마무리 로직보다 리스너가 먼저 실행되어 실행 순서가 정반대로 뒤집힐 수 있습니다.
스프링 프레임워크에서 제공하는 이벤트 리스너로, 이벤트가 발행된 트랜잭션의 특정 페이즈(예: AFTER_COMMIT)에 동기화하여 이벤트를 처리할 수 있게 돕는 기능입니다.
@TransactionalEventListener 어노테이션의 속성으로, 활성 트랜잭션이 없을 때 리스너를 그냥 무시할지 아니면 즉시 실행할지 여부를 결정하는 옵션입니다.
스프링의 현재 스레드에 바인딩된 트랜잭션 상태 및 동기화 리소스를 관리하고 확인할 수 있도록 지원하는 핵심 유틸리티 클래스입니다.




