SDK 연동

몇 가지 단계를 거쳐 빠르게 SDK 연동을 시작해보세요.

  1. 의존성 추가
  2. SDK 초기화
  3. 사용자 설정
  4. 이벤트 전송
  5. A/B 테스트
  6. 기능 플래그

1. 의존성 추가

repositories {
  mavenCentral()
}

build.gradle 파일에 의존성을 추가합니다.

dependencies {
  implementation 'io.hackle:hackle-android-sdk:2.37.0'
}

ProGuard

ProGuard를 사용하는 경우, aar 아티팩트에 난독화 규칙이 자동으로 포함됩니다. 이 경우가 아니라면 아래 규칙을 포함시켜야 합니다.

-keep class io.hackle.android.** { *; }
-keep class io.hackle.sdk.** { *; }

2. SDK 초기화

SDK를 사용하기 위해서 반드시 HackleApp을 초기화 해야 합니다. HackleApp을 초기화 하기 위해 SDK 키가 필요합니다.

  • HackleApp은 SDK의 기능을 사용하기 위한 메소드들을 제공하는 클래스입니다.
  • SDK 키는 핵클 서비스의 대시보드 안에 위치한 SDK 연동 정보에서 확인하실 수 있습니다.
import io.hackle.android.Hackle
import io.hackle.android.initialize

Hackle.initialize(applicationContext, YOUR_APP_SDK_KEY)
import io.hackle.android.HackleApp;

HackleApp.initializeApp(getApplicationContext(), YOUR_APP_SDK_KEY);

초기화 완료

초기화가 시작되면 핵클 서버로부터 필요한 정보들을 가져와서 SDK에 저장합니다. 이 작업은 비동기로 실행되며, 초기화시 마지막 파라미터로 콜백을 전달하면 SDK 사용 준비가 완료된 것을 알 수 있습니다. 초기화가 완료 되기 전에 A/B 테스트, 기능 플래그를 호출하면 기본 그룹(A), 꺼짐(false)을 리턴합니다.

import io.hackle.android.Hackle
import io.hackle.android.initialize

Hackle.initialize(applicationContext, YOUR_APP_SDK_KEY) {
  // SDK ready to use.
}
import io.hackle.android.HackleApp;

HackleApp.initializeApp(getApplicationContext(), YOUR_APP_SDK_KEY, () -> {
  // SDK ready to use.
});

권장 초기화 전략: 로딩 화면을 통한 초기화

앱을 즉시 시작하지 않고 로딩 화면을 표시하고 SDK를 초기화합니다.
이후 콜백을 통해 로딩 화면을 닫고 사용자가 앱과 상호작용을 시작할 수 있도록 합니다.

이 전략을 사용하는 경우 로딩 화면에 제한 시간을 두는 것이 좋습니다.

인스턴스 가져오기

초기화 이후 아래 코드를 통해 HackleApp 인스턴스를 가져올 수 있습니다.

import io.hackle.android.Hackle
import io.hackle.android.app

val hackleApp = Hackle.app
import io.hackle.android.HackleApp;

HackleApp hackleApp = HackleApp.getInstance();

초기화 설정정보

설정정보를 포함하여 SDK를 초기화 할 수 있습니다.

import io.hackle.android.Hackle
import io.hackle.android.HackleConfig
import io.hackle.android.initialize

val config = HackleConfig.builder()
  .exposureEventDedupIntervalMillis(1000)
  .build()

Hackle.initialize(applicationContext, YOUR_APP_SDK_KEY, config) {
  // SDK ready to use.
}
import io.hackle.android.HackleApp;
import io.hackle.android.HackleConfig;

HackleConfig config = HackleConfig.builder()
  .exposureEventDedupIntervalMillis(1000)
  .build();

HackleApp.initializeApp(getApplicationContext(), YOUR_APP_SDK_KEY, config, () -> {
  // SDK ready to use.
});

모든 설정 옵션

설정기능기본값지원 버전
exposureEventDedupIntervalMillis동일한 사용자가 연속으로 발생시킨 동일한 A/B 테스트, 기능플래그 분배결과에 대한 노출 이벤트를 제거합니다.

최솟값: 1000 (1초)
최댓값: 3600000 (1시간)
60000 (1분)2.7.0+
pollingIntervalMillis대시보드에서 설정한 정보를 주기적으로 업데이트 할 수 있습니다.

최솟값 : 60000 (60초)
-1
(주기적으로 업데이트하지 않음)
2.19.0+

대시보드 설정 정보 갱신

대시보드 설정 정보를 명시적으로 갱신 할 수 있습니다.

hackleApp.fetch {
  // done
}
hackleApp.fetch(new Runnable() {
    @Override
    public void run() {
        // done
    }
});

📘

핵클 안드로이드 SDK 2.34.0 이상 버전에서 지원하는 기능입니다.

🚧

해당 함수는 60초에 한번 제한적으로 호출할 수 있습니다.

Third-party 의존성

핵클 Android SDK는 아래와 같은 third-party 의존성을 가지고 있습니다

  • com.squareup.okhttp3:okhttp:3.12.2
  • com.google.code.gson:gson:2.8.6
  • com.google.android.gms:play-services-base:17.3.0

3. 사용자 설정

사용자 정보를 SDK에 설정 할 수 있습니다.

