SQS 기반 알림톡 처리에서 발생한 DB 커넥션 데드락 분석기
올리브영이 SQS 기반 이벤트 구조로 알림톡 시스템을 전환했으나 30초 DB 커넥션 데드락 발생 → REQUIRES_NEW 제거 및 폴링 메시지 한도 조정으로 타임아웃 0건 달성
AI 요약
Context
기존 알림톡 발송 로직이 각 비즈니스 로직에 산재되어 있었으며, 외부 API 호출이 비즈니스 트랜잭션 내부에서 강하게 결합되어 있었다. 외부 API 지연이나 네트워크 이슈 발생 시 전체 트랜잭션이 대기 상태에 빠져 시스템 처리량이 저하되는 구조였다.
Technical Solution
- Amazon SQS 기반 이벤트 구조 도입: 비즈니스 로직에서 최소 데이터만 담아 SQS 메시지로 발행하고, Consumer 서버에서 비동기로 처리하도록 분리
- NoticeSender 공통 인터페이스 구현: 알림 발송 흐름(검증 → 템플릿 생성 → 메시지 생성 → 발송 → 저장)을 하나의 파이프라인으로 일원화하여 알림 유형별 독립 확장 가능하게 변경
- 트랜잭션 결합 해소: 비즈니스 로직의 트랜잭션을 SQS 발행 시점까지로 제한하여 알림 발송 성공 여부와 무관하게 빠르게 종료
- Amazon EventBridge를 통한 재시도 구조 도입: DB 기반 실패 이력 관리 + 주기적 재시도 API 호출로 실패 건 추적 및 개별 재처리 가능하게 구현
- DB 커넥션 풀 설정 최적화: REQUIRES_NEW 트랜잭션 전파 옵션 제거로 스레드당 필요 커넥션 수를 2개에서 1개로 감소, SQS maxNumberOfMessages를 커넥션 풀 크기 이하로 조정
Impact
Java HikariPool 타임아웃 오류(java.sql.SQLTransientConnectionException: Connection is not available, request timed out after 30008ms)가 0건으로 감소.
Key Takeaway
SQS 폴링 병렬 처리와 트랜잭션 전파 옵션이 DB 커넥션 풀 크기와 결합될 때 발생하는 데드락 임계점을 이해해야 한다. 최소 필요 커넥션 수 = Tn × (Cm - 1) + 1 공식(Tn: 동시 처리 스레드 수, Cm: 스레드당 최대 커넥션 수)을 기준으로 커넥션 풀과 폴링 메시지 개수를 함께 튜닝하는 것이 필수적이다.
실천 포인트
SQS, Kafka 등 폴링 기반 메시지 큐를 사용하는 비동기 처리 시스템에서는 @Transactional(propagation = Propagation.REQUIRES_NEW) 옵션 사용을 최소화하고, maxNumberOfMessages 또는 동등 설정값이 DB 커넥션 풀 크기(HikariCP maximumPoolSize)를 초과하지 않도록 설정해야 대규모 병렬 처리 환경에서 데드락을 피할 수 있다.