본문 바로가기

iOS Subscription Group 생성

GitHub

구독 그룹은 iOS 앱에서 여러 구독 등급을 체계적으로 관리하는 데 필수적입니다. 업그레이드, 다운그레이드 및 크로스그레이드 기능을 구현하려면 구독 그룹의 작동 방식을 이해해야 합니다.

구독 그룹이란 무엇인가요?

“구독 그룹이란 무엇인가요?” 섹션

구독 그룹은 사용자가 선택할 수 있는 연관된 구독들의 집합입니다. 사용자는 그룹 내에서 한 번에 하나의 구독만 이용할 수 있습니다. 사용자가 구독을 변경하면 Apple이 전환 과정을 자동으로 처리합니다.

구독 그룹이 중요한 이유

“구독 그룹이 중요한 이유” 섹션

구독 그룹을 통해 다음을 구현할 수 있습니다:

  • 계층형 가격 책정: 베이직, 프리미엄, 얼티밋 플랜 제공
  • 다양한 구독 기간: 월간, 연간 및 평생 이용 옵션
  • 업그레이드/다운그레이드 로직: 구독 변경 사항 자동 처리
  • 간소화된 관리: 관련 구독을 하나의 그룹으로 묶음

그룹 내 각 구독은 가장 높은 가치(레벨 1)부터 가장 낮은 가치 순으로 등급이 매겨져야 합니다. 이 등급에 따라 구독 변경 사항의 분류가 결정됩니다:

구독 그룹 계층 구조

레벨 1 (최고 가치)

  • Premium 연간 플랜 ($99.99/year)
  • Ultimate 월간 ($19.99/month)

레벨 2 (중간 가치)

  • Standard 연간 ($49.99/year)
  • Premium 월간 ($9.99/month)

레벨 3 (가장 낮은 가치)

  • Basic 연간 ($29.99/year)
  • Standard 월간 ($4.99/month)

Apple은 레벨 순위에 따라 세 가지 유형의 구독 변경을 자동으로 처리합니다:

더 높은 등급의 구독으로 변경 (예: 레벨 2 → 레벨 1).

동작 방식:

  • 즉시 적용됨
  • 사용자는 남은 기간에 대해 비례 배분된
  • 환불을 받으며, 새 구독이 즉시 시작됩니다

예시:

// User currently has: Standard Monthly (Level 2)
// User upgrades to: Premium Annual (Level 1)
// Result: Immediate access to Premium, refund for unused Standard time

더 낮은 등급의 구독 플랜으로 변경 (예: 레벨 1 → 레벨 2).

동작 방식:

  • 다음 갱신일에 적용됨
  • 구독 기간이 종료될 때까지 현재 구독 유지
  • 만료 후 새 구독이 자동으로 시작됨

예시:

// User currently has: Premium Annual (Level 1)
// User downgrades to: Standard Monthly (Level 2)
// Result: Premium access continues until annual renewal date, then switches

동일한 티어 레벨의 다른 구독으로 전환 시.

기간에 따른 동작 방식:

기간이 다를 경우 → 다음과 같이 동작: downgrade

  • 다음 갱신일에 적용됨
  • 예시: 월간 Premium (Level 1) → 연간 Premium (Level 1)

동일한 기간 → 다음과 같이 동작 업그레이드

  • 즉시 적용됨
  • 예시: Premium Monthly (Level 1) → Ultimate Monthly (Level 1)

구독 그룹 생성하기

