모든 글
Deep dive9분 소요

서버가 이미 받고 있는 환불 사유 코드를 읽으면, 앱을 고쳐야 할지 고객과 다퉈야 할지 알 수 있다

Apple과 Google이 서버로 보내는 모든 환불에는 사유 코드가 담겨 있습니다. Google Play는 각 무효화에 아홉 가지 사유 중 하나와 출처를 찍고, Apple은 환불이 앱을 탓하는지 여부를 표시합니다. 각 코드가 무엇을 뜻하는지, 이를 수정, 대응, 수용으로 어떻게 분류하는지, 그리고 금액으로 얼마의 가치가 있는지 설명합니다.

돋보기 옆 종이 라벨에 고무 도장으로 찍힌 코드 표시. 서버가 모든 환불에서 받는 환불 사유 코드를 나타낸다.

핵심 요약

  • Apple이나 Google이 서버로 보내는 모든 환불에는 환불 사유 코드가 담겨 있으며, 돈이 이미 움직인 뒤에도 읽을 수 있는 환불의 유일한 조각입니다. 왜 환불이 일어났는지 알려 주고, 그것이 다음에 무엇을 해야 할지 알려 줍니다.
  • Google Play의 Voided Purchases API는 모든 무효화에 두 개의 숫자를 찍습니다. 0에서 8까지의 voidedReason(기타, 변심, 미수령, 결함, 실수 구매, 사기, 본인 부인 사기, 지불 거절, 미확인 구매)과 0 사용자, 1 개발자, 또는 2 Google의 voidedSource입니다.
  • Apple은 더 좁지만 날카로운 신호를 줍니다. 환불된 거래에서 App Store가 앱 내부의 실제 문제 또는 인지된 문제로 인해 환불한 경우 revocationReason은 1이고, 실수 구매 같은 다른 이유로 환불한 경우에는 0입니다.
  • 코드는 세 무더기로 나뉩니다. 결함, 미수령, 미확인, 그리고 Apple의 앱 내 문제 코드는 제품을 가리키므로 수정합니다. 사기, 본인 부인 사기, 지불 거절은 다투거나 예방하는 분쟁입니다. 변심과 실수 구매는 애초에 막을 수 있는 것이 아니었습니다.
  • voidedReason 8, 미확인 구매는 스스로에게 청구한 환불입니다. Google은 앱이 3일 이내에 확인하지 못한 구매를 자동으로 환불하고 취소하며, 이 코드는 자신의 연동에 있는 그 버그를 찾는 방법입니다.
  • voidedReason 7, 지불 거절은 비용이 큰 것입니다. August 3, 2026 이후에 이루어진 Google Play 주문의 경우, 지불 거절에서 지면 개발자는 구매 가격에서 Play의 서비스 수수료를 뺀 금액에 은행의 지불 거절 수수료를 더해 부담합니다. 그래서 지불 거절로 코드가 찍힌 무효화를 세는 것은 실제로 추가된 비용을 세는 것입니다.
  • Voided Purchases API는 30일만 거슬러 봅니다. 게다가 구매가 언제 일어났는지가 아니라 Google이 무효화를 언제 인지하는지로 필터링하므로, 그 기간 안에 포착하지 못한 사유 코드는 영영 잃는 사유 코드입니다.

Apple이나 Google이 당신의 고객 한 명에게 환불할 때, 돈은 대개 당신이 한마디 하기도 전에 사라집니다. 그 뒤 서버에 도착하는 것은 영수증처럼 보이고, 대부분의 팀은 그것을 영수증처럼 다룹니다. 그것은 그 이상입니다. 모든 환불에는 환불 사유 코드가 담겨 있으며, 결정이 내려진 뒤에도 여전히 읽을 수 있는 환불의 유일한 부분입니다. Google Play는 그 환불이 지불 거절이었는지, 변심에 의한 요청이었는지, 아니면 당신의 앱이 한 번도 확인하지 않은 구매였는지 알려 줍니다. Apple은 그 환불이 앱 내부의 무언가를 탓했는지 알려 줍니다. 그 코드를 읽으면 환불은 보고서의 한 줄이기를 멈추고 지시가 됩니다. 이것을 수정하라, 이것에 대응하라, 아니면 이것은 놓아 주라. 각 코드가 무엇을 뜻하는지, 어떻게 분류하는지, 그리고 각각이 얼마의 비용인지 설명합니다.

환불 사유 코드란 실제로 무엇인가

