SDK ์ฐ๋
Hackle React Native SDK๋ React 16.8 ์ด์ ๋ฐ React Native 0.64.1 ์ด์์ ์ง์ํฉ๋๋ค.
React Native SDK๋ Android SDK, iOS SDK ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ํฉ๋๋ค.
์๋ OS๋ฅผ ์ง์ํฉ๋๋ค.
- Android API 16 (4.1 Jelly Bean) ์ด์
- iOS 10 ์ด์
1. ์์กด์ฑ ์ถ๊ฐ
SDK ์ค์น/์ ๋ฐ์ดํธ ํ ์ฑ์ ์๋กญ๊ฒ ๋น๋ํด์ผ ์ฐ๋์ด ๋ณ๊ฒฝ์ฌํญ์ด ์ ์ฉ๋ฉ๋๋ค.
npm install --save @hackler/react-native-sdkyarn add @hackler/react-native-sdkiOS
cd ios
pod installExpo ์ฌ์ฉ ์ ์์กด์ฑ ์ถ๊ฐ
React Native SDK๋
Expo Goํ๊ฒฝ์ ์ง์ํ์ง ์์ต๋๋ค.expo prebuild๋ฅผ ์ฌ์ฉํด์ฃผ์ธ์.
npm install --save @hackler/react-native-sdkyarn add @hackler/react-native-sdkexpo ์ฌ์ฉ ์์๋ link๋ pod install์ ์คํํ์ง ์์๋ ๋ฌด๋ฐฉํฉ๋๋ค.
์๋๋ก์ด๋ ์ค์
React Native SDK 3.25.0 ์ดํ ๋ฒ์ React Native SDK 3.26.0 ์ด์ ๋ฒ์ ๋ถํฐ๋ ์๋ ์ค์ ์ด ์๋์ผ๋ก ์ ์ฉ๋ฉ๋๋ค. ์ด ๋จ๊ณ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ค์์ผ๋ก ์งํํด ์ฃผ์ธ์. 3.25.0 ์ดํ ๋ฒ์ ์์๋ ์๋ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํด์
registerActivityLifecycleCallbacks๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.์์ฑ๋ Application ํด๋์ค๊ฐ ์๋ค๋ฉด ์๋ก ์์ฑํ์ฌ
AndroidManifest.xml์ ๋ฑ๋กํด ์ฃผ์ธ์.
Application ํด๋์ค์ ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ onCreate ํจ์ ์๋ ์ถ๊ฐํด ์ฃผ์ธ์.
import android.app.Application;
import io.hackle.android.HackleApp;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
...
HackleApp.registerActivityLifecycleCallbacks(this);
...
}
}import android.app.Application
import io.hackle.android.Hackle
import io.hackle.android.registerActivityLifecycleCallbacks
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
...
Hackle.registerActivityLifecycleCallbacks(this)
...
}
}2. SDK ์ด๊ธฐํ
SDK๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ ๋ฐ๋์ createInstance()์ SDK ํค๋ฅผ ์ ๋ฌํ์ฌ HackleReactNativeSDKClient๋ฅผ ์์ฑํ๊ณ React ์ดํ๋ฆฌ์ผ์ด์
์ ๊ฐ์ธ๋ HackleProvider์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
- SDK ํค๋ ํตํด ์๋น์ค์ ๋์๋ณด๋ ์์ ์์นํ SDK ์ฐ๋ ์ ๋ณด์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
- ์ดํ๋ฆฌ์ผ์ด์ ์ด๊ธฐํ ๋จ๊ณ์ ํตํด ์๋ฒ์ ๋ฐ์ดํฐ ๋๊ธฐํ๋ฅผ ์ํ ํต์ ์ ์งํํฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ด ์๊ฐ์ ์ ๋ฐ๋ฆฌ ์ด์ ๋ถ๊ณผํฉ๋๋ค. ๋๊ธฐํ๊ฐ ์๋ฃ๋๋ฉด ์ฆ์ ๋ ๋๋ง์ด ์งํ๋ฉ๋๋ค.
import { createInstance, HackleProvider } from "@hackler/react-native-sdk";
// YOUR_APP_SDK_KEY ์๋ฆฌ์ SDK ํค๋ฅผ ๋ฃ์ต๋๋ค.
const hackleClient = createInstance("YOUR_APP_SDK_KEY");
const App = () => {
return (
<HackleProvider hackleClient={hackleClient}>
<YourApp />
</HackleProvider>
);
};์ด๊ธฐํ ์ค์ ์ ๋ณด
์ค์ ์ ๋ณด๋ฅผ ํฌํจํ์ฌ SDK๋ฅผ ์ด๊ธฐํ ํ ์ ์์ต๋๋ค
import { createInstance, HackleProvider } from "@hackler/react-native-sdk";
const config = {
debug: true
};
const hackleClient = createInstance("YOUR_APP_SDK_KEY", config);
const App = () => {
return (
<HackleProvider hackleClient={hackleClient}>
<YourApp />
</HackleProvider>
);
};์ค์ | ๊ธฐ๋ฅ | ๊ธฐ๋ณธ๊ฐ | ์ง์ ๋ฒ์ |
|---|---|---|---|
exposureEventDedupIntervalMillis | ๋์ผํ ์ฌ์ฉ์๊ฐ ์ฐ์์ผ๋ก ๋ฐ์์ํจ ๋์ผํ A/B ํ ์คํธ, ๊ธฐ๋ฅํ๋๊ทธ ๋ถ๋ฐฐ๊ฒฐ๊ณผ์ ๋ํ ๋ ธ์ถ ์ด๋ฒคํธ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์ต์๊ฐ: 1000 (1์ด) ์ต๋๊ฐ: 3600000 (1์๊ฐ) | -1 (์ค๋ณต์ ๊ฑฐ ํ์ง ์์) | 3.3.1+ |
debug | ๋ชจ๋ ๊ธฐ๋ฅ์ ๋ํ ๋ก๊ทธ๋ฅผ ์ฝ์์ ์ถ๋ ฅํ๊ณ , ์ด๋ฒคํธ๋ฅผ ์ฆ์ ์ ์กํฉ๋๋ค. | false | 3.4.1+ |
pollingIntervalMillis | ๋์๋ณด๋์์ ์ค์ ํ ์ ๋ณด๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธ ํ ์ ์์ต๋๋ค. ์ต์๊ฐ : 60000 (60์ด) | -1 (์ฃผ๊ธฐ์ ์ผ๋ก ์ ๋ฐ์ดํธํ์ง ์์) | 3.6.0+ |
sessionTimeoutMillis | ์ธ์ ๋ง๋ฃ ์๊ฐ์ ์ค์ ํฉ๋๋ค. | 1800000 (30๋ถ) | 3.11.0+ |
๋์๋ณด๋ ์ค์ ์ ๋ณด ๊ฐฑ์
๋์๋ณด๋ ์ค์ ์ ๋ณด๋ฅผ ๋ช ์์ ์ผ๋ก ๊ฐฑ์ ํ ์ ์์ต๋๋ค.
hackleClient.fetch();ํด๋น ํจ์๋ 60์ด์ ํ๋ฒ ์ ํ์ ์ผ๋ก ํธ์ถํ ์ ์์ต๋๋ค.
3. ์ฌ์ฉ์ ์ค์
์ฌ์ฉ์ ์ ๋ณด๋ฅผ SDK์ ์ค์ ํ ์ ์์ต๋๋ค.
์ฌ์ฉ์ ID ์ค์
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ, setUserId๋ฅผ ํธ์ถํด์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ID๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
- ๋ก๊ทธ์ธ ์ ํ๋ฒ๋ง ์ค์ ํ๋ฉด ๋ฉ๋๋ค.
- ์ด๋ฏธ ๋ก๊ทธ์ธ์ด ๋์ด์๋ ์ฌ์ฉ์์ ๊ฒฝ์ฐ์๋ ๋ก๊ทธ์ธํ ์ ๋ณด๋ฅผ ํ์ธํ๋ ์์ ์ ํธ์ถํ๋ฉด ๋ฉ๋๋ค.
const userId = ...; // ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ ID (ํ์๋ฒํธ, ๋ฉค๋ฒ ID ๋ฑ)
hackleClient.setUserId(userId);์ฌ์ฉ์ ์์ฑ ์ค์
์ด๋ฉ์ผ์ฃผ์, ์์น, ๋์ด, ํ์๋ฑ๊ธ๊ณผ ๊ฐ์ ์ ๋ณด๋ฅผ ์ฌ์ฉ์ ์์ฑ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. setUserProperty, setUserProperties ๋ฅผ ํธ์ถํ์ฌ ์ฌ์ฉ์ ์์ฑ์ ์ค์ ํ ์ ์์ต๋๋ค.
import { PropertyOperationsBuilder } from "@hackler/react-native-sdk"
const operations = new PropertyOperationsBuilder()
.set("age", 42)
.set("grade", "GOLD")
.build();
hackleClient.updateUserProperties(operations);์ฌ์ฉ์ ๋ก๊ทธ์์ ์ ์ฌ์ค์
์ฌ์ฉ์๊ฐ ๋ก๊ทธ์์ ํ ๊ฒฝ์ฐ resetUser๋ฅผ ํธ์ถํ์ฌ ๊ธฐ์กด์ ์ค์ ํ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ฆฌ์
ํ ์ ์์ต๋๋ค. ์๋ ์ ๋ณด๊ฐ ๋ฆฌ์
๋ฉ๋๋ค.
- ์ฌ์ฉ์ ID
- ์ฌ์ฉ์ ์์ฑ
hackleClient.resetUser();4. ์ด๋ฒคํธ ์ ์ก
์ฌ์ฉ์๊ฐ ์ํํ๋ ํ๋์ ์ด๋ฒคํธ๋ก ์ ์กํ ์ ์์ต๋๋ค. ์ ์ก๋ ์ด๋ฒคํธ๋ A/B ํ ์คํธ ๋ถ์, ๋ฐ์ดํฐ ๋ถ์ ๋ฑ์ ์ฌ์ฉ๋ฉ๋๋ค. ์๋ฅผ๋ค์ด, ์ฌ์ฉ์๊ฐ ๊ตฌ๋งค๋ผ๋ ํ๋์ ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ด๋ฒคํธ๋ฅผ ์ ์กํ ์ ์์ต๋๋ค.
// ์ด๋ฒคํธ ์ ์ก
const track = useTrack()
const event = { key: "purchase" }
<Button onClick={() => track(event)}>๊ตฌ๋งค</Button>
// ์ด๋ฒคํธ๋ฅผ ์์ฑ๊ณผ ํจ๊ป ์ ์ก
const track = useTrack()
const event = {
key: "purchase",
properties: {
amount: 4200,
pay_method: "CARD",
is_discount: false
}
}
<Button onClick={() => track(event)}>๊ตฌ๋งค</Button>์ ์กํ ์ด๋ฒคํธ ํ์ธํ๊ธฐ
๋์๋ณด๋ ์ด๋ฒคํธ๊ด๋ฆฌ ๋ฉ๋ด์์ ์ ์กํ ์ด๋ฒคํธ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ์ด๋ฒคํธ ์ ์ก ํ ๋์๋ณด๋์ ํ์๋๊ธฐ๊น์ง ์ผ๋ฐ์ ์ผ๋ก ~60์ด๊ฐ ๊ฑธ๋ฆฝ๋๋ค.
5. A/B ํ
์คํธ
์ฌ์ฉ์๋ฅผ ํ
์คํธ ๊ทธ๋ฃน์ผ๋ก ๋ถ๋ฐฐํ๊ณ ๋ถ๋ฐฐ๋ ๊ฒฐ๊ณผ์ ํด๋นํ๋ ๋ก์ง์ ์์ฑํ์ฌ A/B ํ
์คํธ๋ฅผ ๊ตฌํํฉ๋๋ค. HackleExperiment ์ปดํฌ๋ํธ ํน์ useVariation hook์ ์คํํค๋ฅผ ์ ๋ฌํ์ฌ ํธ์ถํ๋ฉด ๋ถ๋ฐฐ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌํด๋ฐ์ ์ ์์ต๋๋ค.
์คํํค: ๊ฐ A/B ํ ์คํธ๋ณ๋ก ๊ฐ๊ฒ ๋๋ ๊ณ ์ ๋ฒํธ์ ๋๋ค. A/B ํ ์คํธ๋ฅผ ์์ฑํ๋ฉด ์๋์ผ๋ก ๋ฐ๊ธ๋ฉ๋๋ค.
function App() {
return (
// ์คํ ํค๊ฐ 42์ธ A/B ํ
์คํธ์์ ์ฌ์ฉ์์๊ฒ ๋
ธ์ถํ ํ
์คํธ ๊ทธ๋ฃน์ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ ํ
์คํธ ๊ทธ๋ฃน A๋ฅผ ๋ฐํํฉ๋๋ค.
<HackleExperiment experimentKey={42}>
<HackleVariation variation={"A"}> // ํ ๋น๋ฐ์ ๊ทธ๋ฃน์ ๋ํ ๋ก์ง
<AwesomeFeature />
</HackleVariation>
<HackleVariation variation={"B"}>
<SuperAwesomeFeature />
</HackleVariation>
</HackleExperiment>
)
}function App() {
// ์คํ ํค๊ฐ 42์ธ A/B ํ
์คํธ์์ ์ฌ์ฉ์์๊ฒ ๋
ธ์ถํ ํ
์คํธ ๊ทธ๋ฃน์ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ ํ
์คํธ ๊ทธ๋ฃน A๋ฅผ ๋ฐํํฉ๋๋ค.
const variation = useVariation(42)
// ํ ๋น๋ฐ์ ๊ทธ๋ฃน์ ๋ํ ๋ก์ง
if (variation === "A") return <AwesomeFeature />
if (variation === "B") return <SuperAwesomeFeature />
return <AwesomeFeature />
}๋ถ๋ฐฐ ๊ฒฐ๊ณผ ํ์ธํ๊ธฐ
๋์๋ณด๋ A/B ํ ์คํธ์ ์์ธํ์ด์ง์ ์ค์๊ฐ ๋ ธ์ถ ํํฉ ํญ์์ ๋ถ๋ฐฐ๋ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ๋ถ๋ฐฐ ํ ๋์๋ณด๋์ ํ์๋๊ธฐ๊น์ง ์ผ๋ฐ์ ์ผ๋ก ~60์ด๊ฐ ๊ฑธ๋ฆฝ๋๋ค.
6. ๊ธฐ๋ฅ ํ๋๊ทธ
๊ธฐ๋ฅ ํ๋๊ทธ๋ ์ผ์ง(on) ์ํ์ ๊บผ์ง(off) ์ํ๊ฐ ์์ต๋๋ค. ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ก์ง์ ์์ฑํ์ฌ ๊ธฐ๋ฅ ํ๋๊ทธ๋ฅผ ๊ตฌํํฉ๋๋ค. HackleFeature ์ปดํฌ๋ํธ ํน์ useFeature hook ์ ๊ธฐ๋ฅํ๋๊ทธํค๋ฅผ ์ ๋ฌํ์ฌ ํธ์ถํ๋ฉด on/off ์ฌ๋ถ๋ฅผ ๋ฆฌํด๋ฐ์ ์ ์์ต๋๋ค.
๊ธฐ๋ฅํ๋๊ทธํค: ๊ฐ ๊ธฐ๋ฅํ๋๊ทธ๋ณ๋ก ๊ฐ๊ฒ ๋๋ ๊ณ ์ ๋ฒํธ์ ๋๋ค. ๊ธฐ๋ฅํ๋๊ทธ๋ฅผ ์์ฑํ๋ฉด ์๋์ผ๋ก ๋ฐ๊ธ๋ฉ๋๋ค.
function App() {
return (
// ๊ธฐ๋ฅ ํค๊ฐ 42์ธ ๊ธฐ๋ฅ ํ๋๊ทธ์์ ์ฌ์ฉ์์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ false(๊บผ์ง ์ํ)๋ฅผ ๋ฐํํฉ๋๋ค.
<Feature featureKey={42}>
{(featureOn) =>
featureOn ? (
<SuperAwesomeFeature /> // ์ผ์ง ์ํ์ผ ๋์ ๊ธฐ๋ฅ
) : (
<AwesomeFeature /> // ๊บผ์ง ์ํ์ผ ๋์ ๊ธฐ๋ฅ
)
}
</Feature>
)
}function App() {
// ๊ธฐ๋ฅ ํค๊ฐ 42์ธ ๊ธฐ๋ฅ ํ๋๊ทธ์์ ์ฌ์ฉ์์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ false(๊บผ์ง ์ํ)๋ฅผ ๋ฐํํฉ๋๋ค.
const featureOn = useFeature(42)
return (
<>
{
featureOn ? (
<SuperAwesomeFeature /> // ์ผ์ง ์ํ์ผ ๋์ ๊ธฐ๋ฅ
) : (
<AwesomeFeature /> // ๊บผ์ง ์ํ์ผ ๋์ ๊ธฐ๋ฅ
)
}
</>
)
}Updated 6 days ago
