SDK ์ฐ๋
Java/Kotlin SDK๋ JDK 8 ์ด์์ ์ง์ํฉ๋๋ค.
1. ์์กด์ฑ ์ถ๊ฐ
SDK ์์กด์ฑ์ ์ถ๊ฐํฉ๋๋ค.
repositories {
mavenCentral()
}
dependencies {
implementation 'io.hackle:hackle-server-sdk:2.31.0'
}2. SDK ์ด๊ธฐํ
HackleClient๋ SDK ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํ ๋ฉ์๋๋ค์ ์ ๊ณตํ๋ ํด๋์ค์
๋๋ค.
SDK ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ HackleClinet ์ด๊ธฐํ๊ฐ ํ์ํฉ๋๋ค.
์ธ์คํด์คํ
SDK ํค๋ฅผ ์ ๋ฌํ์ฌ HackleClient๋ฅผ ์ธ์คํด์คํ ํฉ๋๋ค.
HackleClient๋ ํ์ํ ์ ๋ณด๋ค์ ์ป๊ธฐ ์ํด ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ผ๋ก ํตํด ์๋ฒ์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋๊ธฐํํฉ๋๋ค.
- SDK ํค๋ ํตํด ์๋น์ค์ ๋์๋ณด๋ ์์ ์์นํ SDK ์ฐ๋ ์ ๋ณด์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
HackleClient๋ ๋ฐ๋์ ์ฑ๊ธํค์ด์ด์ผ ํฉ๋๋ค.
HackleClient๋ ํธ์ถ ์ฐ๋ ๋๋ฅผ ๋ธ๋กํน ํ์ง ์๊ณ ๋ฐ๋ก ํ ์คํธ ๊ทธ๋ฃน์ ๋ถ๋ฐฐํ๊ธฐ ์ํด ๋ด๋ถ์ ์ผ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
์ด๋ฅผ ์ํด ์ถ๊ฐ์ ์ธ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.๋ชจ๋ ์์ฒญ์ ๋ํด ์๋ก์ด ํด๋ผ์ด์ธํธ๋ฅผ ์ธ์คํด์คํ ํ์ง ์๊ณ ์ดํ๋ฆฌ์ผ์ด์ ์๋ช ์ฃผ๊ธฐ ๋์ ์ฑ๊ธ ์ธ์คํด์ค๋ก ๊ด๋ฆฌ๋์ด์ผ ํฉ๋๋ค.
import io.hackle.sdk.HackleClient
import io.hackle.sdk.HackleClients
// YOUR_SERVER_SDK_KEY ์๋ฆฌ์ SDK ํค๋ฅผ ๋ฃ์ต๋๋ค.
HackleClient hackleClient = HackleClients.create(YOUR_SERVER_SDK_KEY);import io.hackle.sdk.HackleClient
import io.hackle.sdk.HackleClients
// YOUR_SERVER_SDK_KEY ์๋ฆฌ์ SDK ํค๋ฅผ ๋ฃ์ต๋๋ค.
val hackleClient = Hackle.client(YOUR_SERVER_SDK_KEY)3. ์ด๋ฒคํธ ์ ์ก
์ฌ์ฉ์๊ฐ ์ํํ๋ ํ๋์ ์ด๋ฒคํธ๋ก ์ ์กํ ์ ์์ต๋๋ค. ์ ์ก๋ ์ด๋ฒคํธ๋ A/B ํ
์คํธ ๋ถ์, ๋ฐ์ดํฐ ๋ถ์ ๋ฑ์ ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ๋ค์ด, ์ฌ์ฉ์๊ฐ ๊ตฌ๋งค๋ผ๋ ํ๋์ ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ด๋ฒคํธ๋ฅผ ์ ์กํ ์ ์์ต๋๋ค.
import io.hackle.sdk.HackleClient;
import io.hackle.sdk.common.Event;
import io.hackle.sdk.common.User;
// 'ae2182e0'๋ผ๋ ๋๋ฐ์ด์ค ์๋ณ์ ๊ฐ์ง ์ฌ์ฉ์๊ฐ ๋ฐ์์ํจ 'purchase'๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ก
User user = User.builder()
.deviceId("ae2182e0")
.build();
Event event = Event.builder("purchase")
.property("pay_method", "CARD")
.property("discount_amount", 800)
.property("is_discount", true)
.build();
hackleClient.track(event, user);import io.hackle.sdk.HackleClient
import io.hackle.sdk.common.Event
import io.hackle.sdk.common.User
// 'ae2182e0'๋ผ๋ ๋๋ฐ์ด์ค ์๋ณ์ ๊ฐ์ง ์ฌ์ฉ์๊ฐ ๋ฐ์์ํจ 'purchase'๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ก
val user = User.builder()
.deviceId("ae2182e0")
.build()
val event = Event.builder("purchase")
.property("pay_method", "CARD")
.property("discount_amount", 800)
.property("is_discount", true)
.build()
hackleClient.track(event, user)์ฌ์ฉ์ ์ด๋ฒคํธ ์ ์ก ํ์ธํ๊ธฐ
SDK ์์ ์ ์กํ ์ฌ์ฉ์ ์ด๋ฒคํธ๊ฐ ์ ์์ ์ผ๋ก ์์ง๋๊ณ ์๋์ง ํ์ธํด๋ณด์ธ์.
ํตํด ๋์๋ณด๋ ์์ [์ผ์ชฝ ๋ฉ๋ด๋ฐ] - [์ด๋ฒคํธ ๊ด๋ฆฌ] ๋ฉ๋ด์์ SDK๋ก ์ ์กํ ์ด๋ฒคํธ๋ฅผ ์ฐพ์ ์ค์๊ฐ ์ด๋ฒคํธ ์์งํํฉ์ ํ์ธํด๋ณผ ์ ์์ต๋๋ค.
4. A/B ํ
์คํธ, ๊ธฐ๋ฅํ๋๊ทธ
A/B ํ
์คํธ
A/B ํ ์คํธ๋ฅผ ์งํํ ๋, ํ ์คํธ ๊ทธ๋ฃน์ ๋์์ผ๋ก ์ฌ์ฉ์๋ฅผ ๋ถ๋ฐฐํ๊ณ ๊ฐ ํ ์คํธ ๊ทธ๋ฃน์ ํด๋นํ๋ ๋ก์ง์ ์์ฑํด์ผ ํฉ๋๋ค. ์ด ๋ ์ฌ์ฉ์ ๋ถ๋ฐฐ๋ฅผ ํตํด SDK๋ฅผ ํตํด ์งํํ ์ ์์ต๋๋ค.
ํ ์คํธ ๊ทธ๋ฃนํ ์คํธ ๊ทธ๋ฃน์ ํ ์คํธ ๋์์ด ๋๋ ๊ธฐ์กด์(๋์กฐ๊ตฐ)๊ณผ ๊ฐ์ ์(์คํ๊ตฐ)์ ์๋ฏธํ๋ฉฐ, ๊ฐ์ ์์ 1๊ฐ ์ด์์ผ ์ ์์ต๋๋ค. ๋์๋ณด๋์์ ์ค์ ๊ฐ๋ฅํ๋ฉฐ, ํ ์คํธ ๊ทธ๋ฃน์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด์๋ A/B ํ ์คํธ ์ค์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
variation
variation() ๋ฉ์๋์ ์คํ ํค์ ์ฌ์ฉ์ ์๋ณ์๋ฅผ ์ ๋ฌํ๋ฉด ์ฌ์ฉ์๋ฅผ ๋ถ๋ฐฐํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์์ต๋๋ค. ์ดํ ํ
์คํธ ๊ทธ๋ฃน ๋ณ ๋ก์ง์ ๊ตฌํํฉ๋๋ค.
์คํ ํค๋ ๊ฐ A/B ํ
์คํธ๋ณ๋ก ๊ฐ๊ฒ ๋๋ ๊ณ ์ ๋ฒํธ์ด๋ฉฐ, ํตํด ์๋น์ค ๋ด์ ๋์๋ณด๋์์ ํ์ธํ ์ ์์ต๋๋ค.
์๋ ์์ ์ฝ๋์์๋ ์คํ ํค 42๋ฅผ ์ ๋ฌํ๊ณ ์์ผ๋ฉฐ, ์ฌ์ฉ์ ์๋ณ์๋ "ae2182e0" ์
๋๋ค. ํ
์คํธ ๊ทธ๋ฃน์ A์ B ๋ ๊ฐ๊ฐ ์กด์ฌํฉ๋๋ค.
import io.hackle.sdk.HackleClient;
import io.hackle.sdk.common.User;
import io.hackle.sdk.common.Variation;
// ์คํ ํค๊ฐ 42์ธ A/B ํ
์คํธ์์
// "ae2182e0"๋ผ๋ ๋๋ฐ์ด์ค ์๋ณ์๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ ๋
ธ์ถํ ํ
์คํธ ๊ทธ๋ฃน์ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ ํ
์คํธ ๊ทธ๋ฃน A๋ฅผ ๋ฐํํฉ๋๋ค.
User user = User.builder()
.deviceId("ae2182e0")
.build();
Variation variation = hackleClient.variation(42, user);
// ํ ๋น๋ฐ์ ๊ทธ๋ฃน์ ๋ํ ๋ก์ง
if (variation == Variation.A) {
// ๊ทธ๋ฃน A ๋ก์ง
} else if (variation == Variation.B) {
// ๊ทธ๋ฃน B ๋ก์ง
}import io.hackle.sdk.HackleClient
import io.hackle.sdk.common.User
import io.hackle.sdk.common.Variation
// ์คํ ํค๊ฐ 42์ธ A/B ํ
์คํธ์์
// "ae2182e0"๋ผ๋ ์๋ณ์๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ ๋
ธ์ถํ ํ
์คํธ ๊ทธ๋ฃน์ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ ํ
์คํธ ๊ทธ๋ฃน A๋ฅผ ๋ฐํํฉ๋๋ค.
val user = User.builder()
.deviceId("ae2182e0")
.build()
val variation: Variation = hackleClient.variation(42, user)
// ํ ๋น๋ฐ์ ๊ทธ๋ฃน์ ๋ํ ๋ก์ง
if (variation == Variation.A) {
// ๊ทธ๋ฃน A ๋ก์ง
} else if (variation == Variation.B) {
// ๊ทธ๋ฃน B ๋ก์ง
}๊ธฐ๋ฅํ๋๊ทธ
๊ธฐ๋ฅ ํ๋๊ทธ๋ SDK ๋ฒ์ 2.0.0 ์ด์์ธ ๊ฒฝ์ฐ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.๊ธฐ๋ฅ ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ ์์กด์ฑ ์ถ๊ฐ ์ SDK ๋ฒ์ ์ 2.0.0 ์ด์์ผ๋ก ์ ์ฉํ์๊ธฐ ๋ฐ๋๋๋ค.
๊ธฐ๋ฅ ํ๋๊ทธ๋ ์ผ์ง(on) ์ํ์ ๊บผ์ง(off) ์ํ๊ฐ ์์ต๋๋ค. ๊ฐ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ค์ ํ๊ฒ ๋ฉ๋๋ค.
๊ธฐ๋ฅ ํ๋๊ทธ๋ฅผ ์ ์ฉํ ๊ธฐ๋ฅ์ ์ด๋ค ์ฌ์ฉ์๊ฐ ์ ๊ทผํ ๊ฒฝ์ฐ ์ผ์ง ํน์ ๊บผ์ง ์ํ๋ฅผ ๋ฐ์ ์ ์์ด์ผ ํฉ๋๋ค. ์ด ์ํ ๊ฒฐ์ ์ ํตํด SDK๋ฅผ ํตํด ์งํํ ์ ์์ต๋๋ค.
isFeatureOn
isFeatureOn() ๋ฉ์๋์ ๊ธฐ๋ฅ ํค๋ฅผ ์ ๋ฌํ๋ฉด ์ฌ์ฉ์์ ๋ํ ์ํ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฌ๋ฐ์ ์ ์์ต๋๋ค. ์ดํ ์ํ์ ๋ฐ๋ฅธ ๋ก์ง์ ๊ตฌํํฉ๋๋ค.
๊ธฐ๋ฅ ํค๋ ๊ฐ ๊ธฐ๋ฅ ํ๋๊ทธ๋ณ๋ก ๊ฐ๊ฒ ๋๋ ๊ณ ์ ๋ฒํธ์ด๋ฉฐ ํตํด ์๋น์ค ๋ด์ ๋์๋ณด๋์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
์๋ ์์ ์ฝ๋์์๋ ๊ธฐ๋ฅ ํค 42๋ฅผ ์ ๋ฌํ๊ณ ์์ผ๋ฉฐ, ์ํ๋ฅผ ๋ฐ์ ์ฌ์ฉ์์ ์ฌ์ฉ์ ์๋ณ์๋ "ae03e1adf" ์
๋๋ค.
import io.hackle.sdk.HackleClient
// ๊ธฐ๋ฅ ํค๊ฐ 42์ธ ๊ธฐ๋ฅ ํ๋๊ทธ์์ ์ฌ์ฉ์์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ false(๊บผ์ง ์ํ)๋ฅผ ๋ฐํํฉ๋๋ค.
boolean isFeatureOn = hackleClient.isFeatureOn(42, "ae03e1adf");
if (isFeatureOn) {
// ON ๊ธฐ๋ฅ
} else {
// OFF ๊ธฐ๋ฅ
}import io.hackle.sdk.HackleClient
// ๊ธฐ๋ฅ ํค๊ฐ 42์ธ ๊ธฐ๋ฅ ํ๋๊ทธ์์ ์ฌ์ฉ์์ ์ํ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
// ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ false(๊บผ์ง ์ํ)๋ฅผ ๋ฐํํฉ๋๋ค.
val isFeatureOn: Boolean = hackleClient.isFeatureOn(42, "ae03e1adf")
if (isFeatureOn) {
// ON ๊ธฐ๋ฅ
} else {
// OFF ๊ธฐ๋ฅ
}๋ถ๋ฐฐ๊ฒฐ๊ณผ ํ์ธํ๊ธฐ
ํตํด ๋์๋ณด๋ ์์ [์ผ์ชฝ ๋ฉ๋ด๋ฐ] - ๋ ๊ธฐ๋ฅํ๋๊ทธ] ํ๋ฉด์์ ๋ ธ์ถ๋๋ ํ๋ฉด์์ ๋ ธ์ถ๋๋ A/Bํ ์คํธ ๋๋ ๊ธฐ๋ฅํ๋๊ทธ ๋ฆฌ์คํธ ์ค ์ฐ๋ํ ๋์์ ์ฐพ์ ์์ธ ํ์ด์ง๋ก ์ด๋ ํ ํ ํ๋ฉด ์ค๊ฐ์ [์ค์๊ฐ ๋ ธ์ถ ํํฉ] ํญ์ ํด๋ฆญํ๋ฉด SDK๋ก ์ฐ๋ ๋ ๋ถ๋ฐฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
5. ์ข
๋ฃ
import io.hackle.sdk.HackleClient
hackleClient.close();import io.hackle.sdk.HackleClient
hackleClient.close()์ดํ๋ฆฌ์ผ์ด์
์ด ์ข
๋ฃ๋ ๋ close() ๋ฉ์๋๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค. ์ด ๊ณผ์ ์ ํตํด ์ฌ์ฉ ์ค์ธ ๋ฆฌ์์ค๋ฅผ ๋ฐ๋ฉํ๊ณ ๋จ์์๋ ์ด๋ฒคํธ๋ฅผ ์ ์กํฉ๋๋ค. ์ด ๊ณผ์ ์์ด ์ดํ๋ฆฌ์ผ์ด์
์ด ์ข
๋ฃ๋๋ฉด ์ด๋ฒคํธ๊ฐ ๋๋ฝ๋ ์ ์์ต๋๋ค.
์คํ๋ง ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉ ์ค์ด๋ผ๋ฉด?
HackleClient๋ฅผ ๋น(bean)์ผ๋ก ๋ฑ๋กํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค.
์ดํ๋ฆฌ์ผ์ด์ ์๋ช ์ฃผ๊ธฐ ๋์ ์ฑ๊ธ ์ธ์คํด์ค๋ก ๊ด๋ฆฌ๊ฐ ๋๋ฉฐ ์ดํ๋ฆฌ์ผ์ด์ ์ข ๋ฃ ์close()๊น์ง ์๋์ผ๋ก ํธ์ถ๋ฉ๋๋ค.
Hackle Client ๋ฅผ wrapping ํ์ฌ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ
wrapping ํด๋์ค์ AutoClosable implementation ํ์๊ณ close() ์์ HackleClient ์ close()๋ฅผ ํธ์ถ ํ์๋ ๋ฐฉ๋ฒ์ ๊ถ์ฅ๋๋ฆฝ๋๋ค.
import io.hackle.sdk.HackleClient
public class CustomHackleClient implements AutoCloseable {
private final HackleClient hackleClient;
public CustomHackleClient(HackleClient hackleClient) {
this.hackleClient = hackleClient;
}
@Override
public void close() throws Exception {
hackleClient.close();
}
}import io.hackle.sdk.HackleClient
class CustomHackleClient(private val hackleClient: HackleClient): AutoCloseable {
override fun close() {
hackleClient.close()
}
}Updated 14 days ago
