SDK 마이그레이션 가이드
이 가이드는 기존 Monetai 고객이 예측 기반 SDK (비구매자 예측 기반 매출 최적화)에서 현재 SDK (개인화된 가격 기반 매출 최적화)로 마이그레이션할 때 필요한 모든 변경 사항을 안내합니다. 대시보드 개념부터 SDK 코드 업데이트까지 전체 과정을 다룹니다.
변경 사항 요약
Monetai 작동 방식: 이전과 현재
이전 (예측 기반): SDK가 각 사용자를 구매자 또는 비구매자로 예측한 후, 비구매자로 예측된 사용자에게 고정 할인을 표시했습니다. 캠페인이 프로모션을 실행하는 단위였습니다. 캠페인 실행 전에 학습된 AI 모델(200명 이상 필요)이 필요했습니다.
현재 (개인화된 가격 기반): SDK가 각 프로모션에 대해 개인화된 오퍼를 가져오며, 상품별로 AI가 최적화한 할인율을 제공합니다. 프로모션은 앱 내 구매 페이지를 나타내는 새로운 상위 개념입니다. 각 프로모션 안에서 에이전트 (캠페인의 진화형)가 플랫폼별 가격 최적화를 타겟팅 규칙과 함께 담당합니다. AI 최적화는 즉시 시작되며, 최소 데이터 요구가 없습니다.
개념 매핑
| 이전 | 현재 | 변경 사항 |
|---|---|---|
| 캠페인 | 에이전트 | 캠페인이 에이전트로 진화. 매출 최적화의 핵심 단위이며, 타겟팅 규칙과 우선순위가 추가됨 |
| (해당 없음) | 프로모션 | 새 개념: 에이전트를 그룹으로 묶으며, 앱 내 하나의 구매 페이지를 나타냄 |
| predict(): 사용자를 구매자 / 비구매자로 분류 | getOffer(placement): 특정 placement에 대한 개인화된 오퍼 조회 | 주어진 placement에 대해 상품별 할인율을 반환하는 새로운 API |
| onDiscountInfoChange 콜백 | getOffer() 반환값 | 할인 정보가 콜백 대신 직접 반환됨 |
| 모델 생성 (200명 이상 필요) | AI 가격 최적화 (즉시 시작) | 모델 학습 대기 불필요 |
| 고정 할인 (표시/숨김) | 상품별 동적 할인율 | AI가 할인율을 자동으로 최적화 |
단계별 마이그레이션
Step 1: SDK 버전 업데이트
최신 SDK 버전으로 업데이트하세요.
- React Native
- iOS
- Android
yarn add @hayanmind/monetai-react-native@latest
iOS의 경우, 업데이트 후 cd ios && pod install을 실행하세요.
Swift Package Manager (최신 버전 선택) 또는 CocoaPods로 업데이트하세요:
pod 'MonetaiSDK' # 최신 버전으로 업데이트
pod install
build.gradle에서 의존성을 업데이트하세요:
dependencies {
implementation 'com.github.hayanmind:monetai-android:2.0.0'
}
SDK v2.0.0은 Google Play Billing Library v8을 사용합니다. 다른 결제 라이브러리를 사용하는 경우, Billing Library v8을 지원하는지 확인하세요.
Step 2: SDK 초기화 업데이트
initialize() 호출 방식은 동일합니다. 다만 반환값에서 group 필드가 제거되었습니다.
- React Native
- iOS (Swift)
- Android (Kotlin)
// 이전: 반환값에 group 포함
// 현재: group 제거됨
const result = await MonetaiSDK.initialize({
sdkKey: "YOUR_SDK_KEY",
userId: "USER_ID",
useStoreKit2: true,
});
// result에 더 이상 .group이 포함되지 않음
// 이전: 반환값에 group 포함
// 현재: group 제거됨
let result = try await MonetaiSDK.shared.initialize(
sdkKey: "YOUR_SDK_KEY",
userId: "USER_ID",
useStoreKit2: true
)
// result에 더 이상 .group이 포함되지 않음
// 이전: 반환값에 group 포함
// 현재: group 제거됨
MonetaiSDK.shared.initialize(
context = this,
sdkKey = "YOUR_SDK_KEY",
userId = "USER_ID"
) { result, error ->
// result에 더 이상 .group이 포함되지 않음
}
group / testGroup을 사용하고 있었다면, 해당 분기 로직을 안전하게 제거할 수 있습니다. getOffer()가 내부적으로 처리하며, null 반환은 해당 사용자에게 제공할 오퍼가 없다는 의미입니다.
Step 3: predict() 제거 및 getOffer() 추가
가장 중요한 변경 사항입니다. 사용자를 구매자 또는 비구매자로 분류하던 기존 predict() 메서드가 제거됩니다. 대신 특정 placement에 대한 개인화된 오퍼를 조회하는 새로운 API인 getOffer(placement:)를 사용합니다.
placement란?placement는 가격 최적화를 적용할 화면의 고유 문자열 식별자입니다. 설명적인 값을 자유롭게 정의하세요 (예:main_paywall,special_offer). 이미 대시보드에서 프로모션을 생성했다면 대시보드 → 프로모션 → 프로모션 설정에서 placement 값을 확인할 수 있습니다.
두 API는 서로 다른 목적을 가집니다:
predict() (제거됨) | getOffer() (신규) | |
|---|---|---|
| 목적 | 사용자를 구매자/비구매자로 분류한 뒤, 비구매자에게 고정 할인 제공 | 상품별 AI 최적화 할인율이 포함된 개인화된 오퍼 조회 |
| 입력 | 없음 | placement (화면/UI 요소 식별자) |
| 반환 | prediction + testGroup | 상품별 discountRate가 포함된 Offer 객체, 또는 null |
| 호출 시점 | 프로모션을 보여줄지 판단하고 싶은 타이밍에 호출 | 특정 placement에서 가격 화면을 표시할 때 호출 |
| 할인 정보 | 이후 onDiscountInfoChange 콜백으로 전달 | 응답에 직접 포함되어 반환 |
- React Native
- iOS (Swift)
- Android (Kotlin)
// ❌ 제거: predict()
const result = await MonetaiSDK.predict();
if (result.prediction === "non-purchaser") {
showDiscountUI();
}
// ✅ 추가: getOffer() - placement에 대한 개인화된 오퍼 조회
const offer = await MonetaiSDK.getOffer("YOUR_PLACEMENT");
if (offer) {
// 오퍼 있음: AI 최적화 할인을 가격 화면에 적용
console.log("할인율:", offer.discountRate);
displayPrice(offer);
} else {
// 오퍼 없음: 앱의 기본 가격 표시
displayDefaultPrice();
}
// ❌ 제거: predict()
let result = try await MonetaiSDK.shared.predict()
if result.prediction == .nonPurchaser {
showDiscountUI()
}
// ✅ 추가: getOffer() - placement에 대한 개인화된 오퍼 조회
let offer = try await MonetaiSDK.shared.getOffer(placement: "special_offer")
if let offer = offer {
// 오퍼 있음: AI 최적화 할인을 가격 화면에 적용
for product in offer.products {
print("SKU: \(product.sku), 할인: \(product.discountRate * 100)%")
}
showPricingScreen(with: offer)
} else {
// 오퍼 없음: 앱의 기본 가격 표시
showDefaultPrice()
}
// ❌ 제거: predict()
MonetaiSDK.shared.predict { result, error ->
if (result?.prediction == PredictResult.NON_PURCHASER) {
showDiscountUI()
}
}
// ✅ 추가: getOffer() - placement에 대한 개인화된 오퍼 조회
MonetaiSDK.shared.getOffer(placement = "special_offer") { offer, error ->
if (offer != null) {
// 오퍼 있음: AI 최적화 할인을 가격 화면에 적용
offer.products.forEach { product ->
println("SKU: ${product.sku}, 할인: ${product.discountRate * 100}%")
}
displayPrice(offer)
} else {
// 오퍼 없음: 앱의 기본 가격 표시
displayDefaultPrice()
}
}
Step 4: logViewProductItem() 추가 (신규, 필수)
새로 추가된 필수 로깅 호출입니다. 사용자가 가격 화면을 볼 때마다 표시되는 각 상품에 대해 logViewProductItem()을 호출해야 합니다. 이 데이터는 AI 가격 최적화에 필수적입니다.
가격 화면 — placement를 전달하여 화면을 식별합니다:
- React Native
- iOS (Swift)
- Android (Kotlin)
// 가격 화면에 표시되는 각 상품에 대해 호출
await MonetaiSDK.logViewProductItem({
placement: "special_offer",
productId: "premium_monthly",
price: 4.99, // 표시 가격 (할인 가격)
regularPrice: 9.99, // 정가
currencyCode: "USD",
});
// 가격 화면에 표시되는 각 상품에 대해 호출
await MonetaiSDK.shared.logViewProductItem(
ViewProductItemParams(
placement: "special_offer",
productId: "premium_monthly",
price: 4.99, // 표시 가격 (할인 가격)
regularPrice: 9.99, // 정가
currencyCode: "USD"
)
)
// 가격 화면에 표시되는 각 상품에 대해 호출
MonetaiSDK.shared.logViewProductItem(
ViewProductItemParams(
placement = "special_offer",
productId = "premium_monthly",
price = 4.99, // 표시 가격 (할인 가격)
regularPrice = 9.99, // 정가
currencyCode = "USD"
)
)
Monetai 미적용 구매 화면 — 가격 예측 정확도 향상을 위해 수집 권장:
- React Native
- iOS (Swift)
- Android (Kotlin)
await MonetaiSDK.logViewProductItem({
placement: "main_paywall",
productId: "premium_monthly",
price: 9.99,
regularPrice: 9.99,
currencyCode: "USD",
});
await MonetaiSDK.shared.logViewProductItem(
ViewProductItemParams(
placement: "main_paywall",
productId: "premium_monthly",
price: 9.99,
regularPrice: 9.99,
currencyCode: "USD"
)
)
MonetaiSDK.shared.logViewProductItem(
ViewProductItemParams(
placement = "main_paywall",
productId = "premium_monthly",
price = 9.99,
regularPrice = 9.99,
currencyCode = "USD"
)
)
이 단계를 건너뛰면 AI 가격 최적화가 정상적으로 작동하지 않습니다. 모든 상품 조회에 대해 logViewProductItem() 호출을 반드시 추가하세요.
Step 5: 제거 대상 코드 정리
더 이상 필요하지 않은 코드를 제거하세요:
5-1. onDiscountInfoChange 콜백 제거
할인 정보가 이제 getOffer()에서 직접 반환됩니다. onDiscountInfoChange 콜백은 더 이상 사용되지 않습니다.
- React Native
- iOS (Swift)
- Android (Kotlin)
// ❌ onDiscountInfoChange prop 제거
<MonetaiProvider onDiscountInfoChange={handleDiscountInfoChange}>
{/* ... */}
</MonetaiProvider>
// ❌ 제거하세요
MonetaiSDK.shared.onDiscountInfoChange = { discountInfo in
// ...
}
// ❌ 제거하세요
MonetaiSDK.shared.onDiscountInfoChange = { discountInfo ->
// ...
}
5-2. predict() 호출 제거
// ❌ 모든 predict() 호출 제거
let result = try await MonetaiSDK.shared.predict()
5-3. group 처리 제거
// ❌ group/testGroup 분기 로직 제거
if result.testGroup == .monetai { ... }
if result.testGroup == .baseline { ... }
Step 6: UI 템플릿 제거 (사용한 경우)
Banner/Paywall UI 템플릿은 더 이상 제공되지 않습니다. getOffer()를 통한 가격 최적화는 앱의 자체 프로모션 또는 가격 화면에 직접 적용하기 때문에 별도의 UI 템플릿이 필요하지 않습니다.
configurePaywall() 또는 독립 Banner/Paywall 컴포넌트를 사용하셨다면, 이를 제거하고 기존 결제 플로우에 getOffer()를 연동하세요. 자세한 내용은 Step 3을 참고하세요.
- React Native
- iOS (Swift)
- Android (Kotlin)
// ❌ 아래 import 및 사용 코드를 제거하세요
import { Banner, Paywall } from "@hayanmind/monetai-react-native";
// ❌ 제거하세요
MonetaiSDK.shared.configurePaywall(config)
MonetaiSDK.shared.setSubscriptionStatus(false)
// ❌ 제거하세요
MonetaiSDK.shared.configurePaywall(config)
MonetaiSDK.shared.setSubscriptionStatus(false)
Step 7: 대시보드에서 프로모션 및 에이전트 설정
이전 버전에서는 캠페인을 직접 생성했습니다. 현재는 두 가지 개념이 있습니다. 프로모션은 앱 내 구매 페이지를 나타내는 새 개념이고, 에이전트는 캠페인의 진화형으로 프로모션 안에서 AI 가격 최적화를 수행하는 단위입니다.
| 이전 | 현재 |
|---|---|
| 캠페인 생성 | 프로모션 (상품 및 할인 가격) 생성 후, 그 안에 에이전트 생성 |
| 모델 학습 대기 (구매자 100명 이상 / 비구매자 100명 이상) | 대기 불필요. AI 최적화가 즉시 시작 |
| 캠페인 시작 | 플랫폼별 (iOS / Android) 에이전트 시작 |
| 캠페인 지표 모니터링 | 프로모션 내 에이전트별 지표 모니터링 |
자세한 방법은 다음을 참고하세요: 프로모션 생성 및 관리
마이그레이션 체크리스트
마이그레이션이 완료되었는지 이 체크리스트로 확인하세요:
- SDK 버전을 최신으로 업데이트
-
predict()제거 - 가격/프로모션 화면에
getOffer(placement:)추가 - 가격 화면의 모든 상품 조회에
logViewProductItem()추가 -
onDiscountInfoChange콜백 제거 -
configurePaywall()및 Banner/Paywall UI 템플릿 제거 (해당 시) -
testGroup,ABTestGroup등 group 처리 코드 제거 -
logEvent()호출은 그대로 유지 (변경 불필요) - 로그아웃 시
reset()호출은 그대로 유지 (변경 불필요) - 대시보드: 상품과 에이전트가 설정된 프로모션 생성 완료
- 테스트: 테스트 기기에서
getOffer(placement:)가 예상대로 오퍼를 반환하는지 확인
변경 없는 부분
다음 SDK 기능은 변경이 필요 없습니다:
| 기능 | 비고 |
|---|---|
initialize() | 동일한 API (반환값에서 group 필드 제거) |
logEvent() | 동일. 기존과 같이 사용자 이벤트를 계속 로깅 |
reset() | 동일. 사용자 로그아웃 시 호출 |
| SDK 설치 | 동일한 패키지 매니저 (SPM, CocoaPods, Gradle, yarn/npm) |
FAQ
Q. 기존 캠페인과 새 프로모션을 동시에 운영할 수 있나요? A. 아니요. 마이그레이션을 완료하고 새로운 프로모션 시스템으로 전환해야 합니다.
Q. 시작하기 전에 모델 학습을 기다려야 하나요? A. 아니요. 200명 이상의 사용자가 필요했던 이전 버전과 달리, 현재 버전의 글로벌 최적화는 SDK 연동 직후 즉시 작동합니다.
Q. 기존 캠페인 데이터는 어떻게 되나요? A. 기존 캠페인 데이터는 대시보드에서 계속 확인할 수 있습니다. 새로운 지표는 프로모션 시스템에서 추적됩니다.
Q. 이전 SDK는 prediction (purchaser/non-purchaser)을 반환했는데, 이제 어떻게 처리하나요?
A. 더 이상 사용자를 분류할 필요가 없습니다. 대신 특정 프로모션에 대해 getOffer()를 호출하면 됩니다. 오퍼가 반환되면 할인을 적용하고, null이 반환되면 기본 가격을 표시하세요. AI가 내부적으로 사용자 타겟팅을 처리합니다.
Q. 프로모션과 에이전트의 관계는 무엇인가요? A. 프로모션은 앱 내 구매 페이지를 나타냅니다 (예: 온보딩 오퍼, 이탈 방지 오퍼). 각 프로모션 안에 플랫폼별 (iOS / Android) 에이전트를 하나 이상 생성하며, 에이전트가 실제 AI 가격 최적화를 담당합니다. 캠페인이 에이전트로 진화했고, 프로모션은 그 위에 새로 추가된 레이어입니다.
지원
마이그레이션 중 문제가 발생하면 support@monetai.io로 문의하세요.