✅ 문제 상황: 포인트 만료 및 사용 내역 정산 문제
현재 운영 중인 시스템에서는 포인트 지급/사용 기록은 point_tx 테이블에 남고, 유저의 총 보유 포인트는 user_point에 관리되고 있었다. 그러나 다음과 같은 문제가 있었다
📌 문제
- GRANT(지급)된 개별 포인트가 얼마나 사용됐는지 알 수 없음
- USE(사용) 기록은 남지만 어떤 지급건에서 사용됐는지는 추적 불가
- 지급된 포인트는 1년 후 만료되어야 하는 정책이 있음
- 유저에게 지급된 바우처성 포인트나 결제포인트를 오래된 순서로 차감하고 싶었지만 이를 위한 정보가 없었음
→ 결국 남은 포인트(remaining_point)를 파악할 수 없어, 정합성 있는 만료/차감 로직을 구현할 수 없는 상황이었다.
✅ 해결 방법: 마이그레이션 기반 정산 + FIFO 차감 로직 구축
1. 마이그레이션 설계 – 남은 포인트 추적 및 정합성 확보
- 기존 point_tx 테이블을 순회하여 FIFO 원칙에 따라 GRANT → USE 매핑을 구성
- 각 GRANT 트랜잭션에 대해 남은 포인트(remaining_point)를 계산하여 저장
- USE 트랜잭션에 대해 어떤 GRANT에서 차감되었는지 기록하는 point_use_detail 테이블 구성
2. 차감 로직 설계 – FIFO 기반처리
- 지급 시: remaining_point = point로 초기화
- 사용 시:
1. 새로운 USE 트랜잭션을 기록하고
2. remaining_point > 0인 GRANT를 createdAt ASC 순서로 조회
3. FIFO 방식으로 순차 차감 및 point_use_detail에 기록
| 단계 | 처리 내용 |
|---|
| 1️⃣ | 포인트가 충분한지 (GRANT.remaining_point 총합으로) 사전 검증 |
| 2️⃣ | point_tx에 USE 트랜잭션 저장 |
| 3️⃣ | GRANT 트랜잭션들을 createdAt ASC 정렬하여 FIFO 방식으로 차감 |
| 4️⃣ | 각 GRANT의 remaining_point를 더티 체킹 방식으로 업데이트 (saveAll 없이도 반영됨) |
| 5️⃣ | point_use_detail 테이블에 차감 내역 기록 (어떤 GRANT에서 얼마를 썼는지 추적 가능) |
예시
| 순번 | 타입 | 포인트 | 남은 포인트 | 설명 |
|---|
| 1 | GRANT | 1000 | 0 | 다 써버림 |
| 2 | GRANT | 500 | 300 | 200원만 썼음 |
| 3 | USE | -1200 | - | 총 1200원 사용 |
진행과정 순서
- 포인트 기록과 유저 포인트 덤프 추출
- 마이그레이션 설계(로직생성)
- 정합성 체크: point_tx.remaining_point 합과 유저 현재 포인트 비교
- 1명 유저로 선행 테스트
- 차감 로직변경
구현
1. 스키마 설계 요약 (SQL 예시)
- remaining_point 컬럼을 추가하여 지급된 포인트의 남은 양을 저장합니다.
- 마이그레이션 이전에 기존 GRANT 트랜잭션의 포인트 값을 초기값으로 세팅합니다.
- 실패 이력 및 포인트 차감 상세 기록을 위한 테이블도 정의합니다.
2. 마이그레이션 처리 흐름 (1회성 처리)
- 유저의 포인트 트랜잭션을 createdAt ASC로 정렬하여 불러옵니다.
- GRANT 트랜잭션은 큐에 저장하고, USE 트랜잭션이 나올 때마다 큐를 기준으로 FIFO 순서대로 차감합니다.
- 어떤 GRANT에서 얼마만큼 차감되었는지를 기록하고, 사용 후 남은 GRANT의 포인트는 업데이트합니다.
- 차감 도중 부족할 경우 실패 이력으로 기록합니다.
3. 포인트 사용 시 차감 처리 흐름 (요청 시점 처리)
- 사용자가 포인트를 사용할 때, 해당 유저의 GRANT 트랜잭션 중 remaining_point > 0인 항목을 정렬하여 조회합니다.
- FIFO 순으로 남은 포인트를 차감하고, remaining_point 값을 갱신합니다.
- 각 차감 항목은 point_use_detail에 기록됩니다.
- 차감할 수 있는 포인트가 부족할 경우 예외를 발생시킵니다.
📝 요약 정리
- 총 포인트만 관리하던 구조라, 지급(GRANT)과 사용(USE) 간의 흐름 정합성이 보장되지 않았다.
- 마이그레이션으로 remaining_point 및 차감 매핑 정보 구성
- 차감 시에도 FIFO 원칙, 더티 체킹, use_detail 저장으로 정산 정확도 확보
- 지급된 포인트가 언제, 어디서, 얼마만큼 사용되었는지를 정밀하게 추적 가능해짐
💡 보완 사항 및 고려점
병렬 처리가 성능 향상에 기여할 수 있으나, FIFO(시간 순서 보장)가 핵심이므로 제외함
포인트 만료 로직은 batch 스케줄링이나 scheduled task로도 확장 가능
참고로 테이블명이나 컬럼명은 사내와 동일하지않습니다 ai가 생성된 예시입니다