네 번째로 환불을 요청하는 사람은 불만을 가진 고객이 아닙니다. 그는 하나의 패턴을 반복하고 있는 것이며, 이는 환불된 매출뿐 아니라 주문을 처리하는 데 소모한 모든 비용까지 당신에게 떠안깁니다. Apple과 Google은 각각 하나의 식별자 필드를 제공하는데, 한쪽은 appAccountToken이고 다른 쪽은 obfuscated account ID로, 이것이 개별적인 사건들을 눈에 보이는 패턴으로 바꿔줍니다.
핵심 요약
당신이 제출하는 증거가 스토어에 전달되는 경우는 정확히 두 가지뿐입니다. 12시간 내에 응답해야 하는 Apple의 CONSUMPTION_REQUEST와, Review Refund API를 통해 24시간 내에 응답해야 하는 Google Play의 차지백 리뷰입니다. 그 외의 모든 경우는 당신 없이 결정됩니다.
Apple에서는 당신이 생성한 UUID가 appAccountToken으로 구매와 함께 전달됩니다. StoreKit이 이를 트랜잭션에 결부시키므로, 이후 발생하는 환불은 당신의 레코드 안에서 식별 가능한 하나의 계정으로 귀속됩니다.
Google의 대응 필드는 64자를 넘지 않는 해시 문자열입니다. Google이 직접 이 값을 읽어, 한 계정이 짧은 시간 안에 비정상적으로 많은 기기에서 구매하는 등의 비정상적인 행동을 포착하는 데 사용합니다.
이 Google 필드에 평문 개인정보를 넣으면 구매가 즉시 차단됩니다. 암호화된 값이나 단방향 해시가 필요하며, 원본 이메일 주소는 허용되지 않습니다.
Play의 voidedReason은 friendly_fraud와 fraud를 일반적인 단순 변심 환불과 구분해 줍니다. 이를 근거로 상습 위반자를 기본적인 '환불 후 넘어가기' 경로가 아니라 검토 대기열로 보낼 수 있습니다.
Google은 2022년 한 해 동안 20억 달러 이상의 사기 및 악용 거래를 차단했다고 밝혔습니다. 이러한 방어 체계는 당신의 구매 데이터가 해당 식별자를 포함할 때만 작동하는 식별 신호를 기반으로 합니다.
환불 이후에도 유지되는 접근 권한은 더 이상 대가를 받지 못하는 스토리지, 컴퓨팅, API 예산을 계속 소모합니다. 그리고 의도적으로 환불을 반복하는 사람은 바로 이런 결과를 반복해서 만들어내고 있는 것입니다.
개요
환불은 일어나기 마련이며, 그중 하나는 단순한 운영 비용일 뿐입니다. 상황이 달라지는 것은 같은 계정이 이전 구매마다 상품을 소비한 뒤 네 번째로 다시 돌아올 때입니다. 이런 행동은 모든 트랜잭션이 당신이 지정한 식별자를 담고 올 때만 비로소 당신에게 보입니다. 두 플랫폼 모두 이를 위한 필드를 제공합니다. 또한 결과가 확정되기 전에 응답할 수 있는 짧은 시간도 열어줍니다. 식별자를 생략하거나 그 시간을 놓치면, 시스템을 악용하는 사람과 정당한 불만을 가진 신규 고객을 구별할 수 없게 됩니다. 이 둘을 가르는 것이 무엇이며, 그 차이가 금전적으로 얼마의 가치를 지니는지가 이어서 다룰 내용입니다.
환불 남용은 사실 환불의 탈을 쓴 식별자 문제입니다
환불 결정은 스토어의 몫입니다. 고객이 요청하면 대부분의 흐름에서 스토어는 당신의 개입 없이 이를 승인합니다. 당신의 영향력이 작용하는 곳은 다른 지점입니다. 바로 이 특정 계정이 같은 행동을 반복해 온 이력이 있는지, 그리고 구매한 것이 실제로 전달되어 사용되었는지를 입증하는 일입니다. 두 질문 모두 식별자에 관한 질문입니다. 이 트랜잭션 뒤에 있는 사용자가 누구이며, 그가 이전에 무엇을 했는가. 당신의 사용자 레코드로 연결되는 안정적인 링크가 없는 구매는 두 질문 모두에 답할 수 없게 만들며, 그 결과 모든 환불은 맥락이 제거된 채로 처리됩니다.
이것이 바로 메워야 할 간극입니다. 정책이 메커니즘을 고정하며 당신은 이를 바꿀 수 없습니다. 하지만 증거를 모으는 일은 당신의 몫이며, 그 수집은 환불 시점이 아니라 결제 시점에서 시작됩니다.
당신이 보내는 내용이 실제로 중요한 두 가지 창구
당신의 입력을 실제 입력으로 취급하는 흐름은 단 두 가지뿐입니다. 고객이 소모성 상품이나 자동 갱신 구독에 대해 환불을 요청하면 Apple의 CONSUMPTION_REQUEST가 트리거되고, 당신은 12시간 내에 응답해야 합니다. 고객이 은행을 통해 결제에 이의를 제기하면 Google Play의 차지백 리뷰가 트리거되며, Review Refund API를 통해 24시간 내에 응답할 수 있습니다. 이 두 가지를 제외한 모든 경우는 당신 없이 결정됩니다. Play의 48시간 자가 서비스 환불, 지원팀이 승인한 환불, 당신이 한 번도 확인하지 못한 구매에 대한 자동 환불 등이 그렇습니다.
트랜잭션에 이미 당신의 식별자가 포함되어 있으면 두 경로 모두 훨씬 더 정교해집니다. Apple에 전송하는 소비 정보에는 해당 계정의 지출 및 이력과 함께 appAccountToken을 포함할 수 있으며, Google의 리뷰는 구매가 완료된 시점부터 관찰해 온 obfuscated account ID를 바탕으로 이루어집니다. 식별자가 없으면 제출할 이력도 없습니다.
두 식별자 필드 비교
두 회사는 서로 다른 이름과 제약 조건 아래에서 거의 동일한 해법에 도달했습니다. 각 필드는 구매에 당신의 사용자 레코드로 귀결되는 값을 표시할 수 있게 해줍니다. 두 필드 모두 기본적으로는 활성화되어 있지 않습니다. 또한 구매가 진행되는 동안 설정하지 않으면 둘 다 아무 소용이 없습니다.
Apple: appAccountToken
UUID를 생성해 구매가 시작될 때 전달하면, StoreKit이 이를 그 결과로 생성되는 트랜잭션에 결부시킵니다. 이후 이 값은 당신의 서버가 검증하는 트랜잭션 데이터에 나타나며, CONSUMPTION_REQUEST 중 반환하는 소비 정보에도 다시 나타납니다. 이 값은 당신이 생성한 것이므로, 이름이나 이메일을 전혀 사용하지 않고도 스토어 트랜잭션을 데이터베이스의 한 행에 연결해 줍니다. 오직 실제 UUID만 허용되며, 그 외의 값은 거부됩니다. Apple은 이후 이미 발생한 트랜잭션, 오퍼 코드 사용, 그와 유사한 앱 외부 구매에도 토큰을 기록하거나 업데이트할 수 있는 Set App Account Token 엔드포인트를 추가로 제공했습니다.
Google Play: the obfuscated account ID
setObfuscatedAccountId는 Google 버전으로, 구매 계정에 결부되는 선택적 문자열입니다. Google의 문서는 그 목적을 분명하게 밝히고 있습니다. Play는 이 값을 사용해 비정상적인 활동을 탐지하는데, 짧은 시간 안에 많은 기기가 하나의 계정으로 거래하는 경우가 그 예로 제시되며, 일부 사기성 구매는 완료되기 전에 차단됩니다. 상한선은 64자이며, 평문 개인정보는 허용되지 않습니다. 원본 이메일을 넣으면 구매가 차단되는데, 이 필드가 기대하는 값은 암호화된 값이나 단방향 해시이기 때문입니다. 하나의 계정이 여러 프로필을 포함하는 앱에는 보조 필드인 setObfuscatedProfileId가 제공됩니다.
appAccountToken은 Apple의 필드입니다. 반드시 UUID여야 하며 다른 값은 허용되지 않습니다. 당신의 코드가 결제 시점에 이를 설정하며, 직접 추가하지 않으면 존재하지 않습니다. Apple은 이를 사용해 트랜잭션을 당신의 사용자에게 고정하며, 트랜잭션 페이로드와 소비 페이로드에 다시 나타납니다.
obfuscatedAccountId는 Google Play의 필드입니다. 최대 64자의 해시 문자열을 받으며, 당신의 코드가 결제 시점에 이를 설정하고, 이 역시 기본적으로는 존재하지 않습니다. Google은 이를 비정상 활동 탐지에 활용하며, 일부 사기성 구매가 완료되기 전에 이를 차단하는 데 사용합니다.
한 가지 비대칭이 매우 중요합니다. Google은 어떠한 사후 보완도 제공하지 않습니다. 식별자 없이 완료된 Play 구매는 영구적으로 익명으로 남으며, 앞으로의 구매에 태그를 붙이는 것이 유일하게 가능한 대처입니다. Apple의 Set App Account Token 엔드포인트는 이력을 보완할 수 있으므로, 이는 일반적인 패턴이 아니라 예외에 해당합니다.
상습적으로 환불하는 사람 때문에 드는 실제 비용 계산하기
환불된 매출은 눈에 보이는 부분이자 더 작은 부분이기도 합니다. 환불을 승인하면 판매 금액이 되돌아가고, 이는 당신의 장부에 기록됩니다. 그 기록에서 빠져 있는 것은 고객이 지금 공짜로 손에 쥔 것을 만들어내는 데 들어간 모든 비용입니다.
실제 작업을 발생시키는 소모성 상품을 떠올려 보십시오. 이미지 생성, 모델 제공업체에 대한 일련의 호출, 비디오 내보내기, 크리에이터에게 지급되는 대금 등입니다. 그 컴퓨팅 자원은 사용되는 순간에 구매된 것입니다. 환불은 판매 금액만 되돌릴 뿐, 제공업체에 지급해야 할 청구서는 그대로 남습니다. 상품이 환불보다 더 오래 남는다는 것을 알아낸 사람은 단순히 구매, 소비, 환불이라는 순서를 반복하며, 반복될 때마다 전달 비용을 당신에게 다시 부과합니다.
플랫폼이 비용을 당신 쪽으로 넘기는 측면도 있습니다. 2026년 8월 3일부터는 Google Play가 그 날짜 이후 접수된 주문에 대해 구매 금액과 은행의 차지백 수수료를 모두 개발자에게 부담시킵니다. 과거 대부분 Google이 부담하던 분쟁 비용이 이제는 당신의 손실 매출에 수수료까지 더해진 형태가 되며, 상습적으로 차지백을 거는 사람은 시도할 때마다 그 금액을 늘립니다. 식별자 필드가 있어야만 24시간 창구 안에서 Review Refund API에 읽을 가치가 있는 정보를 전달할 수 있습니다.
Google은 이 문제의 규모를 수치로 제시합니다. 2022년 한 해 동안 차단된 사기 및 악용 거래가 20억 달러를 넘습니다. 이 수치가 존재하는 이유는 obfuscated account ID를 포함한 기반 신호들이 실제로 채워져 있었기 때문입니다. 이 필드들을 비워둔 채 구매를 처리하는 것은 그 보호 체계 바깥에 머물겠다는 선택입니다.
스토어가 판단을 내리기 전에 상습 환불자 잡아내기
모든 구매에 당신이 관리하는 식별자를 찍어두기
두 플랫폼 모두 식별자 없는 구매를 봐서는 안 됩니다. StoreKit 구매에는 appAccountToken을, Play Billing 구매에는 setObfuscatedAccountId를 담아야 하며, 두 값 모두 당신 자신의 사용자 레코드에서 나와야 합니다. Apple은 해당 계정에 매핑된 진짜 UUID를 기대하고, Google은 아무 개인정보도 평문으로 전달되지 않도록 해시된 계정 키를 기대합니다. 둘 다 결제 시점이 바로 그 타이밍이며, Google의 경우 이 타이밍은 나중에 다시 조정할 수 없습니다.
그 식별자를 키로 하는 장부를 유지하기
전달, 소비 이벤트, 구매, 환불을 모두 그 식별자 아래에 기록하십시오. 그러면 CONSUMPTION_REQUEST나 차지백 리뷰가 발생했을 때, 이전 환불 내역까지 포함한 그 계정의 전체 과거 기록을 단 한 번의 조회로 확인할 수 있습니다. Apple의 소비 정보는 바로 이런 자료를 위한 전용 필드를 제공합니다. consumptionStatus, deliveryStatus, playTime, accountTenure, lifetimeDollarsPurchased, 그리고 당신이 직접 지정하는 refundPreference입니다.
voidedReason을 라우팅 결정으로 활용하기
무효 처리된 Play 구매에는 그 원인을 설명하는 voidedReason이 포함되며, friendly_fraud와 fraud는 단순한 변심과는 별도로 기록됩니다. 이런 경우에는 첫 환불에 적용되는 자동 처리 대신 검토 대기열과 더 강경한 정책이 필요합니다. Google의 가이드라인은 단계적으로 강화되는 대응을 설명합니다. 처음에는 경고, 반복되면 더 강경한 조치, 그리고 계속되는 계정에는 구매 비활성화가 적용됩니다.
창구를 절대 놓치지 않기
늦게 제출된 증거는 존재하지 않는 것과 마찬가지입니다. CONSUMPTION_REQUEST 응답이 12시간 안에 여유롭게 전송되도록, 그리고 차지백 리뷰 응답이 24시간 안에 전송되도록 자동화하십시오. 마감 이후에 제출된 완벽한 계정 이력은 스토어의 누구도 열어보지 않을 이력입니다.
한 계정이 한꺼번에 비정상적으로 많은 기기에서 거래하는 상황을 포착하려면, obfuscated account ID를 읽는 Google Play의 비정상 활동 탐지 기능에 의존하십시오.
이 계정의 과거 환불 이력을 확인하려면, 당신 자신의 레코드, 즉 두 플랫폼 중 하나의 식별자로 키를 설정한 장부에 의존하십시오.
상품이 실제로 구매자에게 전달되어 사용되었는지 확인하려면, consumptionStatus와 deliveryStatus가 들어 있는 소비 정보를 제공하는 Apple에 의존하십시오.
실제로는 구매자가 당신을 상대로 사기를 치는 분쟁을 포착하려면, voidedReason이 friendly_fraud로 반환되는 Google Play에 의존하십시오.
플랫폼이 도와주는 지점, 그리고 멈추는 지점
책임의 경계를 정확히 파악하는 것은 중요합니다. 스토어가 남용을 알아서 처리해 줄 것이라고 쉽게 가정해 버릴 수 있지만, 스토어는 자신이 어디서 멈추는지 거의 알려주지 않기 때문입니다. Google은 실제로 obfuscated account ID를 읽어 구매 전 일부 사기를 차단하며, 플랫폼 차원의 시스템이 상당한 규모를 가로막습니다. Apple은 모든 환불 결정을 자신의 몫으로 남겨두며, 당신이 제출하는 소비 정보를 투표가 아니라 증거로 취급합니다. 어느 스토어도 하지 않는 일은, 당신을 대신해 남용자 명단을 관리하거나, 환불된 소모성 상품을 당신의 잔액으로 다시 돌려주거나, 상습 환불자를 당신을 위해 거부해 주는 것입니다. 경계 지점에서는 식별자를 가지고 행동하는 것이 스토어의 몫입니다. 그 외의 모든 곳에서는 그것이 당신의 몫입니다.
Refund Sensor는 바로 이 식별자를 중심으로 설계되어 있으며, 이유는 동일합니다. 한 계정에 속한 환불, 차지백 리뷰, 소비 요청이 하나의 이력으로 통합되므로, 네 번째 청구서가 이미 지급된 뒤가 아니라 두 번째 발생 시점에 반복 패턴이 눈에 보이게 됩니다.
이 규정들이 문서화된 곳
자주 묻는 질문
이는 고객이 구매한 상품을 받아 사용한 뒤에도 반복적으로 환불을 요청하여, 혜택을 그대로 누리면서 결제 금액까지 되돌려받는 경우를 말합니다. 앱스토어 환경에서는 보통 한 계정이 소모성 상품이나 구독을 반복해서 환불하는 형태로 나타나거나, 정상적인 결제를 은행을 통해 이의 제기하는 프렌들리 프로드 형태로 나타납니다.
Apple에서는 UUID를 생성해 구매가 시작될 때 appAccountToken으로 전달하면, StoreKit이 이를 결과 트랜잭션에 결부시키고, 이후 트랜잭션 데이터와 소비 데이터 양쪽에 다시 나타납니다. Google에서는 해당 계정에서 파생된 해시 값을 사용해 setObfuscatedAccountId를 호출합니다. 두 방식 모두 개인정보를 전혀 노출하지 않으면서 스토어 트랜잭션을 당신의 사용자 레코드에 연결해 줍니다.
적어도 직접적으로는 둘 다 알려주지 않습니다. Google은 obfuscated account ID를 읽어 비정상적인 활동을 식별하고 구매 전 일부 사기를 차단하며, Apple은 소비 요청 중에 제출되는 계정 이력을 받아들입니다. 하지만 두 회사 중 어느 쪽도 상습 위반자 명단을 되돌려주지는 않습니다. 그 명단을 작성하는 일은 당신의 몫이며, 당신이 해당 식별자 아래 기록해 둔 데이터를 바탕으로 만들어야 합니다.
대개 obfuscated account ID에 평문 개인정보가 들어 있는 것이 원인입니다. 원본 이메일 주소 같은 값을 그 자리에 넣으면 Play가 구매를 즉시 차단합니다. 대신 암호화된 값이나 단방향 해시를 64자 상한선 안에서 제공하십시오.
완전히 막아주는 것이 아니라 줄여주는 역할을 합니다. CONSUMPTION_REQUEST는 당신의 증거가 결정 전에 도달하는 단 두 가지 경로 중 하나이며, 전달 및 소비 데이터와 결합된 계정 이력은 Apple이 반품 남용과 프렌들리 프로드를 인식하는 데 도움을 줍니다. 하지만 최종 결정은 여전히 Apple이 내리며, 당신이 이의를 제기할 수 없는 흐름을 통해 들어오는 남용은 그대로 남습니다.



