Kotlin Multiplatform 구매 및 페이월 개요
0:02:00RevenueCat의 KMP (Kotlin Multiplatform) SDK Codelab에 오신 것을 환영합니다!
이 codelab에서는 다음을 배우게 됩니다:
Kotlin Multiplatform 프로젝트에 RevenueCat KMP SDK를 통합하기 KMP 애플리케이션에서 인앱 결제 구현하기 유료 사용자와 무료 사용자를 구별하는 방법 배우기 서버 기반 UI 접근 방식을 기반으로 하는 페이월 화면 구축하기
이 codelab을 마치면 KMP 앱에서 인앱 결제를 성공적으로 구현하고 RevenueCat의 KMP SDK를 사용하여 동적 페이월을 표시할 수 있게 됩니다.
RevenueCat SDK 가져오기
0:07:00인앱 결제를 구현하기 전에 먼저 RevenueCat SDK를 기존 프로젝트 또는 새 프로젝트에 가져와야 합니다. 시작하려면 build.gradle.kts 파일에 다음 종속성을 추가하세요:
GitHub에서 최신 릴리스 버전을 확인할 수 있습니다.
[versions]
purchases-kmp = "1.8.6+14.0.2"
[libraries]
purchases-core = { module = "com.revenuecat.purchases:purchases-kmp-core", version.ref = "purchases-kmp" }
purchases-ui = { module = "com.revenuecat.purchases:purchases-kmp-ui", version.ref = "purchases-kmp" }이제 모듈의 build.gradle.kts에 있는 commonMain 소스 세트에 종속성을 추가할 수 있습니다.
kotlin {
// ...
sourceSets {
// ...
commonMain.dependencies {
// purchases-kmp 종속성을 추가합니다.
implementation(libs.purchases.core)
implementation(libs.purchases.ui)
}
}
}ExperimentalForeignApi 선택
SDK가 네이티브 iOS 코드용 Kotlin 생성 바인딩을 활용하므로 iOS 소스 세트에서 ExperimentalForeignApi를 선택해야 합니다. 이를 활성화하려면 모듈의 build.gradle.kts 파일에 다음 구성을 추가하세요:
kotlin {
// ...
sourceSets {
// ...
named { it.lowercase().startsWith("ios") }.configureEach {
languageSettings {
optIn("kotlinx.cinterop.ExperimentalForeignApi")
}
}
}
}네이티브 iOS SDK 연결하기
SDK는 네이티브 RevenueCat iOS 프레임워크인 PurchasesHybridCommon에 의존하므로 기존 iOS 프로젝트에 연결해야 합니다. 이 codelab에서는 CocoaPods를 사용하여 네이티브 iOS SDK를 구성합니다.
전체 Kotlin 프로젝트를 CocoaPods 종속성으로 포함할 수 있습니다. 이렇게 하려면 생성된 .podspec 파일이 포함된 디렉터리의 이름과 경로를 제공하여 프로젝트의 Podfile에서 종속성을 지정하세요.
- 버전 카탈로그에 Kotlin CocoaPods Gradle 플러그인 및
purchases-common버전을 추가합니다.
gradle/libs.versions.toml 파일에서 [plugins] 블록에 다음을 추가하세요:
[versions]
# 이 version은 purchases-kmp version의 '+' 뒤에 있는 모든 것과 동일해야 합니다.
purchases-common = "13.3.0"
[plugins]
kotlin-cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }- 루트
build.gradle.kts파일에서 plugins {} 블록에 다음 별칭을 추가하세요:
alias(libs.plugins.kotlin.cocoapods) apply false- CocoaPods를 통합하려는 모듈(예: composeApp)에서
plugins {}블록에 동일한 별칭을 추가하세요:
alias(libs.plugins.kotlin.cocoapods)- 다음으로 아래와 같이 cocoapods 환경을 구성하세요:
kotlin {
cocoapods {
// 필수 속성
// 여기에서 필요한 Pod 버전을 지정하세요
// 그렇지 않으면 Gradle 프로젝트 버전이 사용됩니다
version = "1.0"
summary = "Some description for a Kotlin/Native module"
homepage = "Link to a Kotlin/Native module homepage"
// 선택적 속성
// Gradle 프로젝트 이름을 변경하는 대신 여기에서 Pod 이름을 구성하세요
name = "MyCocoaPod"
// .. 다른 Cocoapods 옵션들이 여기에 있습니다.
// PurchasesHybridCommon 종속성을 추가합니다.
pod("PurchasesHybridCommon") {
version = libs.versions.purchases.common.get()
extraOpts += listOf("-compiler-option", "-fmodules")
}
}
}- 마지막으로
Podfile의 iOS 앱 대상에 다음post_install스크립트를 추가하세요. 예를 들어, Kotlin Multiplatform 모듈의 이름이shared인 경우 스크립트는 다음과 같습니다:
target 'iosApp' do
use_frameworks!
platform :ios, '16.0'
pod 'shared', :path => '../shared', :platforms => :ios
# 다음 post_install 스크립트를 추가하세요:
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'shared'
target.build_configurations.each do |config|
config.build_settings.delete('ASSETCATALOG_COMPILER_APPICON_NAME')
end
end
end
end
endRevenueCat SDK를 성공적으로 가져왔습니다. 이제 초기화 단계로 넘어가겠습니다.
초기화
0:02:00이제 프로젝트에서 Purchases SDK를 초기화할 시간입니다. Project Settings > Platforms에서 찾을 수 있는 공개 API 키만 사용하여 Purchases를 구성하세요.
import com.revenuecat.purchases.kmp.LogLevel
import com.revenuecat.purchases.kmp.Purchases
import com.revenuecat.purchases.kmp.configure
// 공통 초기화 로직이 있다면 거기서 configure()를 호출하세요. 그렇지 않으면,
// 각 플랫폼의 앱 라이프사이클 초기에 호출하세요.
// 참고: 각 플랫폼에 올바른 api key를 사용해야 합니다.
// 이를 위해 Kotlin Multiplatform의 expect/actual 메커니즘을 사용할 수 있습니다.
Purchases.logLevel = LogLevel.DEBUG
Purchases.configure(apiKey = "<google_or_apple_api_key>") {
appUserId = "<app_user_id>"
// 기타 구성 옵션.
}.configure 메서드의 app_user_id 필드는 RevenueCat이 앱에서 사용자를 식별하는 데 사용됩니다. 사용자 지정 사용자 식별자를 제공하거나 생략하여 RevenueCat이 자동으로 익명 ID를 생성하도록 할 수 있습니다. 자세한 내용은 사용자 식별 가이드를 참조하세요.
네! 이제 구현의 50%를 완료했습니다.
Entitlement 검증하기
0:03:00이제 사용자 entitlement를 검증하는 단계로 넘어가겠습니다.
앞서 언급했듯이 entitlement는 사용자가 구매 후 잠금 해제하는 액세스 수준이나 기능을 나타냅니다. 이를 통해 광고 배너를 표시할지 또는 프리미엄 액세스를 부여할지와 같은 사항을 결정하는 데 유용합니다.
아래 코드 스니펫을 사용하여 사용자에게 활성 entitlement가 있는지 쉽게 확인할 수 있습니다:
val ENTITLEMENT_IDENTIFIER = ".." // RevenueCat 대시보드에서 특정 entitlement 식별자를 가져옵니다
val customerInfo = Purchases.sharedInstance.awaitCustomerInfo()
val isEntitled = customerInfo?.entitlements[ENTITLEMENT_IDENTIFIER]?.isActive == true사용자에게 특정 entitlement가 있는지 확인한 후에는 앱의 비즈니스 모델을 기반으로 진행 방법을 결정할 수 있습니다.
예를 들어, 앱이 광고 지원인 경우 AdMob 배너를 표시하거나 숨기도록 선택할 수 있습니다. 또는 페이월이나 구매 대화 상자를 표시하여 사용자가 고급 기능이나 콘텐츠를 잠금 해제할 수 있도록 선택할 수 있습니다.
해당 로직을 구현하는 방법의 예는 다음과 같습니다:
@Composable
fun ContentScreen(isEntitled: Boolean) {
if (isEntitled) {
// 사용자에게 이 entitlement에 대한 액세스 권한이 부여된 경우. 배너를 표시할 필요가 없습니다.
} else {
// 여기에 배너 UI를 표시하거나 페이월을 표시합니다
..
}
}인앱 결제 구현하기
0:04:00이제 광고 없는 경험을 제공하기 위해 인앱 결제를 구현해보겠습니다. 시작하려면 먼저 RevenueCat 대시보드에서 관련 제품 정보를 가져와야 합니다. 이 제품 데이터는 사용자에게 구매 옵션을 표시하는 데 사용됩니다.
아래 예제와 같이 Purchases.sharedInstance.awaitGetProducts()를 호출하여 사용 가능한 제품을 검색할 수 있습니다:
// RevenueCat 서버에서 제품 정보를 가져옵니다
val products = Purchases.sharedInstance.awaitGetProducts(
productIds = listOf("paywall_tester.subs"),
)
// 인앱 결제를 진행합니다
val purchaseResult = Purchases.sharedInstance.awaitPurchase(
storeProduct = products.first()
)paywall_tester.subs:weekly, paywall_tester.subs:monthly, paywall_tester.subs:yearly와 같은 여러 제품 변형을 제공하는 경우 productIds 필드의 값으로 기본 제품 식별자인 paywall_tester.subs를 사용하여 제품 검색을 단순화할 수 있습니다. 이렇게 하면 RevenueCat이 모든 관련 제품 변형을 목록으로 가져오므로 페이월 UI에서 동적으로 표시할 수 있습니다.
제품 데이터를 검색한 후에는 Purchases.sharedInstance.awaitPurchase(product)를 호출하여 인앱 결제 플로우를 시작할 수 있습니다. 이렇게 하면 Google Play 구매 대화 상자가 자동으로 트리거되어 사용자가 앱 내에서 거래를 완료할 수 있습니다.
이렇게 하면 영수증, 스토어 API 또는 구매 검증을 수동으로 처리하는 복잡성을 처리할 필요 없이 단 몇 줄의 코드로 완전히 작동하는 인앱 결제 플로우를 통합할 수 있습니다.
페이월 구현하기
0:07:00이제 Compose Multiplatform을 사용하여 KMP 프로젝트에서 페이월을 구현할 시간입니다.
비즈니스 로직
시작하려면 RevenueCat 대시보드에서 현재 offering을 가져와야 합니다. offering은 월간, 연간 또는 평생 플랜과 같이 사용자에게 제공되는 사용 가능한 구매 옵션을 정의합니다. 아래 예제에서 설명한 것처럼 Purchases.sharedInstance.awaitOfferings() 메서드를 사용하여 쉽게 수행할 수 있습니다.
internal class DetailsRepositoryImpl : DetailsRepository {
override fun fetchOffering(): Flow<ApiResponse<Offering>> = flow {
try {
val offerings = Purchases.sharedInstance.awaitOfferings()
offerings.current?.let { currentOffering ->
val response = ApiResponse.of { currentOffering }
emit(response)
}
} catch (e: PurchasesException) {
ApiResponse.exception(e)
}
}
}RevenueCat KMP SDK는 Kotlin 코루틴에 대한 네이티브 지원을 제공하므로 코루틴 기반 아키텍처를 사용하는 프로젝트에 완벽하게 적합합니다. 현재 offering은 Flow로도 노출되므로 변경 사항을 반응적으로 관찰하고 그에 따라 UI를 업데이트할 수 있습니다.
Compose Multiplatform으로 페이월 UI 만들기
이 시점에서 모든 것이 준비되어야 합니다. com.revenuecat.purchases:purchases-kmp-ui SDK를 이미 추가한 경우 Compose Multiplatform을 사용하여 페이월 UI를 쉽게 빌드할 수 있습니다.
RevenueCat의 UI 라이브러리는 PaywallDialog와 같은 내장 컴포넌트를 제공하여 페이월 화면이나 대화 상자를 빠르게 표시할 수 있습니다. 이러한 컴포넌트는 완전히 사용자 정의 가능하며 앱의 디자인에 맞게 모양과 동작을 조정할 수 있는 다양한 구성 옵션을 제공합니다.
Compose Multiplatform을 사용하여 페이월을 구현하고 사용자 지정하는 것이 얼마나 간단한지 보여주는 예제는 다음과 같습니다:
val currentOffering by viewModel.offering.collectAsState()
val options = remember {
PaywallOptions(dismissRequest = { TODO("Handle dismiss") }) {
offering = currentOffering
shouldDisplayDismissButton = true
}
}
Paywall(options)구성 완료! 이제 사용자에게 필요한 entitlement가 없을 때마다 Paywall Editor에서 구성한 것과 정확히 동일한 디자인을 사용하여 페이월을 표시할 수 있습니다.
Codelab: RevenueCat Google Play 연동 (페이월 만들기)에서 이미 보셨듯이 페이월 시스템은 서버 기반 UI를 기반으로 합니다. 이는 앱 업데이트를 푸시하거나 검토 프로세스를 거칠 필요 없이 대시보드에서 직접 페이월의 콘텐츠와 디자인을 동적으로 업데이트할 수 있음을 의미합니다.
결론
이 codelab에서는 RevenueCat의 KMP SDK를 통합하고, 인앱 결제를 구현하고, Compose Multiplatform에서 페이월을 빌드하는 방법을 배웠습니다. 이제 앱을 출시하고 더 많은 수익을 올릴 시간입니다!
아래 리소스를 통해 RevenueCat SDK 사용에 대해 자세히 알아볼 수도 있습니다:
- 제품 튜토리얼: RevenueCat을 시작하고 최대한 활용하는 데 도움이 되는 비디오 튜토리얼입니다.