“구독 그룹 생성하기” 섹션
  1. Subscriptions로 이동

    App Store Connect에서 앱을 선택한 후 다음으로 이동: 수익화 > 구독.

  2. 그룹 생성

    클릭 + “Subscription Groups” 옆의 버튼을 눌러 새 그룹을 생성합니다.

  3. 그룹 이름 지정

    포함된 구독 상품을 잘 나타내는 이름을 선택하세요:

    • “Premium Access”
    • “Cloud Storage 요금제”
    • “Pro 기능”
  4. 구독 상품 추가

    그룹을 생성한 후 개별 구독 상품을 추가합니다. 각 구독 상품에는 레벨 순위가 부여됩니다.

  5. 레벨 순위 설정

    가장 높은 가치(1)부터 낮은 가치 순으로 구독 상품을 배치합니다. 다음 사항을 고려하세요:

    • 일반적으로 연간 플랜이 월간 플랜보다 순위가 높습니다
    • 가격이 높은 티어가 낮은 티어보다 상위에 위치합니다
    • Ultimate/premium 티어가 가장 높은 순위를 차지합니다

native-purchases 플러그인이 구독 그룹 로직을 자동으로 처리합니다:

import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
// Fetch all subscriptions in a group
const { products } = await NativePurchases.getProducts({
productIdentifiers: ['premium_monthly', 'premium_annual', 'ultimate_monthly'],
productType: PURCHASE_TYPE.SUBS,
});
// Display current subscription using StoreKit transactions
const { purchases } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.SUBS,
});
const activeSubs = purchases.filter((purchase) => purchase.isActive);
// Detect pending downgrade/cancellation (StoreKit sets willCancel === true)
const pendingChange = purchases.find((purchase) => purchase.willCancel === true);
if (pendingChange) {
console.log('Subscription will stop auto-renewing on', pendingChange.expirationDate);
}
// Purchase (StoreKit handles upgrades/downgrades automatically)
await NativePurchases.purchaseProduct({
productIdentifier: 'premium_annual',
productType: PURCHASE_TYPE.SUBS,
});
// Listen for StoreKit updates (fires on upgrades/downgrades/refunds)
NativePurchases.addListener('transactionUpdated', (transaction) => {
console.log('Subscription updated:', transaction);
});

구독 변경 사항 처리

“구독 변경 사항 처리” 섹션
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
// Get current subscription info
const { purchases } = await NativePurchases.getPurchases({
productType: PURCHASE_TYPE.SUBS,
});
const currentSubscription = purchases.find(
(purchase) => purchase.subscriptionState === 'subscribed',
);
if (currentSubscription) {
// StoreKit reports if user cancelled auto-renew
if (currentSubscription.willCancel) {
console.log(
`User cancelled. Access remains until ${currentSubscription.expirationDate}`,
);
}
if (currentSubscription.isUpgraded) {
console.log('User recently upgraded to this plan.');
}
}
// Listen for automatic upgrades/downgrades
NativePurchases.addListener('transactionUpdated', (transaction) => {
console.log('Subscription changed!', transaction);
if (transaction.subscriptionState === 'revoked') {
revokeAccess();
} else if (transaction.isActive) {
unlockPremiumFeatures();
}
});

사용자 커뮤니케이션

“사용자 안내” 섹션

변경 사항은 항상 명확하게 안내하세요:

업그레이드 시:

“Premium 기능을 즉시 이용할 수 있습니다. 현재 구독 요금은 일할 계산됩니다.”

다운그레이드 시:

“[갱신일]까지 Premium 이용 권한이 유지되며, 이후 Standard로 전환됩니다.”

플랜 변경(Crossgrade) 시:

“다음 갱신일인 [날짜]에 연간 결제 플랜으로 변경됩니다.”

Apple의 App Store Server Notifications v2 또는 자체 영수증 검증 백엔드를 사용해 StoreKit 변경 사항을 데이터베이스에 반영하세요. 서버 알림을 transactionUpdated 리스너와 함께 사용하면 클라이언트와 백엔드가 동기화된 상태를 유지합니다.

  • 관련된 구독 상품은 동일한 그룹에 유지하세요
  • 서로 관련 없는 기능(예: 스토리지와 광고 제거)을 섞지 마세요
  • 기능 세트별로 별도의 그룹을 생성하세요
  • 연간 플랜 → 동일 티어 내에서 월간 플랜보다 높은 레벨 설정
  • 가격이 높은 티어 → 더 높은 레벨 설정
  • 단순 가격이 아닌 가치를 고려하세요
  • 현재 구독 상태를 명확하게 표시
  • 그룹 내 사용 가능한 모든 옵션 표시
  • 즉시 적용되는 변경 사항과 갱신 시 적용되는 사항 구분
  • 플랜 간의 간편한 전환 지원
  • 모든 업그레이드 시나리오 테스트
  • 모든 다운그레이드 시나리오 테스트
  • 크로스그레이드(Crossgrade) 동작 확인
  • webhook 호출 여부 확인

