연쇄 환불 악용은 두 번 손해를 입힙니다. 스토어가 마련해 둔 반격 방법을 소개합니다
몇 번이고 반복해서 환불을 요구하는 고객은 우연이 아닙니다. 환불 악용은 금액을 되돌려주게 할 뿐 아니라 이미 쓴 연산 자원까지 앗아갑니다. 그리고 두 스토어 모두 그 패턴을 엮어낼 신원 신호, 즉 Apple 의 appAccountToken 과 Google 의 난독화 계정 ID 를 제공합니다.

핵심 요약
- 개발자가 환불 악용에 맞서 증거를 제출할 수 있는 환불 흐름은 단 두 가지뿐입니다. Apple 의 CONSUMPTION_REQUEST 는 12시간의 창을, Google Play 의 Review Refund API 를 통한 지불거절 심사는 24시간의 창을 제공합니다.
- Apple 의 appAccountToken 은 당신이 생성하여 구매에 붙이는 UUID 이며, StoreKit 이 이를 생성된 거래에 묶어 두므로 당신의 서버는 모든 환불을 그 구매를 한 정확한 계정까지 되짚어 갈 수 있습니다.
- Google Play 의 난독화 계정 ID 는 최대 64자로 제한된 해시 문자열이며, Google 자신이 이를 사용해 짧은 시간 안에 많은 기기가 한 계정에서 구매하는 것과 같은 비정상 활동을 탐지합니다.
- Google 의 난독화 계정 ID 에 평문 개인정보를 저장하면 구매가 차단되므로, 이 필드는 암호화된 값이나 단방향 해시여야 하며 결코 원본 이메일이어서는 안 됩니다.
- Google Play 의 voidedReason 필드는 friendly_fraud 와 fraud 를 일반적인 변심 환불(remorse)과 구별되는 사유로 표시하며, 이를 통해 반복 악용자를 자동 환불 후 잊어버리는 경로가 아니라 심사 대기열로 보낼 수 있습니다.
- Google 은 2022년에 사기 및 악용성 거래를 20억 달러 넘게 차단했다고 밝혔으며, 그 시스템을 떠받치는 신원 필드는 모든 구매마다 채워 넣어야만 작동합니다.
- 접근 권한을 유지한 채 환불된 모든 구매는 이미 되돌려준 돈 위에서 계속 지불하는 연산, 저장소, API 비용이며, 연쇄 환불자는 그 청구액을 의도적으로 몇 배로 불립니다.
한 건의 환불은 사업을 하는 비용입니다. 같은 계정이 매번 산 것을 다 쓰고 나서 네 번째로 환불하면 그것은 환불 악용이며, 이는 모든 구매가 당신이 통제하는 신원을 지니고 있을 때에만 볼 수 있는 패턴입니다. Apple 과 Google 모두 그 신원을 제공하며, 환불이나 지불거절이 판정되기 전에 그 신원을 스토어 앞에 내놓을 수 있는 좁은 창을 줍니다. 그 창을 놓치거나 신원을 한 번도 붙이지 않으면, 연쇄 환불자는 처음으로 불만을 품은 고객과 똑같아 보입니다. 아래에서는 그 둘을 어떻게 구별하는지, 그리고 그 차이가 돈으로 얼마의 가치가 있는지를 설명합니다.
환불 악용이 환불 문제가 아니라 신원 문제인 이유
환불은 스토어가 판정합니다. 고객이 요청하는 것을 막을 수 없고, 대부분의 흐름에서는 스토어가 승인하는 것도 막을 수 없습니다. 당신이 할 수 있는 일은, 특정 계정이 전에도 이런 일을 했는지, 그리고 산 콘텐츠가 실제로 전달되고 사용되었는지를 판단하는 것입니다. 그 둘 모두 신원에 관한 질문입니다. 즉 이 거래 뒤에 있는 사람이 당신의 어느 사용자인지, 그리고 그 이력은 어떤지입니다. 당신의 구매가 자신의 사용자 기록까지 되짚어 갈 안정적인 식별자를 지니고 있지 않다면, 그 어느 질문에도 답할 수 없고 모든 환불은 맥락 없이 도착합니다.
그것이 진짜 공백입니다. 환불 메커니즘은 정책으로 고정되어 있습니다. 하지만 거기에 가져갈 증거를 만드는 것은 전적으로 당신의 몫이며, 그것은 환불의 순간이 아니라 구매의 순간에 시작됩니다.
증거가 결과를 바꾸는 두 개의 창
당신이 보내는 것이 판정을 움직일 수 있는 흐름은 정확히 두 가지뿐입니다. 고객이 소모성 상품이나 자동 갱신 구독의 환불을 요청하면 Apple 의 CONSUMPTION_REQUEST 가 발동하며, 당신에게는 답할 12시간이 있습니다. 사용자가 은행에 청구를 이의 제기하면 Google Play 의 지불거절 심사가 발동하며, 당신에게는 Review Refund API 를 통해 대응할 24시간이 있습니다. 그 밖의 모든 환불, 48시간의 Play 셀프서비스 환불, 지원팀이 승인한 환불, 미승인 구매의 자동 환불은 당신의 개입 없이 판정됩니다.
이 두 증거 경로는 거래가 이미 당신의 식별자를 지니고 있을 때 훨씬 강력해집니다. Apple 의 소비 정보에는 계정 이력과 지출액과 더불어 appAccountToken 을 포함할 수 있고, Google 의 심사는 구매 이후로 계속 지켜봐 온 난독화 계정 ID 에 기댈 수 있습니다. 식별자가 없는 계정은 제출할 이력이 없는 계정입니다.
두 신원 필드를 나란히 놓고 보기
Apple 과 Google 은 같은 문제를 거의 같은 방식으로, 다른 이름과 다른 규칙으로 풀었습니다. 둘 다 구매에 자신의 사용자 기록을 가리키는 값을 찍을 수 있게 합니다. 둘 다 기본값으로는 켜져 있지 않습니다. 둘 다 구매 시점에 설정하지 않으면 아무 쓸모가 없습니다.
Apple: appAccountToken
appAccountToken 은 구매가 시작될 때 당신이 생성하여 전달하는 UUID 입니다. StoreKit 이 이를 생성된 거래에 연결하며, 그것은 당신의 서버가 검증하는 거래 데이터와 CONSUMPTION_REQUEST 동안 되돌려 보내는 소비 정보에 나타납니다. 그것은 당신 자신의 값이므로, 이메일이나 이름을 전혀 거치지 않고 스토어 거래를 당신 데이터베이스의 계정에 직접 대응시킵니다. 그것은 진짜 UUID 여야 하며, 그 밖의 어떤 것도 거부됩니다. Apple 은 이후 Set App Account Token 엔드포인트를 추가하여, 오퍼 코드 사용 같은 앱 밖에서 이루어진 구매를 포함해 과거 거래에 토큰을 붙이거나 갱신할 수 있게 했습니다.
Google Play: 난독화 계정 ID
Google 의 대응물은 setObfuscatedAccountId 로, 구매 계정에 묶인 선택적 문자열입니다. Google 자신의 문서는 그 목적에 대해 단도직입적입니다. Google Play 는 이를 사용해 짧은 시간 안에 많은 기기가 같은 계정에서 구매하는 것과 같은 비정상 활동을 탐지하고, 일부 사기 거래를 완료 전에 차단합니다. 그것은 64자로 제한되며 평문 개인정보를 담아서는 안 됩니다. 거기에 원본 이메일을 저장하면 Google 은 구매를 곧바로 차단하는데, 이 필드는 암호화된 값이나 단방향 해시를 기대하기 때문입니다. 한 계정이 여러 프로필을 가지는 앱을 위해 같은 종류의 필드 setObfuscatedProfileId 도 존재합니다.
| 필드 | 스토어 | 유형과 상한 | 설정 주체 | 기본값 | 스토어가 그것으로 하는 일 |
|---|---|---|---|---|---|
| appAccountToken | Apple | UUID | 당신, 구매 시점에 | 미설정 | 거래를 당신의 사용자에 묶고, 거래 및 소비 데이터에서 반환 |
| obfuscatedAccountId | Google Play | 해시 문자열, 최대 64자 | 당신, 구매 시점에 | 미설정 | 비정상 활동을 탐지하고, 완료 전에 일부 사기를 차단 |
연쇄 악용자의 환불이 실제로 치르는 비용
환불 그 자체는 청구서에서 가장 작은 부분입니다. 스토어가 환불을 승인하면 당신은 매출을 되돌려주며, 그만큼은 장부에 보입니다. 환불 항목에 보이지 않는 것은, 이제 공짜가 된 제품을 전달하기 위해 쓴 모든 것입니다.
실제 작업을 촉발하는 소모성 상품을 떠올려 보세요. 이미지 생성, 모델 제공사로의 일괄 API 호출, 동영상 내보내기, 크리에이터에게 지급하는 정산금 등입니다. 고객이 사용한 그 순간에 당신은 이미 그 연산에 대해 지불했습니다. 환불은 가격을 되찾아 가지만, 제공사의 청구서는 되찾아 오지 못합니다. 연쇄 환불자란 콘텐츠가 환불 후에도 남는다는 것을 배운 사람이며, 그래서 그들은 그 루프를 다시 돌립니다. 구매하고, 소비하고, 환불하고, 반복합니다. 매 주기마다 당신은 전달 비용을 두 번째로 떠안습니다.
그다음에는 스토어 자신의 비용 전가가 있습니다. 2026년 8월 3일부터, 그 날짜 이후에 이루어진 주문에 대해 Google Play 는 구매 가격과 은행의 지불거절 수수료를 개발자에게 넘깁니다. 예전에는 대체로 Google 의 문제였던 지불거절이 이제 당신의 매출에 수수료를 더한 것이 되며, 반복해서 청구하는 사람은 그 숫자를 매번 끌어올립니다. 신원 필드야말로 24시간의 창 안에서 부당한 이의를 반박할 증거를 Review Refund API 에 공급할 수 있게 해 주는 것입니다.
Google 은 그 규모를 솔직히 밝힙니다. 2022년에 사기 및 악용성 거래를 20억 달러 넘게 차단했다고 말합니다. 그 숫자가 존재하는 이유는 그 신호들, 그 안에는 난독화 계정 ID 도 포함되는데, 그것들이 채워져 있었기 때문입니다. 빈 신원 필드로 구매를 출고하는 앱은 그 보호에서 스스로 빠지는 것입니다.

