SubSovereign
All guides

SubSovereign on Web & React Native — 통합 가이드

이 가이드는 JavaScript/TypeScript SDK를 다룹니다. 하나의 라이브러리로 세 가지 환경을 지원합니다: React Native (iOS + Android), React Native TV, 그리고 (Stripe 연동). 이 가이드를 따라 하면 앱이 *"누가 결제했는지 전혀 모르는 상태"*에서 *"올바른 사용자에게 올바른 기능을 내 서버에서 직접 검증하여 제공하는 상태"*로 바뀝니다.

SubSovereign이 해주는 것

사용자는 앱 스토어 (Apple, Google) 또는 웹에서 Stripe를 통해 구독합니다. SubSovereign은 앱이 필요로 하는 단 하나의 질문에 신뢰할 수 있는 답을 드립니다: 이 사용자는 실제로 무엇에 결제했는가?

  • 앱이 SubSovereign에 사용자의 이용 권한 — 잠금 해제된 접근 권한 — 을 요청합니다.
  • 영수증 서버 검증은 서버에서 직접 스토어(또는 Stripe)와 통신하여 이루어지므로, 클라이언트를 조작해 구독을 위조할 수 없습니다.
  • 결제 화면은 원격으로 설정되므로, 재배포 없이 가격, 무료 체험 기간, 문구를 변경할 수 있습니다.
  • 자체 호스팅 방식입니다: 내 인프라에서 실행되고, 사용자 데이터는 내 손을 떠나지 않으며, 수익 배분이 없습니다 — 사용자가 결제한 금액의 100%를 그대로 가져갑니다.

클라이언트를 신뢰하지 마십시오. 클라이언트는 요청하고, 서버가 판단합니다.

시작 전 준비

실행 중인 SubSovereign 서버, 대시보드에 등록된 앱 (appIdAPI 키 발급), 그리고 사용자가 구매하는 상품에 연결된 접근 등급 (예: pro)이 필요합니다 — React Native의 경우 App Store / Google Play 상품, 웹의 경우 Stripe 가격 설정을 연결합니다. 실제 결제 처리는 기존 방식대로 진행하십시오 (React Native에서는 인앱 결제 라이브러리, 웹에서는 Stripe Checkout/Billing 사용). SubSovereign은 결제 이후에 이를 검증하고 기록합니다.

1단계 — SDK 설치

npm install @subsovereign/js-sdk
import SubSovereign from '@subsovereign/js-sdk';

2단계 — 앱 시작 시 한 번만 설정

SubSovereign.configure({
  apiKey:  'YOUR_APP_API_KEY',                  // from the dashboard
  appId:   'your-app-id',                       // from the dashboard
  baseUrl: 'https://subs.yourdomain.com/api/v1', // YOUR self-hosted server
  userId:  currentUser.id,                      // your own stable user id
  locale:  'en',                                // the user's language
});

로그인한 사용자에게는 **일관된 userId**를 사용하십시오 — 모든 곳에서 동일한 값을 써야 기기와 플랫폼 전반에 걸쳐 접근 권한이 올바르게 유지됩니다. 다른 사용자가 로그인하면 configure를 다시 실행하십시오.

3단계 — 사용자의 접근 권한 확인

전체 이용 권한 정보는 checkEntitlements()로 확인합니다:

try {
  const result = await SubSovereign.checkEntitlements();
  if (result.hasAccess) unlockProFeatures();
  else showFreeExperience();
} catch (err) {
  // Keep the user on their last-known access and retry later.
  console.warn('Entitlement check failed:', err);
}

단순한 접근 제어에는 편의 함수 hasAccess()를 사용할 수 있습니다. 이 함수는 네트워크 오류 시 안전하게 차단 (false 반환)하므로, 일시적인 오류로 유료 기능이 실수로 열리는 일이 없습니다:

if (await SubSovereign.hasAccess('pro')) unlockProFeatures();

result.entitlements의 각 이용 권한에는 accessLevelId, isActive, expiresAt, willRenew, 그리고 해당 store 정보가 포함됩니다. result.fromCachetrue이면 짧은 장애 중 마지막으로 알려진 캐시에서 응답이 반환된 것입니다.

4단계 — 구독 판매

결제 화면 표시

const paywall = await SubSovereign.getPaywallConfig('web'); // or 'ios' | 'android' | 'firetv' | 'roku'
if (paywall) renderPaywall(paywall);   // headline, features, products…
else renderFallbackPaywall();

결제 완료 후 검증

각 플랫폼의 일반적인 방식으로 결제를 진행한 뒤, 결과를 SubSovereign에 전달하십시오. 그러면 서버가 결제를 검증하고 접근 등급을 부여합니다. 결제가 발생한 플랫폼에 맞는 함수를 호출하십시오:

// Web (Stripe)
await SubSovereign.validateStripeSubscription({
  subscriptionId, productId, accessLevelId: 'pro',
});

// React Native — iOS (StoreKit)
await SubSovereign.validateApplePurchase({ transactionId, productId, accessLevelId: 'pro' });

// React Native — Android (Play Billing)
await SubSovereign.validateGooglePurchase({ purchaseToken, productId, accessLevelId: 'pro' });

서버에서 결제 확인이 완료되면 각 함수는 true를 반환합니다. 이후 checkEntitlements()를 다시 실행하여 잠금을 해제하십시오.

기능 플래그

배포 없이 서버에서 기능을 단계적으로 출시할 수 있습니다:

const flags = await SubSovereign.getFeatureFlags(); // { newPlayer: true, ... }
if (flags.newPlayer) showNewPlayer();

5단계 — 개인정보 보호: GDPR 및 CCPA

await SubSovereign.recordConsent({ purpose: 'analytics', granted: true });

await SubSovereign.requestErasure();            // "forget me"
const myData = await SubSovereign.exportMyData(); // data export
await SubSovereign.setDoNotSell(true);          // CCPA "Do Not Sell" / GPC signal

오류 처리

checkEntitlementsvalidate… 계열 함수는 실패 시 예외를 던집니다try/catch로 감싸고, 오류 발생 시 사용자를 마지막으로 알려진 접근 상태로 유지한 뒤 나중에 재시도하십시오. 일시적인 오류로 결제 사용자를 차단해서는 안 됩니다. 편의 함수들(hasAccess, getPaywallConfig, getFeatureFlags)은 반대로 안전하게 차단하여 false/null/{}을 반환하므로, 인라인 호출에 안전하게 사용할 수 있습니다.

모범 사례

  • 마운트 / 실행 시 확인 — 사용자가 잠긴 기능에 도달하기 전에 접근 제어가 올바르게 적용되도록 합니다.
  • 구매 후 재확인 — UI가 즉시 업데이트되도록 합니다.
  • 클라이언트를 신뢰하지 마십시오 — 서버에 요청하십시오. 영수증 검증은 서버가 합니다.
  • 실제 사용자 한 명당 하나의 userId, 웹과 모바일 전반에 걸쳐 일관되게 유지하십시오.

빠른 참조

원하는 작업 호출
SDK 설정 SubSovereign.configure(config)
사용자의 이용 권한 확인 await checkEntitlements()EntitlementResult
단순 접근 제어 (안전 차단) await hasAccess('pro')boolean
원격 결제 화면 표시 await getPaywallConfig(platform)PaywallConfig | null
Stripe / Apple / Google 결제 검증 await validateStripeSubscription / validateApplePurchase / validateGooglePurchase(…)
기능 플래그 읽기 await getFeatureFlags()
GDPR / CCPA recordConsent · requestErasure · exportMyData · setDoNotSell

다음 단계