DevLog

엔지니어링 블로그를 한 곳에서 탐색하고, 최근 발행 흐름을 빠르게 파악할 수 있는 서비스 입니다.

Quick Links

  • Latest Feed
  • Engineering Directory

Support

  • 소개
  • 개인정보처리방침

Contribute

  • 원하는 블로그 추가 (준비 중)
  • Feedback

© 2026 DevLog Inc. All rights reserved.

본 사이트는 공개 RSS 피드를 통해 콘텐츠를 수집하며, 모든 콘텐츠의 저작권은 원저작자에게 있습니다.

Back to Feed
Read Original

Contents

Continue Reading

  • More from Flex
  • Related reads#SpringBoot
#Backend

@TransactionalEventListener는 왜 조용히 무시될까

@TransactionalEventListener는 왜 조용히 무시될까
01

Summary

이벤트가 감쪽같이 사라졌다? @TransactionalEventListener의 조용한 경고

트랜잭션 바깥에서 벌어지는 무증상 이벤트 누락 현상의 원인부터 두 가지 명쾌한 처방법까지 한 번에 정리합니다.

본 아티클은 스프링 환경에서 @TransactionalEventListener가 예상과 다르게 트랜잭션이 없는 문맥에서 동작하지 않고 이벤트를 유실하는 원인을 파헤칩니다. 일반 @EventListener 전환 시 롤백 전용(rollback-only) 표시로 인한 예외 함정을 살펴보고, 부수효과의 성격에 따라 fallbackExecution 옵션이나 명시적 트랜잭션 검사를 활용하는 구체적인 아키텍처 가이드를 제안합니다.

  • 01@TransactionalEventListener의 실제 계약은 '커밋 이후 실행'이 아니라 '활성 트랜잭션이 있을 때만 등록'하는 것입니다.
  • 02트랜잭션 없이 호출될 경우 에러나 경고 로그 없이 조용히 무시되므로 모니터링이 매우 어렵습니다.
  • 03일반 @EventListener를 쓰면 리스너 내부 실패 시 본 작업 전체가 롤백 전용 상태가 되어 UnexpectedRollbackException을 일으킵니다.
  • 04fallbackExecution = true 옵션은 트랜잭션이 없을 때 이벤트를 즉시 실행하여 가용성을 보장하지만, 실행 순서 역전 현상을 초래할 위험이 있습니다.
  • 05커밋 여부가 중요한 민감한 이벤트인 경우 TransactionSynchronizationManager를 통해 트랜잭션 부재 시 즉시 에러를 터뜨리는 방어 코드가 유효합니다.

+RECOMMENDATION

색인 생성이나 로그 기록처럼 멱등성이 보장되는 작업에는 fallbackExecution = true를 적용하되, 결제 확정이나 외부 알림 발송처럼 완벽한 커밋 상태에 의존하는 이벤트의 경우 트랜잭션 활성 여부를 명시적으로 검증하는 가드로직을 반드시 추가하세요.

The Problem

스프링 프레임워크에서 @TransactionalEventListener를 사용할 때, 활성 트랜잭션이 없는 경로(예: 운영자 콘솔)에서 이벤트가 발행되면 리스너가 예외나 로그 없이 조용히 무시되어 검색 색인이 누락되는 등의 오작동이 발생합니다.

The Solution

이벤트 발생 시 트랜잭션이 없을 때 즉시 실행하는 fallbackExecution = true 옵션을 도입하거나, 트랜잭션 의존성이 필수적인 경우에는 TransactionSynchronizationManager.isActualTransactionActive()를 활용하여 활성 트랜잭션 존재 여부를 검증하고 예외를 발생시키도록 설계했습니다.

The Result

검색 색인 갱신처럼 멱등성이 보장되는 부수효과 작업은 fallbackExecution = true 설정으로 트랜잭션 외부 호출 시에도 누락 없이 완벽히 실행되도록 처리했으며, 결과적으로 비즈니스 로직에 맞춰 가용성과 정합성을 선별적으로 확보할 수 있게 되었습니다.