스토어가 판정하기 전에 반복 환불자를 잡는 방법
당신이 소유한 신원으로 모든 구매에 태그를 달아라
모든 StoreKit 구매에 appAccountToken 을, 모든 Play Billing 구매에 setObfuscatedAccountId 를 설정하되, 둘 다 당신 자신의 사용자 기록에서 생성합니다. Apple 에서는 계정에 대응시킨 진짜 UUID 를 사용합니다. Google 에서는 계정 키를 해시하여 평문으로 개인정보가 오가지 않도록 합니다. 이것은 구매 시점에 해야 하는데, Google 에서는 이것이 나중에 되돌릴 수 없는 유일한 단계이기 때문입니다.
그 신원을 키로 하는 장부를 유지하라
모든 구매, 전달, 소비 이벤트, 환불을 그 식별자에 대해 기록하세요. CONSUMPTION_REQUEST 나 지불거절 심사가 도착하면, 그 계정의 전체 이력은 이전 환불까지 포함해 단 한 번의 조회로 손에 들어옵니다. Apple 의 소비 정보에는 바로 이것을 위한 명시적 필드가 있습니다. consumptionStatus, deliveryStatus, playTime, accountTenure, lifetimeDollarsPurchased, 그리고 당신의 refundPreference 입니다.
voidedReason 을 읽고 악용자를 다르게 라우팅하라
Google 구매가 무효화되면 voidedReason 필드가 그 이유를 알려 주며, friendly_fraud 와 fraud 는 일반적인 변심 환불(remorse)과 구별되는 별개의 값입니다. 그것들은 심사 대기열과 더 엄격한 정책으로 보내고, 첫 환불과 같은 자동 경로로 보내지 마세요. Google 자신의 지침은 다단계 경고 모델입니다. 초범에게는 경고하고, 반복하는 자에게는 더 단호한 조치를 취하며, 그래도 계속하는 계정에는 구매를 비활성화합니다.
매번 창 안에서 응답하라
증거는 그 두 창 안에서만 의미가 있습니다. CONSUMPTION_REQUEST 응답을 자동화하여 12시간의 충분히 안쪽에서 발동시키고, 지불거절 심사를 자동화하여 24시간 안쪽에서 발동시키세요. 늦게 제출한 완벽한 이력은 스토어가 결코 읽지 않는 이력입니다.
| 잡고 싶은 신호 | 그것이 있는 곳 | 그것을 드러내는 필드 또는 흐름 |
|---|---|---|
| 같은 계정, 많은 기기, 짧은 시간 창 | Google Play | 난독화 계정 ID 의 비정상 활동 탐지 |
| 이 계정은 전에 환불한 적이 있다 | 당신의 장부 | appAccountToken 또는 난독화 계정 ID 를 키로 하는 이력 |
| 콘텐츠가 전달되고 소비되었다 | Apple | 소비 정보 내의 deliveryStatus 와 consumptionStatus |
| 어떤 이의가 사실은 제1자 사기이다 | Google Play | voidedReason 값 friendly_fraud |
스토어가 당신을 위해 할 일과 하지 않을 일
이 분업을 정확히 짚어 둘 가치가 있습니다. 스토어가 악용을 처리해 줄 것이라 넘겨짚기 쉽지만, 처리하지 않을 때 스토어는 대체로 그 사실을 알려 주지 않기 때문입니다. Google 은 난독화 계정 ID 를 적극적으로 사용해 구매가 완료되기 전에 일부 사기를 차단하며, 그 시스템은 플랫폼 층위에서 상당 부분을 잡아냅니다. Apple 은 모든 환불을 스스로 판정하고 당신의 소비 정보를 하나의 입력으로 취급하지만, 결코 한 표로 취급하지는 않습니다. 두 스토어 모두 당신을 위해 악용자 목록을 유지하거나, 환불된 소모성 상품을 당신 잔액에서 차감하거나, 당신을 대신해 반복 환불자에게 거절을 통보하지 않습니다. 신원은 가장자리에서는 스토어가 다룰 것이고, 그 밖의 모든 곳에서는 당신이 다룰 것입니다.
이것이 바로 RefundHalt 가 모든 것을 구매 신원으로 키 지정하는 이유입니다. 같은 계정의 환불, 지불거절 심사, 소비 요청은 하나의 이력으로 귀결되므로, 연쇄 환불자는 당신이 이미 지불한 네 번째 청구서 이후가 아니라, 그들이 처음 반복하는 시점에 하나의 패턴으로 드러납니다.
자주 묻는 질문
- 앱에서의 환불 악용이란 무엇인가요?
- 환불 악용이란 고객이 산 것을 받아 사용한 뒤 반복해서 환불을 요구하여, 콘텐츠나 혜택은 그대로 지니면서 돈은 되돌려받는 것입니다. 앱 스토어에서는 보통 같은 계정이 소모성 상품이나 구독을 몇 번이고 환불하는 형태로, 또는 정당한 청구를 은행에 이의 제기하는 제1자 사기(friendly fraud)로 나타납니다.
- 인앱 구매를 특정 사용자에 어떻게 연결하나요?
- Apple 에서는 UUID 를 생성해 구매가 시작될 때 appAccountToken 으로 전달하면, StoreKit 이 이를 거래에 묶고 거래 및 소비 데이터에서 반환합니다. Google Play 에서는 계정에 묶인 해시 값으로 setObfuscatedAccountId 를 호출합니다. 둘 다 개인정보를 노출하지 않고 스토어 거래를 당신 자신의 사용자 기록에 대응시킵니다.
- Apple 이나 Google 이 어떤 계정이 반복 환불자라고 알려 주나요?
- 직접 알려 주지는 않습니다. Google 은 난독화 계정 ID 를 사용해 비정상 활동을 탐지하고 구매 전에 일부 사기를 차단하며, Apple 은 소비 요청 동안 계정 이력을 제출하게 해 주지만, 두 스토어 모두 반복 환불자 목록을 건네주지는 않습니다. 그 목록은 신원 필드를 키로 하는 당신 자신의 장부에서 직접 만들어 내야 합니다.
- 계정 ID 를 설정했는데 왜 Google 이 제 구매를 차단하나요?
- 난독화 계정 ID 는 평문 개인정보를 담아서는 안 되기 때문입니다. 원본 이메일 주소 같은 것을 거기에 저장하면 Google Play 가 구매를 차단합니다. 암호화된 값이나 단방향 해시를 사용하고, 64자 상한 안에 유지하세요.
- 소비 요청을 통해 환불에 반박하면 악용을 막을 수 있나요?
- 줄일 수는 있습니다. CONSUMPTION_REQUEST 는 스토어가 판정하기 전에 당신의 증거가 스토어에 도달하는 단 두 흐름 중 하나이며, 계정 이력에 더해 전달 및 소비 데이터가 Apple 이 반품 악용과 제1자 사기를 식별하는 데 도움을 줍니다. 다만 그것은 차단이 아닙니다. Apple 은 여전히 스스로 판정하며, 반박할 수 없는 흐름을 통해 도착하는 악용은 영향을 받지 않습니다.
출처 및 추가 자료
- Apple: appAccountToken (App Store Server API)
- Apple: ConsumptionRequest (App Store Server API)
- Android: BillingFlowParams.Builder.setObfuscatedAccountId
- Android: Fight fraud and abuse (Play Billing security)
- Google Play Developer API: Voided Purchases
- Google Play Billing: Provide refund and chargeback suggestions (Review Refund API)
- Android Developers Blog: Play Commerce prevented over $2 billion in fraudulent and abusive transactions in 2022
- Google Play Console Help: Updates to refund protection and chargeback cost responsibility
RefundHalt
App Store와 Google Play 환불 자동 처리
계속 읽기
The refunds you cannot contest: what Apple and Google decide without asking you
Only two refund flows ever ask for your evidence: Apple's consumption request and Google Play's chargeback review. Everything else, the 48-hour Play refund, support refunds, voided purchases, unacknowledged trials, is decided without you. Here is the full map, what you can prevent, and what you can only record.
Apple's CONSUMPTION_REQUEST, explained: the 12 hours that decide your refund
When a customer asks Apple for a refund, Apple asks you first. Here's exactly what the CONSUMPTION_REQUEST notification contains, what Apple expects back, how to answer one end to end, and why most developers silently forfeit.