환불 사유 코드는 구매가 왜 취소되었는지에 대한 스토어 고유의 라벨입니다. 당신이 설정하는 것도 아니고 반박할 수도 없습니다. 사후에 환불에 붙어 도착하며, 두 스토어는 이를 서로 다른 형태로, 매우 다른 해상도로 공개합니다.

Google Play는 모든 무효화에 사유와 출처를 찍는다

Google Play의 Voided Purchases API는 취소된 구매마다 하나의 레코드를 반환하며, 각 레코드에는 중요한 두 개의 정수가 담겨 있습니다. voidedReason은 구매가 왜 무효화되었는지를 말합니다. voidedSource는 그것을 누가 움직였는지를 말합니다. 둘이 합쳐지면 밋밋한 환불이 하나의 문장이 됩니다. 이 주문은 Google이 개시한 지불 거절 때문에 무효화되었다, 혹은 사용자가 개시한 변심으로 무효화되었다. 이것들은 API를 폴링하거나, 무효화가 도착할 때 발생하는 실시간 개발자 알림을 구독하여 읽습니다. 어느 쪽이든 이 두 숫자가 보관할 가치가 있는 페이로드입니다.

Apple은 더 좁지만 날카로운 신호를 준다

Apple은 아홉 갈래의 사유를 건네지 않습니다. 환불된 거래에서 Apple은 revocationReason을 두 값 중 하나로 설정합니다. 1은 App Store가 앱 내부의 실제 문제 또는 인지된 문제 때문에 그 거래를 환불했음을 뜻합니다. 0은 예를 들어 실수 구매처럼 다른 이유로 환불했음을 뜻합니다. 이 필드는 환불되거나 취소된 거래에만, revocationDate와 함께, REFUND App Store Server Notification의 서명된 거래 정보 안에 나타납니다. 두 값은 많지 않지만, 중요한 쪽인 1은 그 환불이 고객의 재고가 아니라 당신의 제품에 관한 것이라고 Apple이 알려 주는 것입니다.

Google Play가 주는 아홉 가지 사유

Google의 voidedReason은 둘 중 더 풍부한 쪽이며, 각각이 서로 다른 곳을 가리키므로 모든 값을 한눈에 알아 둘 가치가 있습니다. VoidedPurchase 리소스에서 그대로 가져온 전체 목록과, 각 코드가 실제로 무엇을 하라고 알려 주는지를 소개합니다.

voidedReasonGoogle의 라벨이 코드가 알려 주는 것
0기타구체적인 사유가 기록되지 않았습니다. 개별 사례가 아니라 전체 건수를 묶어서 주시하세요.
1변심고객이 마음을 바꿨습니다. 앱에는 아무 문제도 없었습니다.
2미수령고객이 지불한 것을 받지 못했다고 말합니다. 확인해야 할 전달 문제입니다.
3결함구매가 작동하지 않았습니다. 제품 버그이며, 이 목록에서 가장 조치 가능한 코드입니다.
4실수 구매잘못된 클릭이나 의도치 않은 구매입니다. 더 명확한 확인 단계를 고려하세요.
5사기Google이 그 거래를 사기로 표시했습니다. 당신의 고객도 아니고, 당신이 가질 수익도 아닙니다.
6본인 부인 사기구매자가 자신이 하고 받은 결제에 이의를 제기했습니다. 이것은 증거가 아직 영향을 줄 수 있는 것입니다.
7지불 거절은행이 결제를 취소했습니다. 가장 비용이 큰 경로이며, 이제 수수료가 붙습니다.
8미확인 구매앱이 구매를 한 번도 확인하지 않아 Google이 자동 환불했습니다. 당신 코드의 버그입니다.

voidedSource는 누가 방아쇠를 당겼는지 알려 준다

사유 옆에는 voidedSource가 있고, 다른 질문에 답합니다. 이것을 취소한 것은 누구인가. 0은 사용자가 셀프서비스나 은행을 통해 했음을 뜻합니다. 1은 개발자, 즉 당신이나 당신의 도구가 환불을 발행했음을 뜻합니다. 2는 Google이 자체 판단으로 했음을 뜻하며, 미확인 구매에 대한 자동 환불도 여기에 포함됩니다. 무효화가 급증하는 것을 볼 때, 출처가 첫 번째 구분점입니다. source 2의 벽은 Google이 당신의 계정에 대해 조치하고 있다는 것이며, 그것은 대개 고객이 아니라 당신의 연동을 되짚어 가리키는 신호입니다.

