Files
sodalive-backend-spring-boot/docs/prd/20260518_충전이벤트보너스지급안정화_prd.md

5.7 KiB

PRD: 충전 이벤트 보너스 지급 안정화

1. Overview

  • 충전 완료 후 지급되는 충전 이벤트 보너스가 누락되거나 중복 지급되지 않도록 안정화한다.
  • 상세 구현 방향은 docs/plan-task/20260518_충전이벤트보너스지급안정화.md를 기준으로 한다.
  • 이 PRD는 충전 이벤트 보너스 지급 작업의 재시도, worker, 관리자 API 운영 정책을 확정한다.

2. Problem

  • 현재 충전 이벤트 보너스 지급은 결제 완료 흐름과 분리된 비동기 이벤트에서 처리된다.
  • 비동기 처리 실패가 발생하면 원 결제는 성공했지만 이벤트 보너스만 누락될 수 있다.
  • 실패 작업을 DB에 남기고, 정해진 주기와 횟수 안에서 재시도하며, 최종 실패 건은 관리자 API로 확인/재시도할 수 있어야 한다.

3. Goals

  • 이벤트 보너스 지급 실패가 DB에 남고 재시도 가능해야 한다.
  • 중복 결제 검증 또는 worker 재시도에도 보너스가 중복 지급되지 않아야 한다.
  • 원본 충전 완료 처리에서도 회원 잔액 변경은 회원 row lock을 잡은 뒤 수행해 동시 충전 시 잔액 유실을 방지해야 한다.
  • 최대 재시도 후에도 실패한 작업은 운영자가 원인과 지급 대상, 지급할 캔 수를 확인할 수 있어야 한다.
  • 충전 완료 검증 시 이벤트 작업을 기록하고 즉시 지급을 시도하되, 즉시 수행 중인 작업을 worker가 중복 처리하지 않아야 한다.

4. Non-Goals

  • 결제 PG 검증 방식 자체를 교체하지 않는다.
  • 충전 상품 가격, 이벤트 보너스율, 첫 충전 이벤트율을 변경하지 않는다.
  • 관리자 화면 신규 개발은 포함하지 않는다. 단, 실패 작업 조회/재시도용 관리자 API는 포함한다.

5. Core Features

Feature A. 충전 이벤트 보너스 지급 작업 추적

Requirements

  • 충전 완료 후 이벤트 보너스 지급 대상이면 DB 작업으로 추적한다.
  • 지급 대상, 원본 충전, 추가 지급 캔 수, 처리 상태, 실패 사유를 확인할 수 있어야 한다.
  • 원본 충전 완료 처리(verify, verifyHecto, appleVerify, payverseVerify, payverseWebhook, processGoogleIap)는 회원 row lock 안에서 PaymentStatus.REQUEST -> COMPLETE 전이와 member.charge(...)를 수행한다.
  • 충전 완료 처리(verify) 시 charge_event_job을 기록하고, 같은 흐름에서 이벤트 보너스 지급을 즉시 시도한다.
  • 즉시 지급 중인 작업은 worker가 처리하지 않도록 PROCESSING 상태로 선점한다.
  • 상세 테이블 구조와 구현 항목은 plan-task 문서를 따른다.

Edge Cases

  • 같은 결제 검증 요청이 여러 번 들어와도 보너스 작업은 중복 생성되지 않아야 한다.
  • worker가 같은 작업을 재시도해도 보너스는 1회만 지급되어야 한다.
  • 이벤트 설정이 재시도 시점에 변경되어도 최초 작업 생성 시점의 추가 캔 수를 유지해야 한다.
  • 즉시 지급 실패 후 worker가 재시도할 수 있도록 작업은 PENDINGnext_retry_at으로 전환되어야 한다.

Feature B. 이벤트 보너스 worker 재시도

Requirements

  • worker 실행 주기는 5분으로 한다.
  • worker batch size는 30건으로 한다.
  • worker는 활성 충전 이벤트가 없으면 charge_event_job 조회를 수행하지 않고 종료한다.
  • worker는 PENDING 상태이면서 next_retry_at IS NULL OR next_retry_at <= now인 작업만 처리한다.
  • backoff 정책은 5분, 10분, 15분 순서로 적용한다.
  • 최대 재시도 횟수는 3회로 한다.
  • 3회 재시도 후에도 실패하면 FAILED로 전환하고 자동 재시도를 중단한다.

Edge Cases

  • 같은 시간에 다른 scheduler/worker가 실행되어도 worker는 최대 30건만 처리한다.
  • 이미 PROCESSING, DONE, FAILED인 작업은 자동 worker가 처리하지 않는다.
  • FAILED 작업은 관리자 재시도 API를 통해서만 다시 재시도 대상으로 전환한다.

Feature C. 이벤트 작업 관리자 API

Requirements

  • DONE, PROCESSING 상태를 제외한 charge_event_job 목록을 조회할 수 있는 관리자 API를 추가한다.
  • 조회 API는 재시도 대기 중인 PENDING 작업과 운영 확인이 필요한 FAILED 작업을 함께 보여준다.
  • FAILED 상태의 단일 작업을 재시도 대상으로 되돌리는 관리자 API를 추가한다.
  • 재시도 API는 대상 작업을 PENDING으로 변경하고 next_retry_at을 즉시 실행 가능하도록 갱신한다.
  • 재시도 API는 이미 DONE 또는 PROCESSING인 작업을 변경하지 않아야 한다.

Edge Cases

  • 관리자가 같은 실패 작업 재시도 API를 여러 번 호출해도 중복 지급되지 않아야 한다.
  • 이미 성공 처리된 작업은 재시도 API에서 거부되어야 한다.
  • 즉시 지급 중인 PROCESSING 작업과 지급 완료된 DONE 작업은 관리자 조회 목록에 노출하지 않는다.

7. Technical Constraints

  • DB는 MySQL을 기준으로 한다.
  • 날짜/시간 컬럼은 TIMESTAMP를 사용한다.
  • boolean 컬럼이 필요해질 경우 TINYINT(1)을 사용한다.
  • 각 DB 컬럼에는 COMMENT를 작성한다.
  • 구현 계획과 DDL은 docs/plan-task/20260518_충전이벤트보너스지급안정화.md를 기준으로 관리한다.

8. Metrics

  • 결제 완료 후 이벤트 보너스 지급 작업 생성 성공률
  • 이벤트 보너스 지급 성공률
  • 재시도 후 성공한 작업 수
  • 최종 FAILED 상태로 남은 작업 수
  • 중복 지급 방지 위반 건수
  • 관리자 API로 재시도된 작업 수

  • docs/plan-task/20260518_충전이벤트보너스지급안정화.md