들어가며 Spring Batch를 사용하다 보면 배치 처리 결과를 외부 시스템에 알려야 할 때가 있다. 특히 DB에 데이터가 반영된 직후 Kafka 이벤트를 발행해야 한다면, 트랜잭션 경계를 정확히 다뤄야 한다.
잘못하면 DB 반영 전에 이벤트가 발행되어 다른 컴포넌트가 잘못된 상태를 읽는 문제가 발생한다. 이 글에서는 내가 실제로 겪은 문제와 이를 @TransactionalEventListener로 해결한 방법을 정리한다.
문제 상황 Spring Batch는 청크 단위 트랜잭션을 사용한다. 일반적인 흐름은 다음과 같다.
나는 Writer 단계에서 DB에 데이터를 저장하고, 이어서 Kafka 이벤트를 발행했다. 그런데 이 시점은 아직 트랜잭션이 커밋되기 전이다.
그림으로 표현하면 이렇다: 이 경우 Kafka 이벤트를 받은 다른 컴포넌트가 곧바로 DB를 조회하면 데이터가 없는 상태가 되어버린다. 즉, 타이밍 이슈가 생긴다.
해결 방법: @TransactionalEventListener...