SDK 연동

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

  • 단계1. SDK 의존성 추가
  • 단계2. SDK 초기화
  • 단계3. 사용자 이벤트 전송
  • 단계4. A/B 테스트, 기능플래그
  • 단계5. 종료

📘

WSGI 환경을 사용하시는 경우 가이드 하단 WSGI 설정 을 꼭 확인해주세요


단계 1. SDK 의존성 추가

pip install hackle-sdk

단계 2. SDK 초기화

hackle_client는 SDK 기능을 사용하기 위한 메소드들을 제공하는 클래스입니다.

인스턴스화

from hackle import hackle

// YOUR_SERVER_SDK_KEY 자리에 SDK 키를 넣습니다.
hackle_client = hackle.Client(sdk_key='YOUR_SERVER_SDK_KEY')

SDK 키를 전달하여 hackle_client를 인스턴스화 합니다.
hackle_client는 필요한 정보들을 얻기 위해 백그라운드 작업으로 핵클 서버와 주기적으로 동기화합니다.

❗️

hackle_client는 전역변수이며, 반드시 한 번만 생성해야 합니다.

hackle_client는 쓰레드에서 I/O없이 바로 결과를 평가하기 위해 내부적으로 상태를 관리합니다. 이를 위해 추가적인 리소스를 사용합니다. 모든 요청에 대해 새로운 인스턴스를 생성하지 않고, 이미 생성되어 있는 인스턴스를 사용합니다.

hackle_client 는 싱글톤(Singleton) 객체로 만들어져 있기 때문에, 다른 함수에서 사용할 때 hackle.Client()로 사용해도 재생성하지 않습니다.

SDK 키는 단계 1에서 가입한 핵클 대시보드 안에서 확인할 수 있습니다. SDK 연동 정보 에서 SDK 종류/환경 별 SDK 키를 확인 후 Server SDK 키를 복사하여 사용하세요.

2556

SDK 키 정보 확인하기

단계 3. 사용자 이벤트 전송

핵클 SDK는 사용자 이벤트를 핵클로 전송하는 기능을 제공합니다.
사용자 행동의 변화가 일어나는 지점마다 이 기능을 활용하면 사용자 행동에 대한 유의미한 데이터를 얻을 수 있으며, 그렇게 모인 데이터를 통해 사용자 행동 분석을 할 수 있습니다.

track

track() 메소드에 이벤트 키사용자 식별자를 전달하여 사용자 이벤트를 전송할 수 있습니다. 필요한 경우 사용자 이벤트 전송 시 숫자 값을 value에 넣어 함께 전송할 수 있습니다.

  • value는 number 타입만 넣을 수 있습니다.

예시

사용자가 구매하기 버튼을 눌렀을 때 이벤트를 수집하기 위해 purchase 라는 이벤트 키를 정의했다고 가정합니다.
이 때 구매 속성정보를 같이 수집하고 싶을 수 있습니다. 이런 경우 property에 구매 속성정보를 함께 받을 수 있습니다.

from hackle.model import HackleUser, Hackle


# "ae2182e0"라는 식별자를 가진 사용자가 발생시킨 "purchase"라는 이벤트를 전송

# 예시 1: 이벤트 키만 전송
event = Hackle.event(key='purchase')
user = HackleUser(id='ae2182e0')
hackle_client.track(event=event, user=user)

# 예시 2: 이벤트 키와 속성정보를 함께 전송
event = Hackle.event(key='purchase',
                     pay_method='CARD',
                     discount_amount=800,
                     is_discount=True
                    )
user = HackleUser(id='ae2182e0')
hackle_client.track(event=event, user=user)

예시 1에서는 이벤트 키만 전송하고 있으며, 예시 2에서는 구매 속성정보를 함께 수집하기 위해 property 에 구매 속성정보를 넣은 사례를 보여주고 있습니다.

사용자 이벤트 전송 확인하기

SDK 에서 전송한 사용자 이벤트가 정상적으로 수집되고 있는지 확인해보세요.
핵클 대시보드 안의 [왼쪽 메뉴바] - [이벤트 관리] 메뉴에서 SDK로 전송한 이벤트를 찾아 실시간 이벤트 수집현황을 확인해볼 수 있습니다.

단계 4. A/B 테스트, 기능플래그

A/B 테스트

A/B 테스트를 진행할 때, 테스트 그룹을 대상으로 사용자를 분배하고 각 테스트 그룹에 해당하는 로직을 작성해야 합니다. 이 때 사용자 분배를 핵클 SDK를 통해 진행할 수 있습니다.

📘

테스트 그룹

테스트 그룹은 테스트 대상이 되는 기존안(대조군)과 개선안(실험군)을 의미하며, 개선안은 1개 이상일 수 있습니다. 대시보드에서 설정 가능하며, 테스트 그룹을 관리하는 방법에 대해서는 A/B 테스트 설정 문서를 참고하시기 바랍니다.

variation

variation() 메소드에 실험 키사용자 식별자를 전달하면 사용자를 분배하고 결과를 전달받을 수 있습니다. 이후 테스트 그룹 별 로직을 구현합니다.
실험 키는 각 A/B 테스트별로 갖게 되는 고유 번호이며, 핵클 서비스 내의 대시보드에서 확인할 수 있습니다.
아래 예제 코드에서는 실험 키 42를 전달하고 있으며, 테스트 그룹은 A와 B 두 개가 존재합니다.

