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 서버, 대시보드에 등록된 앱 (appId 와 API 키 발급), 그리고 사용자가 구매하는 상품에 연결된 접근 등급 (예: 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.fromCache가 true이면 짧은 장애 중 마지막으로 알려진 캐시에서 응답이 반환된 것입니다.

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

오류 처리

checkEntitlements와 validate… 계열 함수는 실패 시 예외를 던집니다 — 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

다음 단계