Spring Boot MongoDB 트랜잭션 도입 실전 가이드
올리브영이 Spring Boot MongoDB 트랜잭션을 Replica Set 환경에서 도입하고 ApplicationEventPublisher로 이벤트 발행 타이밍 문제를 해결
AI 요약
Context
MongoDB 트랜잭션 도입 시 격리 수준과 동시성 제어에 대한 이해 부족으로 설정 오류가 발생했다. 특히 readPreference를 secondaryPreferred()로 설정했을 때 트랜잭션 커밋 전 이벤트가 발행되어 Consumer에서 Not Found Exception이 발생하는 문제가 있었다.
Technical Solution
- MongoDB 트랜잭션 지원 환경 확인: Replica Set 또는 Sharded Cluster 환경 필수, WiredTiger 스토리지 엔진 필수 구성
- Write Concern을 ACKNOWLEDGED로 설정: 최소 1개 노드 응답 확인 후 작업 완료 처리
- Read Preference를 secondaryPreferred()로 설정: Secondary 노드 우선 읽기, Primary 노드 불가 시 폴백
- MongoTransactionManager를 @Bean으로 등록: @Transactional 어노테이션이 트랜잭션을 제대로 관리하도록 설정
- ApplicationEventPublisher + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) 적용: 트랜잭션 커밋 직후에만 이벤트 발행되도록 구현
- @Async를 이벤트 리스너에 추가: 이벤트 발행 작업을 비동기로 처리하여 메인 로직 비블로킹
Impact
트랜잭션 커밋 후 이벤트 발행 보장으로 Consumer에서의 Not Found Exception 제거. 비동기 처리로 이벤트 발행이 메인 로직 응답 시간에 영향 없음.
Key Takeaway
MongoDB 트랜잭션은 Snapshot Isolation을 기반으로 Write Conflict 발생 가능성이 있으므로, 이벤트 기반 아키텍처에서는 반드시 트랜잭션 커밋 이후에 이벤트를 발행하는 타이밍 제어가 필수다. Spring의 @TransactionalEventListener를 활용하면 데이터 정합성과 시스템 안정성을 동시에 확보할 수 있다.
실천 포인트
MongoDB 트랜잭션이 적용된 Spring Boot 애플리케이션에서 데이터 변경 이벤트를 발행할 때, ApplicationEventPublisher와 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)를 조합하면 트랜잭션 커밋 완료를 보장한 후 이벤트를 발행할 수 있어 Consumer에서의 데이터 조회 실패 문제를 근본적으로 해결할 수 있다.