SDK ์ฐ๋
Hackle Python SDK๋ Python 3 ์ด์์ ์ง์ํฉ๋๋ค.
WSGI ํ๊ฒฝ์ ์ฌ์ฉํ์๋ ๊ฒฝ์ฐ ๊ฐ์ด๋ WSGI ์ค์ ์ ๊ผญ ํ์ธํด์ฃผ์ธ์
1. ์์กด์ฑ ์ถ๊ฐ
pip install hackle-sdk2. SDK ์ด๊ธฐํ
hackle_client๋ SDK ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํ ๋ฉ์๋๋ค์ ์ ๊ณตํ๋ ํด๋์ค์
๋๋ค.
SDK๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ hackle_client ์ด๊ธฐํ๊ฐ ํ์ํฉ๋๋ค.
์ธ์คํด์คํ
SDK ํค๋ฅผ ์ ๋ฌํ์ฌ hackle_client๋ฅผ ์ธ์คํด์คํ ํฉ๋๋ค.
hackle_client๋ ํ์ํ ์ ๋ณด๋ค์ ์ป๊ธฐ ์ํด ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ผ๋ก ํตํด ์๋ฒ์ ์ฃผ๊ธฐ์ ์ผ๋ก ๋๊ธฐํํฉ๋๋ค.
- SDK ํค๋ ํตํด ์๋น์ค์ ๋์๋ณด๋ ์์ ์์นํ SDK ์ฐ๋ ์ ๋ณด์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
hackle_client๋ ์ ์ญ๋ณ์์ด๋ฉฐ, ๋ฐ๋์ ํ ๋ฒ๋ง ์์ฑํด์ผ ํฉ๋๋ค.hackle_client๋ ์ฐ๋ ๋์์ I/O์์ด ๋ฐ๋ก ๊ฒฐ๊ณผ๋ฅผ ํ๊ฐํ๊ธฐ ์ํด ๋ด๋ถ์ ์ผ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์ด๋ฅผ ์ํด ์ถ๊ฐ์ ์ธ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ชจ๋ ์์ฒญ์ ๋ํด ์๋ก์ด ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ์๊ณ , ์ด๋ฏธ ์์ฑ๋์ด ์๋ ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.
hackle_client ๋ ์ฑ๊ธํค(Singleton) ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ ธ ์๊ธฐ ๋๋ฌธ์, ๋ค๋ฅธ ํจ์์์ ์ฌ์ฉํ ๋ hackle.Client()๋ก ์ฌ์ฉํด๋ ์ฌ์์ฑํ์ง ์์ต๋๋ค.
from hackle import hackle
// YOUR_SERVER_SDK_KEY ์๋ฆฌ์ SDK ํค๋ฅผ ๋ฃ์ต๋๋ค.
hackle_client = hackle.Client(sdk_key=YOUR_SERVER_SDK_KEY)3. ์ฌ์ฉ์ ์ด๋ฒคํธ ์ ์ก
์ฌ์ฉ์๊ฐ ์ํํ๋ ํ๋์ ์ด๋ฒคํธ๋ก ์ ์กํ ์ ์์ต๋๋ค. ์ ์ก๋ ์ด๋ฒคํธ๋ A/B ํ
์คํธ ๋ถ์, ๋ฐ์ดํฐ ๋ถ์ ๋ฑ์ ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ๋ค์ด, ์ฌ์ฉ์๊ฐ ๊ตฌ๋งค๋ผ๋ ํ๋์ ํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ด๋ฒคํธ๋ฅผ ์ ์กํ ์ ์์ต๋๋ค.
from hackle.model import HackleUser, HackleEvent
# "ae2182e0"๋ผ๋ ๋๋ฐ์ด์ค ์๋ณ์๋ฅผ ๊ฐ์ง ์ฌ์ฉ์๊ฐ ๋ฐ์์ํจ "purchase"๋ผ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ก
user = HackleUser.builder() \
.device_id('ae2182e0') \
.build()
event = HackleEvent.builder('purchase') \
.property('pay_method', 'CARD') \
.property('discount_amount', 800) \
.property('is_discounted', True) \
.build()
hackle_client.track(event=event, user=user)์ฌ์ฉ์ ์ด๋ฒคํธ ์ ์ก ํ์ธํ๊ธฐ
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.builder() \
.device_id('ae2182e0') \
.build()
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์ธ ๊ธฐ๋ฅ ํ๋๊ทธ์์
# "ae2182e0"๋ผ๋ ๋๋ฐ์ด์ค ์๋ณ์๋ฅผ ๊ฐ์ง ์ฌ์ฉ์์๊ฒ ๋
ธ์ถํ ํ
์คํธ ๊ทธ๋ฃน์ ๊ฒฐ์ ํฉ๋๋ค.
# ๊ฒฐ์ ํ์ง ๋ชปํ๋ ์ํฉ์ธ ๊ฒฝ์ฐ false(๊บผ์ง ์ํ)๋ฅผ ๋ฐํํฉ๋๋ค.
user = HackleUser.builder() \
.device_id('ae2182e0') \
.build()
feature_on = hackle_client.is_feature_on(feature_key=42, user=user)
# ํ ๋น๋ฐ์ ๊ทธ๋ฃน์ ๋ํ ๋ก์ง
if feature_on == True:
# ON ๊ธฐ๋ฅ
elif feature_on == False:
# OFF ๊ธฐ๋ฅ๋ถ๋ฐฐ๊ฒฐ๊ณผ ํ์ธํ๊ธฐ
ํตํด ๋์๋ณด๋ ์์ [์ผ์ชฝ ๋ฉ๋ด๋ฐ] - ๋ ๊ธฐ๋ฅํ๋๊ทธ] ํ๋ฉด์์ ๋ ธ์ถ๋๋ ํ๋ฉด์์ ๋ ธ์ถ๋๋ 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()Updated 10 days ago
