이벤트메이커

지급 API 비동기 분리로 참여 응답 지연 개선 및 지급 지연 알림 구성

참여 접수 후 즉시 지급과 재시도 워커가 지급 서버를 호출하고, DEAD 재투입과 알림으로 이어지는 흐름

문제와 배경

  • 평소 100ms 이하였던 참여 응답이 지급 서버가 지연되는 구간에는 500~600ms까지 느려짐 → 연속 참여 중 이 구간에 걸리면 회차마다 같은 지연이 반복됨.
  • 참여 이력을 저장한 뒤 지급 서버의 큐머니 지급 API를 동기로 호출 → 지급 API가 느려지면 참여 응답도 그만큼 느려지는 구조.
    • 지급 서버가 느려지는 원인은 당장 찾기 어렵고, 찾아서 고쳐도 지연은 다시 생길 수 있음 → 원인 분석과 별개로 지연이 참여 응답으로 전파되지 않는 구조부터 필요하다고 판단.

해결 과정

  • 기획자에게 참여 접수와 리워드 지급을 나누자고 제안함. 참여 이력을 저장하면 지급될 리워드와 함께 바로 참여 응답을 반환하고, 지급 호출은 @Async로 비동기 처리.
  • 나누면 지급 실패와 누락, 중복 지급, 지급 반영 지연이 생길 수 있음 → 기획자와 미리 공유하고 각각 대응을 정함.

지급 실패와 누락 대응

  • 참여 이력과 PENDING 지급 이력을 같은 DB 트랜잭션으로 저장 → 응답 뒤에 프로세스가 종료돼도 지급할 대상은 DB에 남음.
  • 1분마다 도는 재시도 작업이 재시도 시각이 된 PENDING 건을 다시 지급. 첫 호출이 실패했든 실행되지 못했든 모두 여기서 처리.
  • 지수 백오프로 재시도하고, 즉시 지급을 포함한 6회가 모두 실패하면 DEAD로 확정해 운영자가 원인을 해결한 뒤 PENDING으로 되돌림.
  • 첫 호출이 실행되지 못한 건은 즉시 지급이 아직 처리 중일 수 있어, 생성 5분 뒤부터 재시도 대상으로 삼음.

중복 지급 방지

  • 재시도가 같은 건을 다시 보낼 수 있어, 거래 ID를 PENDING 생성 때 한 번 정해 모든 재시도가 같은 ID를 쓰게 함. 지급 서버에 이미 있던 (userId, transactionId) Unique 제약이 같은 건의 두 번째 지급을 거절함.

지급 지연 안내와 알림

  • 즉시 지급에 실패한 사용자가 언제 받을지 알 수 있도록 기획자와 안내 시한을 정함. 재시도를 모두 쓰는 경우에도 끝나는 시점에 여유를 더해 1시간으로 잡고, 이벤트 상세에 "리워드는 통상 1시간 이내 지급되며, 시스템 상황에 따라 지연될 수 있습니다"로 안내함.
  • 가장 오래 기다린 PENDING의 대기 시간과 미처리 DEAD 건수를 지표로 노출. 각각 5분 초과, 1건 이상이면 Datadog 알림이 옴.

결과

  • 지급 서버가 지연되는 구간에도 참여 응답을 평소 수준인 100ms 이하로 유지.
  • 지급이 늦어지거나 실패해도 PENDING 이력과 재시도로, 재시도를 다 쓴 DEAD 건은 운영자가 되돌려 결국 지급되어, 참여 기록과 지급 사이의 최종 일관성 확보.
  • 지급 서버가 느려진 원인은 이후 팀과 함께 찾음. 다른 API들이 트랜잭션 안에서 외부를 호출하며 커넥션을 오래 잡아 커넥션 풀이 부족해진 것이었고, 이 코드를 고치는 작업에 참여함.