Table of contents

In-App Purchases: Auto-Renewable Subscriptions Tutorial에서 필요한 부분을 의역했습니다.

Auto-renewable subscripiotns을 앱의 콘텐츠의 지속적인 접근을 제공하여 유저에게 좋은 사용자 경험과 매력적인 비즈니스 모델을 제공합니다.


Auto-renewable subscription은 훌륭합니다. 앱이 consistent or renewable 콘탠츠를 제공한다면 In-App Purchase subscriptions을 제공하는게 좋을 방법일수 있습니다.

Auto-renewable subscriptions을 구독하면 첫해애 7:3 비율로 수익을 얻고 그 구독이 유지되어 한해가 넘어가면 8.5:1.5 수익 점유율이 증가됩니다.

Note: 유저가 구독을 취소하고 60일 이내에 갱신하지 않거나 다른 구독 그룹으로 전환하면 1년 일수 계산이 초기화 됩니다. 그래서 구독이 사용자에게 장기적으로 유지하고 싶은 경험을 제공하는지 확인하세요.

Getting Started

필요한것 (1) 개발자 계정이 active 상태여야 합니다 (2) 실제 테스트 디바이스가 있어야 합니다. IAP subscriptions 구독을 실험 하기위해 Words of Wisdom by Winnie the Pooh 앱을 사용 할것입니다.

앱의 초기 버전의 하나의 auto-renewable IAP를 제공하고 한달동안 무작위로 지혜로운 말들을 받을수 있는 권리를 제공 받습니다. 또한 사람들은 더 오랫동안 이것이 유지되길 원해서 년간 구독을 옵션을 제공 해야 할것입니다.

여기에 몇가지 알아두어야 하는 사항들이 있습니다.

  • 이 셈플 앱에는 하드코딩된 Product Identifiers들을 사용해야 합니다. 실제로 서버에서 이값들을 가져오는것을 선호할 것입니다.
  • 유저가 구매한 제품을 나타내기 위해 UserDefaults를 사용 할것입니다. 실제 앱에서는 receipt validation을 이행하거나 물품을 로컬에 저장 하지 말아야 합니다.

이제 튜토리얼 여기를 눌러서 샘플앱을 다운로드 합니다.

Setting Up the Project

프로젝트와 App Store connect 둘다 변경이 필요합니다.

  1. 새로운 Bundle ID를 생성합니다.
  2. App Store Connect 에서 모든 법적 동의서를 수락 했는지 확인합니다.
  3. 해당 BundleID로 App Store Connect에 App을 생성합니다.
  4. 요구된 필드를 채우고 Auto-Renewable Subscription 제품을 생성합니다.

auto-renewable subscription을 생성하는 과정에서 subscription group 을 정의 하라고 할것입니다. A subscription group은 기본적으로 구독 상품의 모음 입니다. 다음 색션에서 구독 그룹에 대해 더 자세히 알수 있습니다. 새로운 auto-renewable subscription을 위한 새로운 구독 그룹을 생성하세요. 구독 그룹의 이름은 PoohWisdomSubs 라고 명명합니다.

메타 데이터 정보들을 채우세요

Subscription Duration 필드를 확인 하세요. 유저가 갱신을 취소하지 않으면 자동으로 구독이 갱신되는 기간입니다. 많은 경우에 various IAP이 제공하는 차이는 기간과 가격 일것입니다. 콘텐츠 자체는 변하지 않고 사용자는 동일한 콘텐츠에 접근하기 위해 여러 구독 옵션 중에 선택할것 입니다.

1개월 0.99 달러로 가격을 설정하세요.

subscription group은 PoohWisdomSubs을 선택하고, 현지화를 추가합니다.

이것을 완료하면 인앱 상품의 Status가 Ready to Submit 으로 변경됩니다.

  1. 이전단계에서 App, Product Identifier를 복사하여 간단하게 접근할수 있습니다
  2. 프로젝트로 돌아가기 전에 sandbox user 테스터를 생성하는 것 입니다. 실제로 접근할 수 있는 실제 이메일 주소를 사용해야 접근할수 있습니다.

