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 |
다음 단계
- 네이티브 플랫폼별 전용 가이드가 있습니다: Android, iOS, Roku.
- 개념이 처음이라면 SubSovereign 작동 원리를 읽어보십시오.