구독이 포함된 Android SaaS 앱: 2025년 완전 가이드

발행: (2025년 12월 13일 오후 10:08 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

Market Context 2025

전 세계 SaaS 시장 규모는 2025년 기준 4,082.1 억 USD 로 추정되며, 2034년에는 12,513.5 억 USD에 이를 것으로 전망됩니다.
구독 결제 관리 시장은 2030년까지 179.5 억 USD에 도달할 것으로 예상되며, 연평균 성장률(CAGR)은 16.9 %입니다.

1. Google Play Billing Library

Current Version

  • Play Billing Library 7.x (2025년 8월까지 필수)
  • 중요 마감일: 2025년 8월 31일까지 모든 신규 앱 및 업데이트는 Billing Library 7 이상을 사용해야 합니다. 확장 프로그램은 2025년 11월 1일까지 제공됩니다.

Key Features in Version 7.0+

  • 할부 구독 – 사용자가 더 작고 관리하기 쉬운 할부로 결제 (브라질, 프랑스, 이탈리아, 스페인에서 이용 가능)
  • 구독에 대한 보류 중 거래 – 활성화 전 SUBSCRIPTION_STATE_PENDING 상태 처리
  • ReplacementMode API – 업그레이드/다운그레이드 시 기존 ProrationMode를 대체
  • User Choice Billing – 대체 결제 옵션을 위한 enableUserChoiceBilling()

Implementation

// build.gradle.kts
implementation("com.android.billingclient:billing-ktx:7.1.1")

// Initialize BillingClient
val billingClient = BillingClient.newBuilder(context)
    .setListener { billingResult, purchases ->
        // Handle purchase updates
        purchases?.forEach { purchase ->
            if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
                // Verify on backend, then acknowledge
                verifyAndAcknowledge(purchase)
            }
        }
    }
    .enablePendingPurchases(
        PendingPurchasesParams.newBuilder()
            .enablePrepaidPlans()
            .build()
    )
    .build()

// Connect to Google Play
billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
            querySubscriptions()
        }
    }
    override fun onBillingServiceDisconnected() {
        // Implement retry logic
    }
})

// Query available subscriptions
fun querySubscriptions() {
    val params = QueryProductDetailsParams.newBuilder()
        .setProductList(
            listOf(
                QueryProductDetailsParams.Product.newBuilder()
                    .setProductId("premium_monthly")
                    .setProductType(BillingClient.ProductType.SUBS)
                    .build(),
                QueryProductDetailsParams.Product.newBuilder()
                    .setProductId("premium_yearly")
                    .setProductType(BillingClient.ProductType.SUBS)
                    .build()
            )
        )
        .build()

    billingClient.queryProductDetailsAsync(params) { billingResult, productDetailsList ->
        // Check for installment plans (PBL 7+)
        productDetailsList.forEach { product ->
            product.subscriptionOfferDetails?.forEach { offer ->
                offer.installmentPlanDetails?.let { installment ->
                    // Handle installment subscription display
                    val commitments = installment.installmentPlanCommitment
                }
            }
        }
    }
}

// Launch purchase flow
fun launchPurchase(activity: Activity, productDetails: ProductDetails, offerToken: String) {
    val flowParams = BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(
            listOf(
                BillingFlowParams.ProductDetailsParams.newBuilder()
                    .setProductDetails(productDetails)
                    .setOfferToken(offerToken)
                    .build()
            )
        )
        .build()

    billingClient.launchBillingFlow(activity, flowParams)
}

Google Play Commission Rates 2025

ScenarioRate
첫 $1 M 연간 매출15 %
첫 해 이후 구독15 %
첫 해 구독 (표준)30 %

2. 2025 Policy Update: Alternative Billing in the US

Major Change (October 2025)

Epic Games 판결 이후, Google은 이제 미국 개발자들이 대체 결제 수단을 제공하도록 허용합니다:

  • Google Play Billing만을 독점적으로 사용할 필요 없음
  • 개발자는 대체 결제 옵션에 대해 사용자와 커뮤니케이션 가능
  • 결제 수단에 따라 가격 제한이 없음
  • Stripe, PayPal, 혹은 자체 솔루션을 통해 결제 처리 가능

External Offers Program (EEA)

유럽 경제 지역(EEA)에서는 개발자가 앱 외부에서 사용자를 유도해 오퍼를 홍보할 수 있으며, 이는 Google Play 결제 정책을 따릅니다.