이제 프로젝트를 시작할 시간입니다.

  1. Bundle Identifier를 생성한것으로 교체하세요
  2. General 탭에 Team을 변경하세요
  3. com.razeware.poohWisdom.monthlySub 검색해서 IAP의 Product ID를 교체하세요

다음으로 testing 할 디바이스의 Settings 앱을 열고 iTunes & App Store를 엽니다.


애플 아이디를 탭한 후 로그아웃을 합니다. 이 시점에서는 sandbox user로 로그인 하지마세요. ㅇ앱에서 IAP를 구매하려고 할때 등록할것입니다.

Not purchased: $MyIAPID
Loaded list of products...
Found product: $MyIAPID $GroupID $Pricing

이 메시지를 본다면 auto-renewable IAP는 동작하고 있는것 입니다.

만약 아무것도 볼수 없다면 아래 중 한가지를 놓친게 있는지 확인 하세요.

  • App Store Connect에서 모든 설정을 완료 했는지?
  • IAP product state가 Ready to Submit으로 변경 되었나요?
  • 프로젝트의 General 탭에서 Bundle identifier 설정 했는지?
  • com.razeware.poohWisdom.monthlySub 이걸 변경된 ProductID로 설정 했는지

Purchase 버튼을 터치합니다.

App Store Connect에 만든 sandboc account 계정의 username 과 password를 입력하고 OK 버튼을 누릅니다. 모든게 제대로 됬다면 first winnie the Pooh quote를 봐야합니다.

StoreKit과 여기에서 일어나는 것들이 조금 흥미롭다면 Getting Started tutorial 에서 자세히 알수 있습니다(이것을 마지막에 언급할것이라고 약속합니다. 이제 이것들을 해결 하였으니 subscriptions groups 와 함께 auto-renewable subscription 들을 알아볼것 입니다.

Subscription Groups

App Store Connect에서 auto-renewable subscription을 설정할때 subscription group concept를 마주했습니다. 앞에서 언급한것 처럼 기본적으로 subscription 상품들의 그룹이지만 이것들은 좀더 많은 의미를 가지고 있습니다.

각 구독은 반드시 구독 그룹에 포함되어 있어야 하는것을 알고있습니다. 유저는 가격과 기간에 따라서 상품을 선택 할수 있습니다.

유저는 하나의 그룹내에서 하나의 구독권만 구매할수 있습니다. 사용자가 실수로 동일한 콘텐츠에 대한 접근 권한을 구매하여 여러 구독 상품 구매를 방지 할수 있습니다. 이 경우를 방지하기 위해 필요한 것은 모든 관련 구독 상품에 대해 단일 구독 그룹을 생성하는것 입니다.

여러개의 구독 상품을 제공하기를 원하는 경우 여러개의 구독 그룹을 사용해야 합니다. 이럴 경우 사용자가 여러 구독 서비스에 가입하고 있고 단일 구독 상품만 기대하지 않는다는 것을 이해 시켜야 합니다. 그렇지 않으면 구독 취소와 부정적인 리뷰를 남길수 있고 결국 다른 사용자가 가입 하는것을 막고 아무도 그것들을 원하지 않을수 있습니다.

이러한 상황을 방지하기 위해서는 구독 옵션이 명확하고 이해하기 쉬운지 확인 해야 합니다. 구독 그룹 이름은 개발자 에게만 보이므로 적절하게 사용해야합니다.

각 그룹내에 subscriptions의 순위를 매길수 있습니다. 기간에 관계없이 가장 많은 기능과 콘텐츠에 접근하는 그룹을 최상위 티어로 설정 해야 합니다. 각 레벨에서 제공하는 수준이 동일 하면 여러개의 구독을 가질수 있습니다. 이것들을 그룹내에 드레그 하여 설정할수 있습니다. 이들을 같은 수준으로 설정하기 위해 다른 하나를 상단으로 드레그 합니다.

유저는 App Store에 account’s 구독 페이지내에서 이 구독들으 downgrade, crossgrade, upgrade 할수 있습니다.

  • upgrades: 사용자가 업그레이드로 전환하면 즉시 효력이 발생하고 기존 구독 금액의 일부를 환불 받습니다
  • downgrade: 사용자가 다운그레이드를 하면 다음 갱신일까지 기존 구독이 이루어지다가 한단계 낮은 구독으로 갱신 됩니다.
  • crossgrades: 구독 기간이 같으면 바로 즉시 신규 구독이 시작되고 그렇지 않으면 다음 갱신일에 신규 구독이 적용 됩니다.

Note: 이들 중 어느것도 1년 구독 서비스 카운팅에 영향을 주지 않으면 다른 구독 그룹으로 이동하면 카운팅 일수가 재설정 됩니다.

Adding More Subscriptions

이제 앱에 또 다른 auto-renewable subscriptions을 추가할것입니다. 년간 상품이고 기존 구독과 같은 유형의 콘텐츠를 제공하기 때문에 동일한 레벨로 유지할수 있습니다.

App Store Connect로 가서 상품을 추가하면 됩니다. 신제품에 대한 구독 그룹을 선택 하라는 메시지가 뜨면 PoolWisdomsSubs 를 선택하면 됩니다.

구독 기간을 1년으로 설정하고 필요한 메타 정보들을 넣고 아이템을 생성합니다. 그리고 Product ID를 복사합니다

이제 Xcode로 돌아가서

Main.storyboard를 열고 Purchase 버튼 타이틀을 Subscriptions 로변경합니다.

viewController.swift 로 돌아가서 displayRandomQuote() 를 찾고 아래 코드를 삭제합니다.

purchaseBttn.isHidden = true

이렇게 하면 구독 상품을 구매후 다른 상품을 구매할수 있게 유지시켜 줍니다.

이제 purchaseSubscription(_:) 를 찾고 buyProduct 클로저를 purchaseItemIndex(index: Int) 라고 부르는 새로운 매소드로 이동 시킵니다. index parameter는 절대 사용되지 않고 첫번째 라인의 produts[0]을 products[index]로 변경합니다.

PoohWisdomProducts.store.buyProduct(products[index]) { [weak self] success, productId in
  guard let self = self else { return }
  guard success else {
    let alertController = UIAlertController(title: "Failed to purchase product",
                                            message: "Check logs for details",
                                            preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "OK", style: .default))
    self.present(alertController, animated: true, completion: nil)
    return
  }
  self.displayRandomQuote()
}