모든 환불을 수정, 대응, 수용으로 분류하라

코드가 유용한 이유는 그 환불이 세 가지 대응 중 어느 것을 받을 만한지 알려 주기 때문입니다. 대부분의 팀은 모든 환불을 똑같이 다루고, 결코 이길 수 없는 것들에 노력을 태웁니다. 코드는 깔끔하게 나뉩니다.

수정: 당신의 제품이 초래한 환불

어떤 코드는 환불의 옷을 입은 버그 리포트입니다. Google의 결함(3)과 미수령(2), 그리고 Apple의 revocationReason 1은 모두 같은 말을 합니다. 고객은 지불했는데 앱이 전달하지 못했다. 미확인 구매(8)는 그중 가장 날카롭습니다. 잘못이 전적으로 당신의 결제 코드에 있기 때문입니다. 이것들은 없애기에 가장 값싼 환불입니다. 누군가를 설득해서가 아니라 당신이 소유한 것을 수정해서 없애기 때문입니다. 이 무더기에서 건수가 늘어나는 것은 금액이 붙은 제품 결함입니다.

대응: 누군가가 작업하고 있는 환불

사기(5), 본인 부인 사기(6), 지불 거절(7)은 분쟁입니다. 순수한 사기(5)는 당신의 고객이 아니고 애초에 가질 수 없었던 수익입니다. 본인 부인 사기(6)는 구매자가 지불한 그대로를 받고 나서 이의를 제기한 것으로, 당신의 증거가 여전히 움직일 수 있는 유일한 분쟁이며, 지불 거절(7)은 그 증거가 제출되는 곳입니다. 이 중 하나가 도착하면 아직 하지 않았다면 접근 권한을 취소하고, 심사 창이 열려 있는 경우 그 계정에 대해 아는 바로 답합니다.

수용: 애초에 막을 수 없었던 환불

변심(1)과 실수 구매(4)는 고객 자신의 마음 변화입니다. Apple의 revocationReason 0도 여기에 속합니다. 어떤 기능도 실패하지 않았고 어떤 사기도 일어나지 않았습니다. 더 명확한 구매 확인으로 실수 구매 무더기를 누그러뜨릴 수는 있지만, 변심 환불을 말로 물릴 수는 없으며, 그러려고 쓰는 시간은 실제로 돈이 있는 수정 무더기에서 빼앗긴 시간입니다.

무더기Google 코드Apple 신호당신의 조치
수정2 미수령, 3 결함, 8 미확인revocationReason 1그 뒤에 있는 제품 또는 결제 버그의 근본 원인을 찾는다
대응5 사기, 6 본인 부인 사기, 7 지불 거절(사유가 아니라 REFUND로 드러남)접근 권한을 취소하고, 심사 창에 증거로 답한다
수용1 변심, 4 실수 구매revocationReason 0기록하고, 구매 흐름을 다듬고, 넘어간다
작업대 위에서 라벨이 붙은 세 개의 분류 트레이가 분류된 금속 토큰을 받아 내고 있으며, 한 트레이가 더 밝게 비춰지고 있다. 사유 코드로 환불을 수정, 대응, 수용으로 분류하는 것을 나타낸다

사유 코드를 잃기 쉽게 만드는 30일의 함정

Google 쪽에는 이것을 보고 기능에서 마감 기한으로 바꾸는 엄격한 제한이 있습니다. 코드를 지속적으로 포착하고 있지 않다면, 잃고 있는 것입니다.

Voided Purchases API는 30일만 거슬러 본다

Google은 이 API가 지난 30일의 무효화된 구매만 보여 줄 수 있다고 분명히 밝힙니다. 그보다 오래된 무효화는 어떤 startTime을 전달하든 반환되지 않으며, startTime 값 자체도 30일 전보다 이전으로 설정할 수 없습니다. 순진한 연동에 더 나쁜 것은, 이 30일 창이 구매가 언제 이루어졌는지나 레코드의 voidedTimeMillis가 아니라, Google의 시스템이 구매를 무효화로 인지한 시점으로 측정된다는 점입니다. 그래서 그 창 안에서 가져오지 않은 환불 사유 코드는 사라지며, 조금이라도 빈틈이 있는 월간 내보내기 작업은 너무 늦게 잡아 놓친 무효화를 조용히 흘려보냅니다.

사유 코드가 금액으로 얼마의 가치가 있는가

