처음 손실 매출을 감사하러 들어갔을 때, 저는 하마터면 모든 것이 괜찮다고 보고할 뻔했습니다. 환불율은 2.4%로, 어떤 벤치마크로 봐도 양호한 수치였습니다. 팀은 Apple이 정한 기한 내에 소비 요청에 응답하고 있었습니다. 서류상으로는 회수할 것이 없었습니다.
그런데 거의 고집 때문에 쿼리를 하나 더 실행해 보았습니다. Apple이 이미 환불 처리한 거래에 대해 현재 유료 권한을 보유 중인 사용자가 몇 명이나 될까? 41명이었습니다. 유료 구독자가 약 900명인 앱에서요. 결과를 믿을 수 없어서 두 번이나 돌려봤습니다.
이는 전체 사용자 기반의 거의 5%가 대시보드는 녹색을 유지하는 동안 매달 제품을 무료로 사용하고 있었다는 뜻입니다. 그리고 환불율은 전혀 움직이지 않았습니다. 이 권한 수정 작업에 대해서는 환불 후 접근 권한을 회수하는 방법에서 별도로 다뤘습니다.
App Store 환불로 인한 구독 매출을 어떻게 회수할지 고민 중이라면 거기서부터 시작하세요. 환불은 여러분의 매출이 실제로 빠져나가는 네 가지 지점 중 가장 작은 부분에 불과하기 때문입니다. 전체 그림은 이렇습니다.
가치 순으로 정리한 네 가지 영역
저는 이를 네 가지 영역으로 구분해서 생각하는데, 노력 대비 효과 순위는 대부분의 사람들이 예상하는 것과 다릅니다.
유출(The leak): 환불됐지만 접근 권한을 잃지 않은 사용자. 가장 저렴하게 고칠 수 있지만 가장 자주 놓치는 문제입니다.
방어(The defense): 증거를 바탕으로 Apple의 소비 요청에 응답하는 것. 소프트웨어로 자동화할 수 있는 영역이라 모든 벤더가 이야기하는 부분입니다.
재획득(The win-back): 환불하거나 이탈한 사용자를 다시 확보하는 것. 성과가 나타나기까지 가장 오래 걸리지만, Apple이 올해 조용히 이를 더 쉽게 만들었습니다.
재시도(The retry): 손대지 않고 두면 저절로 회복되는 빌링 실패 건들.
대부분의 팀은 두 번째 영역에만 공을 들입니다. 하지만 놀라운 발견은 첫 번째와 세 번째 영역에 있습니다.
첫 번째 영역: 유출 찾기, 한 시간이면 충분합니다
대략적인 쿼리는 이렇습니다. 지난 12개월 내 취소일(revocation date)이 있는 모든 거래를 가져와 권한 테이블과 조인한 뒤, 여전히 활성 접근 권한을 보유한 것으로 표시되는 사용자 수를 세어 보세요.
결과가 정말로 0이라면 이 섹션은 건너뛰어도 됩니다. 하지만 0이 아니라면, 무언가가 차단하기 전까지 매달 빠져나가는 구독 매출을 발견한 것입니다. Apple은 결제를 취소하지만, 여러분의 데이터베이스는 건드리지 않습니다. 이 둘을 직접 연결하기 전까지는 분리된 채로 남아 있습니다. 소모성 상품(Consumables)은 더 심각한데, 한번 사용된 아이템은 StoreKit이 회수할 것이 아무것도 없기 때문입니다.
(저도 몇 달 동안 이 부분을 잘못 처리했습니다. 알림 핸들러는 REFUND 이벤트를 아무도 읽지 않는 테이블에 기록만 하고 있었습니다. 로깅은 처리가 아닙니다.)
해결책은 이렇습니다. REFUND를 수신 대기하고, 취소일에 권한을 회수하며, REFUND_REVERSED가 발생하면 권한을 다시 부여하세요. Apple은 고객 분쟁 이후 간혹 자체적으로 환불을 취소하기도 하는데, 이 경우 고객에게 불이익을 줘서는 안 됩니다.
겸사겸사 쿼리를 하나 더 실행해 보세요. 서버 알림을 전혀 받지 못한 환불 건수를 세어 보는 것입니다. 이 값이 0이 아니라면 엔드포인트가 고장 난 것이고, 두 번째 영역도 마찬가지로 문제가 있는 것입니다.
두 번째 영역: 아직 영향을 줄 수 있는 요청을 방어하세요
Apple은 CONSUMPTION_REQUEST 발생 후 약 12시간 동안 소비 데이터를 전송할 수 있도록 해 줍니다. 필수 필드 3개, 선택 필드 2개, 선호도 필드 1개로 구성되며, 이제는 소모성 상품뿐 아니라 모든 상품 유형을 포괄합니다.
이 영역에 대한 제 조언은 짧습니다. 이미 다른 곳에서 지겹도록 다뤄진 주제이기 때문입니다. 모든 요청에 응답하세요. 상품이 명확히 전달되고 많이 사용된 경우는 거절하세요. 진짜 실수인 경우는 승인하세요. 선의의 양보는 비용이 적게 듭니다. 반면 모든 환불에 맞서 싸우는 것은 그렇지 않은데, Apple이 여러분의 이력에 가중치를 두기 때문입니다.
아무도 언급하지 않는 전제 조건은 바로 증거입니다. 증명할 수 있는 것만 방어할 수 있습니다. 7주 전 구매 건에 대해 "실제로 얼마나 사용했는가"에 아무도 답할 수 없다면, 어떤 자동화도 여러분을 구해줄 수 없습니다. 이는 벤더와 무관하게 메워야 할 데이터 모델링 공백입니다.
비용 측면에 대해서는 환불이 실제로 앱 매출에 미치는 비용에서 환불된 사용자 한 명당 들어간 획득 비용까지 포함해 계산해 두었습니다.
세 번째 영역: 구독자를 다시 되찾으세요
여기서부터는 구독 매출 보호가 더 이상 방어적인 작업이 아니게 됩니다. 그리고 이 영역은 Apple이 지난 1년간 여러분에게 유리한 방향으로 새롭게 구축한 부분이기도 합니다.
Win-back 오퍼. WWDC24에서 새로 도입되었으며 iOS 18 이상에서 사용 가능합니다. App Store Connect에서 구독 상품별로 설정하며, 최소 유료 이용 기간, 마지막 구독 이후 경과 시간, 오퍼 간 2~24개월의 대기 기간 등의 자격 요건을 지정할 수 있습니다. 그 다음부터는 Apple이 배포를 담당합니다. 고객의 구독 관리 페이지, 여러분의 상품 페이지, 개인화된 추천, 때로는 Today 탭의 편집 영역에도 노출됩니다.
다시 한번 읽어보세요. Apple은 여러분의 할인 혜택을 이메일로는 절대 도달할 수 없는 곳에서 이탈한 구독자에게 보여줍니다. 제한 사항: 구독당 350개의 오퍼, 스토어프런트당 5개까지 활성화 가능합니다. 앱 내에서는 사용자가 자격을 갖추게 되면 StoreKit이 winBackOffer 메시지를 발생시키며, 갱신 정보의 eligibleWinBackOfferIDs를 통해 사용할 수 있는 오퍼를 확인할 수 있습니다. Apple의 win-back 설정 가이드에서 자격 요건 필드를 확인할 수 있습니다.
프로모션 오퍼. 구독당 최대 10개까지 가능하며, iOS 12.2부터 존재해 왔고, 서버에서 발급한 JWS 서명이 필요합니다. win-back보다 작업량이 많습니다. 하지만 타기팅을 완전히 직접 제어할 수 있는데, 이는 환불 사유가 특정 국가의 가격 문제처럼 구체적인 정보를 알려줄 때 중요해집니다.
오퍼 코드. 앱 내부나 외부에서 모두 사용할 수 있습니다. 이 덕분에 환불 후 앱을 삭제한 사용자에게 도달할 수 있는 유일한 현실적인 방법이 됩니다. 다른 모든 사용자에게는 앱 내에서 도달할 수 있지만, 이들에게는 그럴 수 없습니다.
구독 갱신일 연장. 제가 보기엔 과소평가된 방법입니다. Apple의 서버 API를 사용하면 구독자의 갱신일을 뒤로 미룰 수 있으며, 거래 하나씩 또는 대량으로 처리할 수 있습니다. 저희는 출시가 잘못됐을 때 호의의 표시로 이를 사용합니다. 누군가 빌링 버그에 대해 고객 지원에 이메일을 보내면, 한 달을 연장해 주는데, 비용이 거의 들지 않으면서도 어떤 쿠폰보다 효과적입니다. 미연에 방지한 환불이 되찾은 환불보다 낫습니다.
단, 한 가지 예외가 있습니다. 누군가 상품 자체가 아니라 예상치 못한 결제 문제 때문에 환불했다면, 할인으로 쫓아가지 마세요. 먼저 페이월 문구를 수정한 다음, 사용자가 스스로 다시 발견하도록 두세요. App Store 환불 관리에서 이러한 운영 측면을 다루고 있습니다.
네 번째 영역: 저절로 해결되는 이탈
Apple은 결제 실패 시 최대 60일 동안 재시도하며, 고객이 카드를 수정하거나 구독을 취소할 때까지 계속합니다. 해당 기간 내에 구독이 갱신되면, 복구일부터 유료 서비스가 계속 제공됩니다.
따라서 손실된 것처럼 보이는 구독 매출 중 상당 부분은 실제로 손실된 것이 아니라 보류 상태였던 것입니다. 이를 망가뜨리는 두 가지 요인이 있습니다. 하나는 켜지 않은 유예 기간이고, 다른 하나는 사실상 사용자에게 취소하라고 말하는 것과 다름없는 결제 독촉 이메일(dunning email)입니다. 유지 도구에 돈을 쓰기 전에 이 두 가지부터 확인하세요.
스스로를 속이지 않고 측정하기
코호트 귀속(cohort attribution) 없는 환불 관리는 확신에 찬 헛소리를 만들어낼 뿐입니다.
각 환불은 환불이 발생한 시점이 아니라 원래 구매가 이루어진 시기에 귀속시키세요. 그런 다음 코호트가 충분히 성숙할 때까지 기다리세요. 월간 플랜은 30~45일, 연간 플랜은 더 길게 잡아야 합니다. 환불 요청이 몇 달 뒤에 들어올 수도 있기 때문입니다.
구독 환불 추적이 어려워지는 지점도 바로 여기이며, 대부분의 대시보드가 슬쩍 속임수를 쓰는 지점이기도 합니다. 11월에 수락된 win-back은 8월에 이탈한 코호트에 속하는 것입니다. 여러분의 리포팅이 이를 연결하지 못한다면, 회수 수치는 허구에 불과합니다.
숫자 하나가 아니라 네 가지 숫자를 추적하세요.
코호트별 환불율.
기한 내 응답한 요청 수.
환불 사유별로 구분한 방어된 매출.
미해결 권한 유출 건수 (0으로 수렴해 유지되어야 함).
대시보드에 딱 하나만 올릴 수 있다면, 저는 유출 건수를 선택하겠습니다. 이는 0이 아닐 때 명백히 잘못된 것으로 판단할 수 있는 유일한 숫자입니다.
솔직히 말해, 소프트웨어가 필요한 지점
두 번째와 네 번째 영역은 깔끔하게 자동화할 수 있습니다. 첫 번째 영역은 한 번만 자동화하면 그 다음부터는 모니터링만 하면 됩니다. 세 번째 영역은 설정과 판단의 문제이며, 어떤 도구도 그 판단을 대신해 주지 않습니다.
Refund Sensor는 양쪽 스토어 모두에서 방어 측면을 처리하며, 거래 증거를 바탕으로 기한 내에 자격을 갖춘 모든 요청에 응답하고 지켜낸 매출을 추적합니다. 하지만 누군가를 다시 되찾아 주거나 혼란스러운 페이월을 고쳐주지는 않습니다. 그건 오직 여러분만이 할 수 있는 일입니다.
출처
자주 묻는 질문
네 가지 방법이 있으며, 제가 시도할 순서대로 나열하면 이렇습니다. 먼저 환불된 거래에 대해 여전히 접근 권한을 보유한 사용자를 찾아 차단합니다. 모든 소비 요청(consumption request)에 12시간 이내로 응답합니다. 이탈한 사용자는 win-back 오퍼나 프로모션 오퍼로 재획득합니다. 그런 다음 빌링 재시도와 유예 기간을 확인하세요. 일부 이탈은 애초에 영구적인 것이 아니었기 때문입니다.
직접적으로는 불가능합니다. Apple은 고객 분쟁 이후 간혹 자체적으로 환불을 취소하고 REFUND_REVERSED 알림을 전송합니다. 이 알림이 도착하면 접근 권한을 복구하세요. 이는 별도로 애써 싸우지 않아도 되는 회수입니다.
Win-back 오퍼는 자동 갱신을 끈 이탈 구독자를 대상으로 하며, 자격 요건은 유료 이용 기간과 마지막 구독 이후 경과 시간을 기준으로 산정됩니다. 환불된 구독도 이탈로 간주되므로 대체로 적용됩니다. 다만 규칙을 설정하고 직접 확인해 보세요.
권한(entitlement) 조회 쿼리입니다. 한 시간이면 끝나고, 외부 벤더도 앱 출시도 필요 없습니다. 제가 이 쿼리를 실행해 본 모든 앱에서 결과는 0이 아니었습니다.
환불 금액 그 이상입니다. 일반적인 비율은 유료 거래의 2%에서 5% 수준입니다. 실제 비용에는 해당 사용자 획득에 들어간 비용, 알림을 놓쳤을 경우 발생하는 권한 유출, 그리고 다음 사용자 획득에 과잉 지출하게 만드는 부풀려진 LTV까지 포함됩니다.
아니요. 유출 문제는 비용 없이 해결할 수 있는 버그입니다. 소프트웨어는 여러분이 응답하지 못하는 요청에 대응해 주는데, 이것도 실제 문제이긴 하지만 최우선 과제는 아닙니다.



