송금 푸시 알림 미수신을 재시도 큐로 해결
목차
문제 상황
연락처 기반 송금 기능에서 푸시 알림이 가끔 빠지는 이슈가 보고됨. 로그 까보니 푸시 발송 자체는 호출되는데 토큰 만료/네트워크 일시 단절 같은 케이스에서 그냥 한 번 던지고 끝나는 구조였음. 받는 쪽은 돈 들어왔는지 모르고 있다가 나중에 앱 켜서 알게 되는 흐름. 송금 UX에서 꽤 치명적임.
원인 정리
기존 코드는 단발성 호출. 실패 응답이 와도 리트라이 없이 그대로 종료됐음. 카테고리별로 나눠보면:
| 실패 유형 | 체감 비율 | 대응 방향 |
|---|---|---|
| 토큰 만료 | 가장 많음 | 토큰 갱신 후 재시도 |
| 일시적 네트워크 | 중간 | 백오프 후 재시도 |
| 디바이스 미등록 | 적음 | 재시도 의미 없음, 스킵 |
세 번째는 재시도해도 답이 없으니 분기가 필요했음.
해결 접근
지수 백오프 + 최대 3회 재시도로 가닥 잡음. 그래도 실패하면 미발송 큐에 적재해서 백그라운드 워커가 따로 처리하도록 분리함.
- 재시도 간격: 1초 → 3초 → 9초
- 3회 초과 시 미발송 큐로 이관, 별도 잡이 주기 처리
- 디바이스 미등록은 큐에 남기지 않고 즉시 폐기
- 결과 로그는 시도 횟수까지 같이 적재
함정
처음엔 그냥 try/catch 감싸고 루프 돌렸는데, 이러면 송금 본 트랜잭션 안에서 외부 호출 길이만큼 DB 락이 같이 길어지는 문제가 있었음. 결제 플랫폼 특성상 잔액 갱신 트랜잭션은 짧게 끊는 게 원칙이라, 본 트랜잭션 커밋 후 발송하도록 이벤트 기반으로 빼냄. 이거 안 빼고 갔으면 동시성 높을 때 락 대기로 더 큰 사고 났을 듯.
효과
배포 후 며칠 모니터링:
- 미수신 신고 거의 사라짐
- 재시도로 회수되는 비율이 첫 시도 실패 중 약 70%
- 큐에 끝까지 남는 진짜 실패는 일 단위 한자리수
회고
푸시는 "API 200 응답 = 성공"이 아니라는 걸 다시 확인함. 이커머스/송금 알림은 사용자가 실제로 봐야 의미 있는 메시지라 재시도 정책을 빡세게 잡는 게 맞다고 판단. 무한 재시도는 비용이고, 0회는 UX 사고라서 그 사이 어딘가에 선을 그어야 함. 이번엔 3회 + 큐로 잡았는데, 다음엔 단말 ack까지 추적해서 진짜 도착 여부로 성공을 정의하는 구조로 끌고 갈지 고민 중.
다음
댓글 0
첫 댓글 달아줘.