// User Choice Billing implementation
val billingClient = BillingClient.newBuilder(context)
    .enableUserChoiceBilling(UserChoiceBillingListener { userChoiceDetails ->
        // User selected alternative billing
        val externalTransactionToken = userChoiceDetails.externalTransactionToken
        // Process with your payment provider
        processAlternativePayment(externalTransactionToken)
    })
    .build()

3. Third‑Party Subscription Platforms

RevenueCat

가장 인기 있는 크로스‑플랫폼 구독 관리 SDK.

// Setup
Purchases.configure(
    PurchasesConfiguration.Builder(context, "your_api_key")
        .appUserID(userId)
        .build()
)

// Fetch offerings
Purchases.sharedInstance.getOfferingsWith(
    onError = { error -> /* Handle error */ },
    onSuccess = { offerings ->
        offerings.current?.availablePackages?.let { packages ->
            // Display subscription options
        }
    }
)

// Make purchase
Purchases.sharedInstance.purchase(
    PurchaseParams.Builder(activity, packageToPurchase).build(),
    onError = { error, userCancelled -> },
    onSuccess = { storeTransaction, customerInfo ->
        if (customerInfo.entitlements["premium"]?.isActive == true) {
            // Unlock premium features
        }
    }
)

// Check subscription status
Purchases.sharedInstance.getCustomerInfo(
    onError = { /* Handle */ },
    onSuccess = { customerInfo ->
        val isPremium = customerInfo.entitlements["premium"]?.isActive == true
    }
)

Pricing: 월 $2,500 MTR까지 무료, 이후 MTR의 1 % 차감.

Adapty

더 정교한 A/B 테스트 기능을 제공하는 강력한 대안.

Advantages over RevenueCat

  • 보다 정교한 다변량 페이월 테스트
  • 무료 플랜에서도 더 많은 분석 지표 제공
  • 실시간 대시보드 데이터
  • 빠른 고객 지원 응답 시간
  • 세부 제어가 가능한 노코드 페이월 빌더

Pricing: 월 $99 부터 시작.

Comparison Table

FeatureRevenueCatAdapty
SDK PlatformsiOS, Android, Flutter, RN, Unity, Cordova, IoniciOS, Android, Flutter, RN, Unity
Free Tier Analytics6 metrics10+ metrics
Real‑time DataNoYes
A/B TestingBasicAdvanced multivariate
Paywall BuilderNative (Paywalls v2)No‑code drag‑drop
Starting PriceFree / $8 mo$99 /mo

4. Backend Architecture with Supabase

Supabase는 PostgreSQL, 인증, 실시간 기능을 갖춘 오픈소스 백엔드로 SaaS 앱에 최적입니다.

Database Schema for Subscriptions

-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Users table
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    email TEXT NOT NULL UNIQUE,
    password_hash TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);

-- Subscriptions table
CREATE TABLE subscriptions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    product_id TEXT NOT NULL,
    purchase_token TEXT NOT NULL,
    status TEXT NOT NULL CHECK (status IN ('active','canceled','past_due','expired')),
    period_start TIMESTAMP WITH TIME ZONE NOT NULL,
    period_end TIMESTAMP WITH TIME ZONE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);

-- Indexes for fast lookup
CREATE INDEX idx_subscriptions_user_id ON subscriptions(user_id);
CREATE INDEX idx_subscriptions_status ON subscriptions(status);

Supabase의 Row‑Level Security(RLS) 정책을 사용해 사용자가 자신의 구독 레코드만 읽고 쓸 수 있도록 제한하고, Google Play 구매 알림을 처리하기 위한 웹훅 리스너를 연동해 실시간 상태 업데이트를 구현합니다.

Back to Blog

관련 글

더 보기 »

프로필

현재 상태 🟢 인턴십 및 초급 기회에 열려 있음 Mission: 52주 안에 30개의 앱을 만들어 세계 수준의 Android 엔지니어가 되기. 저는 열정입니다...

Universal & Deep Links: 2026 완전 가이드

딥 링크는 이론적으로는 간단해 보입니다: 사용자가 링크를 탭하면 앱이 열리고, 필요한 정확한 화면으로 이동합니다. 실제로는 Univ...를 구현해 본 사람이라면 누구나 알 수 있습니다.