찰떡 차감이 두 번 일어나지 않게 막기
AI 분석과 리포트 기능에 쓰는 찰떡 지갑에서 중복 차감, 부족 잔액, 환불 흐름을 방어한 기록입니다.
Code notes
코드에서 확인한 구현 포인트
배포 기준 2026.04.18
관련 파일
apps/web/lib/cubes.tsapps/web/app/api/cubes/spend/route.tsapps/web/app/api/cubes/refund/route.tsapps/mobile/lib/cube-api.ts구현 메모
cube_transactions는 idempotency_key를 기준으로 이미 처리된 요청을 찾을 수 있게 했다.
모바일 cube-api는 잔액 부족 응답을 예외가 아니라 insufficient 상태로 받아 화면이 다음 행동을 안내하게 한다.
차감 실패 후 복구를 위해 refund API도 referenceId와 idempotencyKey를 기준으로 중복 환불을 막는다.
결제성 기능은 성공보다 중복 실패가 무섭다
찰떡은 사용자가 분석이나 리포트 기능을 사용할 때 차감되는 앱 내부 재화다. 이런 기능에서 가장 조심해야 할 것은 네트워크 재시도 때문에 같은 요청이 두 번 처리되는 일이다.
분석은 실패했는데 찰떡만 빠지거나, 버튼을 두 번 눌러 두 번 차감되면 사용자 신뢰가 바로 흔들린다.
idempotency key를 기준으로 거래를 찾다
큐브 거래에는 idempotency key를 붙인다. 같은 행동에서 온 요청이라면 이미 처리된 거래가 있는지 먼저 확인하고, 새 거래를 만들지 않는다.
모바일 쪽에서도 spend, grant, refund 요청에 같은 기준을 넘길 수 있게 했다. 서버와 클라이언트가 같은 중복 방지 언어를 쓰는 셈이다.
잔액 부족은 오류가 아니라 상태다
찰떡이 부족한 상황은 서버 오류가 아니다. 사용자가 다음 행동을 선택해야 하는 상태다. 그래서 spend API가 409 또는 부족 코드를 돌려주면 모바일은 insufficient 상태와 필요한 수량, 현재 잔액을 함께 받는다.
이렇게 하면 화면은 실패 알림만 띄우는 대신 충전이나 다른 행동으로 이어질 수 있다.
환불까지 같은 기준으로 본다
분석 흐름에서는 차감 후 실패가 생길 수 있다. 그래서 refund API도 referenceId와 idempotencyKey를 기준으로 중복 환불을 막을 수 있게 했다.
재화 시스템은 차감만 만들면 끝이 아니다. 적립, 차감, 부족, 환불, 거래 내역이 모두 같은 기준으로 이어져야 운영할 수 있다.
Keep reading
다른 글 이어서 보기
Debugging
2026.05.05
6 min read
GitHub 푸시 후 Vercel 배포가 Blocked가 되었을 때
커밋은 올라갔지만 Vercel 자동 배포가 막혔던 상황에서, GitHub 작성자와 프로젝트 권한을 확인해 해결한 기록입니다.
Debugging
2026.05.04
7 min read
서브도메인은 연결됐는데 /admin이 404였던 이유
blog, ad, nacho 서브도메인을 나누는 과정에서 Vercel 404와 앱 내부 라우팅 문제를 구분해 해결한 기록입니다.
Debugging
2026.05.03
8 min read
도메인은 연결됐는데 접속이 거부될 때
tangly.kr과 www 도메인을 Vercel에 붙이며 DNS, 네임서버, SSL 발급 대기 상태를 구분해 해결한 기록입니다.