이제 유저의 선택에 따라서 관련 있는 구독 상품을 구매할수 있습니다. products[index]에 전달된 값을 기반으로 구독을 선택할것입니다.

pruchaseSubscriptions(_:) 으로 돌아가고 유저가 선호하는 구독을 선택할수 있게 alert을 추가 해야합니다. guard: 아래에 다음 코드를 추가합니다.

let alertController = UIAlertController(
  title: "Choose your subscription",
  message: "Which subscription option works best for you",
  preferredStyle: .alert)

alertController.addAction(
  UIAlertAction(title: "Monthly",
                style: .default,
                handler: { action in
                  self.purchaseItemIndex(index: 0)})
)

alertController.addAction(
  UIAlertAction(title: "Yearly",
                style: .default,
                handler: { action in
                  self.purchaseItemIndex(index: 1)})
)

present(alertController, animated: true, completion: nil)

방금 월간/년간 구독설정을 할수 있는 AlertController를 추가 했습니다. 인덱스로 식별된 이 Alert 에서 사용자의 선택에 따라 앱 스토어에 관련 구독을 구매하라는 요청을 보낼 것 입니다.

이제 남은것은 실제로 두 가지 구독 옵션을 선택할수 있도록 Product ID를 배열에 추가하는 것 입니다.

PoohWisdomProducts.swift 로 갑니다. 그리고 poohWisdomSub의 이름을 monthlySub 으로 변경합니다. 그후 새로운 product ID를 추가하고 yearlySub 이라고 명명합니다.

public static let monthlySub = "com.razeware.poohWisdom.monthlySub"
public static let yearlySub = "com.razeware.poohWisdom.yearlySub"

그후 productIDs 의 배열을 다음 처럼 수정합니다.

private static let productIDs: Set<ProductID> =
  [PoohWisdomProducts.monthlySub, PoohWisdomProducts.yearlySub]}