두 코드에는 구체적인 가격이 붙어 있으며, 이를 읽는 것이 그렇지 않으면 합산된 환불률 안에 숨어 버리는 문제에 숫자를 매기는 방법입니다.

어떤 코드는 당신이 스스로 쓴 청구서다

voidedReason 8, 미확인 구매는 당신이 초래한 환불의 가장 명확한 예입니다. Google Play는 권한을 부여한 뒤 3일 이내에 구매를 확인하도록 앱에 요구하며, 그렇게 하지 않으면 Google이 자동으로 주문을 환불하고 항목을 취소합니다. 8이 찍힌 모든 무효화는 제품을 원했던 고객에게서 나온 진짜 매출이며, 구매를 확인하는 호출이 한 번도 발생하지 않아 되돌려진 것입니다. 잃은 금액은 전액 판매 가격에, 그것을 전달하느라 이미 쓴 연산, API 호출, 저장 공간을 더한 것입니다. 이것은 협상하는 환불이 아닙니다. 닫아야 할 버그이며, 코드는 그것을 찾는 방법입니다.

지불 거절 코드에는 이제 수수료가 붙는다

voidedReason 7, 지불 거절은 August 3, 2026에 비용이 바뀌었습니다. 그 날짜 이후에 이루어진 Google Play 주문의 경우, 지불 거절에서 지면 개발자는 구매 가격에서 Play의 서비스 수수료를 뺀 금액에 은행의 지불 거절 수수료를 더해 부담하고, Google은 자신의 서비스 수수료만 부담합니다. 지불 거절 수수료는 정액이고 제품 가격은 그렇지 않기 때문에, 값싼 인앱 구매에서는 수수료만으로 고객이 지불한 금액을 넘어설 수 있습니다. 코드 7 무효화를 세는 것은 이제 단순히 잃은 매출이 아니라 하나의 비용 항목을 세는 것이며, 바로 그래서 당신이 만드는 어떤 환불 보고서에서도 지불 거절 무더기가 자기만의 행을 가질 만합니다.

사유 코드당신이 부담하는 비용이 코드가 중요한 이유
8 미확인 구매고객이 원했던 매출에 대한, 전액 판매 가격에 더한 전달 비용스스로 초래한 것이므로, 코드는 버그 트래커
7 지불 거절 (Aug 3, 2026 이후 주문)구매 가격에서 Play의 서비스 수수료를 뺀 금액에 더한 은행의 지불 거절 수수료잃은 매출 위에 수수료를 더하는 유일한 코드
3 결함판매 가격에 더한 전달 비용이, 그 버그에 부딪히는 고객마다 반복됨이 코드의 건수가 제품 결함을 달러로 가늠함
1 변심판매 가격과, 이미 쓴 전달 비용실제 비용이지만, 코드 변경으로 되찾을 수 있는 것은 아님

Apple과 Google은 어떻게 나란히 서는가

두 스토어는 같은 질문에 서로 다른 해상도로 답하므로, 스토어 간 환불 보고서는 둘이 일치하기를 기대하기보다 정규화해야 합니다.

질문App StoreGoogle Play
코드가 있는 곳REFUND 알림의 서명된 거래 안 revocationReasonVoided Purchases API와 그 알림 안 voidedReason
사유의 개수두 개: 1 앱 내 문제, 0 기타아홉 개, 0 기타부터 8 미확인 구매까지
누가 했는가구분되지 않음voidedSource: 0 사용자, 1 개발자, 2 Google
얼마나 거슬러 읽을 수 있는가조회하면 언제든 거래에서 이용 가능지난 30일의 무효화만
가장 날카로운 신호1은 환불이 제품에 관한 것임을 뜻함코드 3, 8, 7은 각각 뚜렷하고 고칠 수 있는 비용을 가리킴

스토어가 같은 환불에 같은 코드를 주는 일은 결코 없으며, 그래도 괜찮습니다. 중요한 것은 둘 다 기계가 읽을 수 있는 사유를 건네고, 둘 다 그것을 읽는 팀에게 보답한다는 점입니다. Apple의 한 비트는 환불이 제품의 잘못일 때를 알려 줍니다. Google의 아홉 가지 사유와 출처 플래그는 어떤 제품 버그, 어떤 분쟁, 어떤 스스로 초래한 결제 구멍을 보고 있는지 알려 줍니다. 어느 코드도 환불을 멈추지 않습니다. 둘 다 다음 건이 일어나지 않도록 무엇을 해야 할지 알려 줍니다.

