개발 slecs

송금 푸시 알림 미수신을 재시도 큐로 해결

목차

문제 상황

연락처 기반 송금 기능에서 푸시 알림이 가끔 빠지는 이슈가 보고됨. 로그 까보니 푸시 발송 자체는 호출되는데 토큰 만료/네트워크 일시 단절 같은 케이스에서 그냥 한 번 던지고 끝나는 구조였음. 받는 쪽은 돈 들어왔는지 모르고 있다가 나중에 앱 켜서 알게 되는 흐름. 송금 UX에서 꽤 치명적임.

원인 정리

기존 코드는 단발성 호출. 실패 응답이 와도 리트라이 없이 그대로 종료됐음. 카테고리별로 나눠보면:

실패 유형 체감 비율 대응 방향
토큰 만료 가장 많음 토큰 갱신 후 재시도
일시적 네트워크 중간 백오프 후 재시도
디바이스 미등록 적음 재시도 의미 없음, 스킵

세 번째는 재시도해도 답이 없으니 분기가 필요했음.

해결 접근

지수 백오프 + 최대 3회 재시도로 가닥 잡음. 그래도 실패하면 미발송 큐에 적재해서 백그라운드 워커가 따로 처리하도록 분리함.

  • 재시도 간격: 1초 → 3초 → 9초
  • 3회 초과 시 미발송 큐로 이관, 별도 잡이 주기 처리
  • 디바이스 미등록은 큐에 남기지 않고 즉시 폐기
  • 결과 로그는 시도 횟수까지 같이 적재

함정

처음엔 그냥 try/catch 감싸고 루프 돌렸는데, 이러면 송금 본 트랜잭션 안에서 외부 호출 길이만큼 DB 락이 같이 길어지는 문제가 있었음. 결제 플랫폼 특성상 잔액 갱신 트랜잭션은 짧게 끊는 게 원칙이라, 본 트랜잭션 커밋 후 발송하도록 이벤트 기반으로 빼냄. 이거 안 빼고 갔으면 동시성 높을 때 락 대기로 더 큰 사고 났을 듯.

효과

배포 후 며칠 모니터링:

  • 미수신 신고 거의 사라짐
  • 재시도로 회수되는 비율이 첫 시도 실패 중 약 70%
  • 큐에 끝까지 남는 진짜 실패는 일 단위 한자리수

회고

푸시는 "API 200 응답 = 성공"이 아니라는 걸 다시 확인함. 이커머스/송금 알림은 사용자가 실제로 봐야 의미 있는 메시지라 재시도 정책을 빡세게 잡는 게 맞다고 판단. 무한 재시도는 비용이고, 0회는 UX 사고라서 그 사이 어딘가에 선을 그어야 함. 이번엔 3회 + 큐로 잡았는데, 다음엔 단말 ack까지 추적해서 진짜 도착 여부로 성공을 정의하는 구조로 끌고 갈지 고민 중.

다음

댓글 0

첫 댓글 달아줘.