시나리오 1: 3단계 월간 요금제

“시나리오 1: 3단계 월간 요금제” 섹션
Level 1: Ultimate Monthly ($19.99)
Level 2: Premium Monthly ($9.99)
Level 3: Basic Monthly ($4.99)
  • Basic → Premium: 업그레이드 (즉시 적용)
  • Premium → Ultimate: 업그레이드 (즉시 적용)
  • Ultimate → Premium: 다운그레이드 (갱신 시 적용)
  • Basic → Ultimate: 업그레이드 (즉시 적용)

시나리오 2: 혼합 기간 요금제

“시나리오 2: 혼합 기간 요금제” 섹션
Level 1: Premium Annual ($99.99/year)
Level 2: Premium Monthly ($9.99/month)
  • 월간 → 연간: 크로스그레이드 (갱신 시 적용)
  • 연간 → 월간: 다운그레이드 (갱신 시)

시나리오 3: 멀티 티어 및 멀티 기간

“시나리오 3: 다중 티어 및 다중 기간” 섹션
Level 1: Ultimate Annual ($199/year)
Level 2: Ultimate Monthly ($19.99/month)
Level 3: Premium Annual ($99/year)
Level 4: Premium Monthly ($9.99/month)
Level 5: Basic Annual ($49/year)
Level 6: Basic Monthly ($4.99/month)

이 설정은 명확한 업그레이드/다운그레이드 로직을 유지하면서도 최대한의 유연성을 제공합니다.

그룹에 구독 항목이 나타나지 않는 경우:

  • 올바른 그룹에 할당되었는지 확인하세요
  • 상태가 최소 “Ready to Submit”인지 확인하세요
  • Product ID가 정확한지 확인하세요

업그레이드/다운그레이드 동작이 잘못된 경우:

  • 등급 순위 확인 (1 = 가장 높음)
  • 구독 티어 구성이 적절한지 확인
  • 등급 설정이 올바른지 확인

서로 다른 그룹의 상품:

  • 사용자는 여러 그룹을 동시에 구독할 수 있음
  • 이는 의도된 동작입니다. 관련 상품은 동일한 그룹에 유지하세요.

getActiveProducts에서 여러 구독이 표시되는 경우:

  • 구독 상품들이 서로 다른 그룹에 있는지 확인
  • 가족 공유를 통해 구독 중인지 확인
  • App Store Connect에서 구독 상태 확인

자세한 내용은 구독 그룹에 관한 Apple 공식 문서.

iOS Subscription Group 생성 단계부터 계속하기

섹션 제목: “Create iOS Subscription Group”에서 계속하기

사용 중이라면 iOS Subscription Group 생성 스토어 승인 및 배포를 계획하려면, 다음 항목과 연결하세요 @capgo/native-purchases 사용하기 @capgo/native-purchases 사용 시 네이티브 기능을 위해, @capgo/capacitor-in-app-review @capgo/capacitor-in-app-review의 구현 세부 사항에 대해서는, @capgo/capacitor-in-app-review 사용하기 @capgo/capacitor-in-app-review 사용하기에서 네이티브 기능은, @capgo/capacitor-native-market @capgo/capacitor-native-market의 구현 세부 사항에 대해서는, 그리고 @capgo/capacitor-native-market 사용하기 @capgo/capacitor-native-market. 사용하기에서 네이티브 기능은