사용자 ID 설정

사용자가 로그인한 경우, setUserId를 호출해서 로그인한 사용자의 ID를 설정할 수 있습니다.

  • 로그인 시 한번만 설정하면 됩니다.
  • 이미 로그인이 되어있는 사용자의 경우에는 로그인한 정보를 확인하는 시점에 호출하면 됩니다.
val userId: String = ... // 로그인한 사용자의 ID (회원번호, 멤버 ID 등)
hackleApp.setUserId(userId)
String userId = ... // 로그인한 사용자의 ID (회원번호, 멤버 ID 등)
hackleApp.setUserId(userId);

사용자 속성 설정

이메일주소, 위치, 나이, 회원등급과 같은 정보를 사용자 속성으로 사용할 수 있습니다.

import io.hackle.sdk.common.PropertyOperations

val operations = PropertyOperations.builder()
    .set("age", 42)
    .set("grade", "GOLD")
    .build()

hackleApp.updateUserProperties(operations)
import io.hackle.sdk.common.PropertyOperations;

PropertyOperations operations = PropertyOperations.builder()
    .set("age", 42)
    .set("grade", "GOLD")
    .build();

hackleApp.updateUserProperties(operations);

사용자 로그아웃 시 재설정

사용자가 로그아웃 한 경우 resetUser를 호출하여 기존에 설정한 사용자 정보를 리셋할 수 있습니다. 아래 정보가 리셋됩니다.

  • 사용자 ID
  • 사용자 속성
hackleApp.resetUser()
hackleApp.resetUser();

4. 이벤트 전송

사용자가 수행하는 행동을 이벤트로 전송할 수 있습니다. 전송된 이벤트는 A/B 테스트 분석, 데이터 분석 등에 사용됩니다. 예를들어, 사용자가 구매라는 행동을 했다면 아래와 같이 이벤트를 전송할 수 있습니다.

import io.hackle.sdk.common.Event  

// 이벤트 전송
hackleApp.track("purchase")

// 이벤트를 속성과 함께 전송
val event = Event.builder("purchase")
    .property("amount", 4200)
    .property("pay_method", "CARD")
    .property("is_discount", false)
    .property("product_ids", listOf(42, 43))
    .build()
hackleApp.track(event)
import io.hackle.sdk.common.Event;

// 이벤트 전송
hackleApp.track("purchase");

// 이벤트를 속성과 함께 전송
Event event = Event.builder("purchase")
    .property("amount", 4200)
    .property("pay_method", "CARD")
    .property("is_discount", false)
    .property("product_ids", Arrays.asList(42, 43))
    .build();
hackleApp.track(event);

전송한 이벤트 확인하기

대시보드 이벤트관리 메뉴에서 전송한 이벤트를 확인할 수 있습니다. 이벤트 전송 후 대시보드에 표시되기까지 일반적으로 ~60초가 걸립니다.


5. A/B 테스트

사용자를 테스트 그룹으로 분배하고 분배된 결과에 해당하는 로직을 작성하여 A/B 테스트를 구현합니다. variation에 실험키를 전달하여 호출하면 분배결과를 리턴받을 수 있습니다.

실험키: 각 A/B 테스트별로 갖게 되는 고유 번호입니다. A/B 테스트를 생성하면 자동으로 발급됩니다.

import io.hackle.sdk.common.Variation

// 실험 키가 42인 A/B 테스트에서 사용자에게 노출할 테스트 그룹을 결정합니다.
val variation: Variation = hackleApp.variation(42)

// 할당받은 그룹에 대한 로직
if (variation == Variation.A) {
  // 그룹 A 로직
} else if (variation == Variation.B) {
  // 그룹 B 로직
}
import io.hackle.sdk.common.Variation;

// 실험 키가 42인 A/B 테스트에서 사용자에게 노출할 테스트 그룹을 결정합니다.
Variation variation = hackleApp.variation(42);

// 할당받은 그룹에 대한 로직
if (variation == Variation.A) {
  // 그룹 A 로직
} else if (variation == Variation.B) {
  // 그룹 B 로직
}

분배 결과 확인하기

대시보드 A/B 테스트의 상세페이지의 실시간 노출 현황 탭에서 분배된 결과를 확인할 수 있습니다. 분배 후 대시보드에 표시되기까지 일반적으로 ~60초가 걸립니다.


6. 기능 플래그

기능 플래그는 켜짐(on) 상태와 꺼짐(off) 상태가 있습니다. 상태에 따라 다른 로직을 작성하여 기능 플래그를 구현합니다. isFeatureOn에 기능플래그키를 전달하여 호출하면 on/off 여부를 리턴받을 수 있습니다.

기능플래그키: 각 기능플래그별로 갖게 되는 고유 번호입니다. 기능플래그를 생성하면 자동으로 발급됩니다.

// 기능 키가 42인 기능 플래그에서 사용자의 상태를 결정합니다.
val featureOn = hackleApp.isFeatureOn(42)

if (featureOn) {
    // ON 기능
} else {
    // OFF 기능
}
// 기능 키가 42인 기능 플래그에서 사용자의 상태를 결정합니다.
boolean featureOn = hackleApp.isFeatureOn(42);

if (featureOn) {
    // ON 기능
} else {
    // OFF 기능
}