RefundHalt는 두 스토어 모두에서 모든 환불의 사유 코드를 도착하는 순간 포착하고, Google의 30일 창 한참 안쪽에서 보관하여 아무것도 새어 나가지 않게 합니다. 각 무효화를 수정, 대응, 수용으로 분류하므로, 코드 3 결함의 급증은 제품 경보로, 코드 8 미확인의 급증은 모호한 수익 하락이 아니라 연동 버그로 당신에게 도착합니다. Apple의 CONSUMPTION_REQUEST에는 12시간 이내에, Google Play의 지불 거절 심사에는 24시간 이내에 답하고, 환불이나 지불 거절이 도착하는 순간 접근 권한을 취소합니다. 스토어가 환불에 찍는 코드를 바꿀 수는 없습니다. 모든 코드를 읽고, 실제로 당신이 고쳐야 할 것들에 대해 행동할 수는 있습니다.

자주 묻는 질문

App Store와 Google Play에서 환불 사유 코드란 무엇인가요?
구매가 왜 취소되었는지에 대한 스토어 고유의 라벨로, 환불과 함께 서버로 전달됩니다. Google Play의 Voided Purchases API는 0에서 8까지의 voidedReason과 0 사용자, 1 개발자, 또는 2 Google의 voidedSource를 반환합니다. Apple은 환불이 앱 내부의 문제 때문이면 revocationReason을 1로, 실수 구매 같은 다른 이유이면 0으로 설정합니다. 코드는 당신이 설정하는 것도 바꿀 수 있는 것도 아니지만, 이를 읽으면 환불이 당신의 제품을 가리키는지, 분쟁을 가리키는지, 아니면 고객의 마음 변화를 가리키는지 알 수 있습니다.
Google Play의 voidedReason 값에는 어떤 것들이 있나요?
아홉 개가 있습니다. 0 기타, 1 변심, 2 미수령, 3 결함, 4 실수 구매, 5 사기, 6 본인 부인 사기, 7 지불 거절, 8 미확인 구매입니다. 각각은 무효화를 누가 개시했는지 말해 주는 voidedSource와 함께 Voided Purchases API가 무효화된 구매마다 반환합니다. 코드 2, 3, 8은 당신 앱의 문제를 가리키고, 코드 5, 6, 7은 분쟁이며, 코드 1과 4는 고객 자신의 결정입니다.
Apple의 revocationReason 1은 무엇을 뜻하나요?
App Store가 앱 내부의 실제 문제 또는 인지된 문제 때문에 그 거래를 환불했음을 뜻하며, 이는 값 0과 대비됩니다. 0은 실수 구매 같은 다른 이유로 환불이 일어났음을 뜻합니다. 이 필드는 환불되거나 취소된 거래에만, revocationDate와 함께, REFUND App Store Server Notification의 서명된 거래 정보 안에 나타납니다. 1은 그 환불이 당신의 제품에 관한 것이라고 Apple이 알려 주는 것입니다.
Google은 왜 미확인 사유 코드로 구매를 환불했나요?
당신의 앱이 제때 구매를 확인하지 않았기 때문입니다. Google Play는 권한을 부여한 뒤 3일 이내에 구매를 확인하도록 요구하며, 그렇게 하지 않으면 Google이 자동으로 주문을 환불하고 항목을 취소하면서 그 무효화에 voidedReason 8을 찍습니다. 이는 고객의 요청이 아니라 결제 버그로 당신이 초래한 환불이므로, 해법은 협상이 아니라 구매 처리 코드 안에 있습니다.
환불 사유 코드는 얼마나 거슬러 읽을 수 있나요?
Google Play에서는 30일뿐입니다. Voided Purchases API는 지난 30일의 무효화를 반환하고 그보다 오래된 startTime은 무시하며, 구매가 이루어진 시점이 아니라 Google이 무효화를 인지한 시점으로 창을 측정합니다. 30일 이내에 포착하지 못한 코드는 사라지므로, 실시간 무효화 구매 알림을 구독하거나 창 한참 안쪽의 일정으로 폴링해야 합니다. Apple의 revocationReason은 조회하면 언제든 거래에 남아 있습니다.

출처 및 추가 자료

RefundHalt

App Store와 Google Play 환불 자동 처리

계속 읽기

다음 환불 요청은 이미 오고 있습니다.

이의를 제기하지 못한 환불에 관한 지원 이메일을 하나 더 읽는 시간이면 RefundHalt 설정을 마칠 수 있습니다.