이제 ProductIDs 는 두개의 구독 상품이 있고 구독 알람에서 유저의 선택에 기반해서 에플 서버에서 관련된 하나의 요청을 보낼것입니다.

마지막으로. ViewController.swift 로 가서 viewDidLoad() 에서 두 가지 사용가능한 구독 중 하나를 하나(poohWisdomSub)를 구매하였는지 체크하는 조건문을 다음처럼 변경합니다.

if (PoohWisdomProducts.store.isProductPurchased(PoohWisdomProducts.monthlySub) ||
  PoohWisdomProducts.store.isProductPurchased(PoohWisdomProducts.yearlySub)){
  displayRandomQuote()
} else {
  displayPurchaseQuotes()
}

이제 유저가 구매했다면 인용구를 보여줄 것 입니다.

Seeing it All Come Together

이제 모든걸 완료 했고 테스트 할때입니다. 년간 구독권을 구매하면 다음 과같은 알랏 화면을 볼수 있습니다.

년간 구독 구매 테스트를 하고 싶다면 샌드박스 유저를 생성 해야 합니다.

이것들을 마무리 하기전에 테스트 하는것은 중요합니다. 예외 케이스들은 눈에 띄지 않을수 있기 때문입니다. 따라서 auto-renewable subscriptions이 sandbox 와 production 환경에서 어떻게 다른지 알아야 합니다.

auto-renewable 을 몇년, 몇달 걸려서 테스트하길 원하지 않기 때문에 테스트 환경에 있는 동안은 갱신 기간은 빠르게 종료 됩니다.

추가로 renewable은 하루에 6회로 갱신이 제한되어 있습니다. 그러므로 따라서 다양한 시나리오를 테스트하려면 여러개의 테스트 유저로 테스트 하고 있는 자신을 발견할것입니다 :).

Auto Renewable Subscriptions Best Practices

  • 앱에서 Product IDs들을 하드코딩 하지말고 서버에서 가져와야 하는것을 알고 있습니다. 이것은 어떤 옵션을 제공하던지 더 유연함을 가져다 줍니다.
  • 가격, 설명 그외 다른 subscription 데이터들을 절대 저장하지 말아야 합니다. 최신 데이터를 위해서는 항상 애플에 의존해야 합니다. 사용자가 새로운 버전으로 업그레이드 하지 않고 가격 변경 및 프로모션을 제공할수 있습니다.
  • 앱 내에서 구독 관리 옵션을 제공 하는것을 생각 해야합니다. 특정 앱을 위한 맞춤 구독 경험을 제공함 기회를 줄 것입니다. 업그레이드, 크로스그레이드 등 상황에 맞는 경험을 제공하는 동시에 사용자가 구독을 취소하기로 결정할 경우에 대한 deeplink를 제공할수 있어야 합니다.
  • 사용자가 구입하려는 것을 정확하게 알 수 있도록 구독을 명확하게 설명해야 합니다. 이는 더 많은 가입자를 유치하는데 도움이 될 뿐만 아니라 상품이 생각과 다를 경우 좌잘하는 사용자를 막는데 도움이 됩니다.
  • 추가로 새로운 구독자를 끌어 당기기 위해 어느정도 고민이 필요합니다. 그 중 가격에 관심이 있을수 있는데 이것은 새로운 사용자들에게는 괜찮지만 기존 사용자는 어떨까요? 기존 사용자들이 사용하는 가격을 그대로 유지하고 신규 사용자 가격만 올릴수도 있고 모두 올릴수도 있습니다. 먼저 현재 가격에 가장 가까운 사용자 다음으로 근접한 사용자의 가격등을 인상 해야 합니다 그렇지 않으면 사용자는 애플에 의해 더 높은 가격을 받아들이라는 여러번의 지시를 받을 수도 있습니다
  • 가장 중요한 것은 애플의 가이드라인을 항상 인지하는것 입니다. iOS 전반도 마찬가지 이지만 이건 In-App Purchases 튜토리얼 이기 때문에 관련 가이드라인 을 살펴보고 앱 작업을 시작하기 전에 확인 해야 합니다.