from hackle.model import HackleUser

# 실험 키가 42인 A/B 테스트에서
# "ae2182e0"라는 식별자를 가진 사용자에게 노출할 테스트 그룹을 결정합니다.
# 결정하지 못하는 상황인 경우 테스트 그룹 A를 반환합니다.
user = HackleUser(id='ae2182e0')
variation = hackle_client.variation(experiment_key=42, user=user)

# 할당받은 그룹에 대한 로직
if variation == 'A':
    # 그룹 A 로직
elif variation == 'B':
    # 그룹 B 로직

기능플래그

📘

기능 플래그는 SDK 버전 2.0.0 이상인 경우 사용 가능합니다.

기능 플래그를 사용하시는 경우 의존성 추가 시 SDK 버전을 2.0.0 이상으로 적용하시기 바랍니다.

기능 플래그는 켜짐(on) 상태와 꺼짐(off) 상태가 있습니다. 각 상태에 따라 다른 기능을 설정하게 됩니다.
기능 플래그를 적용한 기능에 어떤 사용자가 접근할 경우 켜짐 혹은 꺼짐 상태를 받을 수 있어야 합니다. 이 상태 결정을 핵클 SDK를 통해 진행할 수 있습니다.

isFeatureOn

is_feature_on() 메소드에 기능 키를 전달하면 사용자에 대한 상태 결과를 전달받을 수 있습니다. 이후 상태에 따른 로직을 구현합니다.
기능 키는 각 기능 플래그별로 갖게 되는 고유 번호이며 핵클 서비스 내의 대시보드에서 확인하실 수 있습니다.
아래 예제 코드에서는 기능 키 42를 전달하고 있으며, 상태를 받을 사용자의 사용자 식별자는 "ae03e1adf" 입니다.

from hackle.model import HackleUser

# 기능 키가 42인 기능 플래그에서 사용자의 상태를 결정합니다.
# 결정하지 못하는 상황인 경우 false(꺼짐 상태)를 반환합니다.
user = HackleUser(id='ae03e1adf')
feature_on = hackle_client.is_feature_on(feature_key=42, user=user)

# 할당받은 그룹에 대한 로직
if feature_on == True:
    # ON 기능
elif feature_on == False:
    # OFF 기능

분배결과 확인하기

핵클 대시보드 안의 [왼쪽 메뉴바] - [A/B 테스트 또는 기능플래그] 화면에서 노출되는 A/B테스트 또는 기능플래그 리스트 중 연동한 대상을 찾아 상세 페이지로 이동 한 후 화면 중간에 [실시간 노출 현황] 탭을 클릭하면 SDK로 연동 된 분배 결과를 볼 수 있습니다.

단계 5. 종료

hackle_client.close()

어플리케이션이 종료될 때 hackle_client.close() 메소드를 통해 hackle_client를 종료시켜야 합니다. 이를 통해 클라이언트가 사용 중인 리소스를 반납하고 남아있는 이벤트를 전송합니다. 이 과정없이 어플리케이션이 종료되면 이벤트가 누락될 수 있습니다.

Flask나 Django를 사용 중 이라면?

@atexit.register를 통해 어플리케이션 종료 시 자동으로 hackle_client를 종료시킬 수 있습니다.

import atexit

@atexit.register
def __exit__():
    hackle_client.close()

WSGI 설정

WSGI를 사용중인 경우 프로세스가 fork된 이후 hackle_client를 초기화 해야 합니다.

uWSGI

# Step 1: uwsgi.ini 설정
enable-threads = True


# Step 2: app.py 설정
from hackle import hackle
from uwsgidecorators import postfork

class HackleClient:
    client = None

    def init(self):
        if self.client is None:
            self.client = hackle.Client(sdk_key='YOUR_SERVER_SDK_KEY')


hackle_client = HackleClient()


# Step 3: post_fork 설정
@postfork
def post_fork(server, worker):
    hackle_client.init()


# Step 4: hackleClient 사용 시
from app import hackle_client

hackle_client.client.variation(...)

gunicorn

# Step 1: app.py 설정
from hackle import hackle

class HackleClient:
    client = None

    def init(self):
        if self.client is None:
            self.client = hackle.Client(sdk_key='YOUR_SERVER_SDK_KEY')


hackle_client = HackleClient()

def post_fork(server, worker):
    hackle_client.init()


# Step 2: gunicorn.conf.py 설정
from app import post_fork

post_fork = post_fork


# Step 3: hackleClient 사용 시
from app import hackle_client

hackle_client.client.variation(...)

gevent 설정

gevent의 몽키패치처럼 내부 통신 방식을 non-blocking 으로 변경하게 되는 경우라면 실제로 호출 시점에 인스턴스가 생성되도록 생성 시점을 지연시켜야 합니다.

# step 1: gevent monkey patch
import gevent.monkey
gevent.monkey.patch_all()

# step 2: app.py wrapper function
from hackle import hackle

def hackle_wrapper():
    if 'client' not in hackle_wrapper.__dict__:
        hackle_wrapper.client = hackle.Client(sdk_key='YOUR_SERVER_SDK_KEY')
    return hackle_wrapper.client

# step 3: hackleClient 사용 시
from app import hackle_wrapper

hackle_wrapper().variation(...)