Trade-off

fallbackExecution = true를 활성화할 경우 트랜잭션 외부에서 이벤트가 발행될 때 발행 즉시 동기로 실행되므로, 이벤트 발행 문장 뒤에 배치된 마무리 로직보다 리스너가 먼저 실행되어 실행 순서가 정반대로 뒤집힐 수 있습니다.

03

Key Concepts

Concept · 01

TransactionalEventListener

스프링 프레임워크에서 제공하는 이벤트 리스너로, 이벤트가 발행된 트랜잭션의 특정 페이즈(예: AFTER_COMMIT)에 동기화하여 이벤트를 처리할 수 있게 돕는 기능입니다.

  • 활성 트랜잭션이 진행 중일 때만 콜백으로 등록되어 작동합니다.
  • 트랜잭션이 없는 환경에서는 기본 설정상 이벤트를 조용히 무시하고 폐기합니다.
Concept · 02

fallbackExecution

@TransactionalEventListener 어노테이션의 속성으로, 활성 트랜잭션이 없을 때 리스너를 그냥 무시할지 아니면 즉시 실행할지 여부를 결정하는 옵션입니다.

  • true로 설정 시 트랜잭션이 없는 상태에서 이벤트가 발행되어도 누락 없이 즉시 실행됩니다.
  • 단, 트랜잭션 내부와 외부 호출 시 이벤트 리스너의 실행 순서가 달라질 수 있으므로 유의해야 합니다.
Concept · 03

TransactionSynchronizationManager

스프링의 현재 스레드에 바인딩된 트랜잭션 상태 및 동기화 리소스를 관리하고 확인할 수 있도록 지원하는 핵심 유틸리티 클래스입니다.

  • isActualTransactionActive() 메서드를 호출하여 현재 활성 트랜잭션이 존재하는지 런타임에 직접 확인합니다.
  • 필수 트랜잭션 계약을 위반한 경로에서 이벤트 발행을 원천 차단하고 즉각적인 예외를 발생시키는 데 사용됩니다.
Continue reading · same source

FlexMore from Flex

View all posts from Flex
  • 격리 안 된 테스트의 초록불은, 에이전트가 믿을 수 없습니다

    Test IsolationCI-CDDatabase Testing
    1주 전
  • 모놀리식인데, 도메인 하나만 따로 띄웁니다

    Modular MonolithHexagonal ArchitectureSpring Boot
    2주 전
  • @Scheduled 한 줄로 버티다, 트리거를 밖으로 꺼낸 이야기

    Spring BootScheduledDistributed Lock
    3주 전
  • 사람도 에이전트도, 덜 읽을수록 더 잘 고칩니다

    ModularizationAI AgentLLM Context
    1개월 전
  • 헥사고날 아키텍처, Adapter만 바꾸면 될까

    Hexagonal ArchitecturePort and AdapterMulti Cloud
    1개월 전

Related reads#SpringBoot

Explore #SpringBoot
Flex·Modular Monolith

모놀리식인데, 도메인 하나만 따로 띄웁니다

#SpringBoot2주 전
Flex

@Scheduled 한 줄로 버티다, 트리거를 밖으로 꺼낸 이야기

#SpringBoot3주 전
여기어때·WebFlux

WebFlux 전환 부하 테스트를 다시 쓴 이야기

#SpringBoot1개월 전
우아한형제들·AI-Assisted Development

기술이 없던 곳에 기술 더하기: 사내 해커톤 플랫폼 만들기

#SpringBoot2개월 전
Flex

[의존성의 방향을 따라 1/5] 버전업이 고통인 이유

#SpringBoot3개월 전

Source

Flex
Flex
Engineering Blog

Published · September 15, 2026

Topics

Spring BootTransactionalEventListenerSpring EventTransaction Management