SDK ์—ฐ๋™

๐Ÿ“˜

Hackle React SDK๋Š” React 16.8 ์ด์ƒ ๋ฒ„์ „์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

React SDK๋Š” JavaScript SDK ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


1. ์˜์กด์„ฑ ์ถ”๊ฐ€

npm install --save @hackler/react-sdk
yarn add @hackler/react-sdk

2. SDK ์ดˆ๊ธฐํ™”

SDK๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฐ˜๋“œ์‹œ HackleReactSDKClient ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • HackleReactSDKClient๋Š” SDK์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • SDK ํ‚ค๋Š” ํ•ตํด ์„œ๋น„์Šค์˜ ๋Œ€์‹œ๋ณด๋“œ ์•ˆ์— ์œ„์น˜ํ•œ SDK ์—ฐ๋™ ์ •๋ณด์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„์— ํ•ตํด ์„œ๋ฒ„์™€ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•œ ํ†ต์‹ ์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ด ์‹œ๊ฐ„์€ ์ˆ˜ ๋ฐ€๋ฆฌ ์ดˆ์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค. ๋™๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ฆ‰์‹œ ๋ Œ๋”๋ง์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

๐Ÿšง

Google Tag Manager (GTM) ์‚ฌ์šฉ์‹œ ์ฃผ์˜ ์‚ฌํ•ญ

GTM์„ ์‚ฌ์šฉํ•˜์—ฌ ์—ฐ๋™์„ ์ง„ํ–‰ํ•  ๊ฒฝ์šฐ, Hackle SDK ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜๊ณ , SDK๋ฅผ GTM ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก window์— ์ถ”๊ฐ€ ์„ ์–ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

import { createInstance, HackleProvider } from "@hackler/react-sdk";

// YOUR_BROWSER_SDK_KEY ์ž๋ฆฌ์— SDK ํ‚ค๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.
const hackleClient = createInstance("YOUR_BROWSER_SDK_KEY")

ReactDOM.render(
  <HackleProvider hackleClient={hackleClient}>
    <YourApp />
  </HackleProvider>,
  document.getElementById('root')
);

// GTM ์—ฐ๋™ ์‹œ ์ถ”๊ฐ€ script
window.hackleClient = hackleClient
import {createInstance, HackleProvider} from "@hackler/react-sdk";

// YOUR_BROWSER_SDK_KEY ์ž๋ฆฌ์— SDK ํ‚ค๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.
const hackleClient = createInstance("YOUR_BROWSER_SDK_KEY")

function MyApp({Component, pageProps}) {
  return (
    <HackleProvider hackleClient={hackleClient} supportSSR>
      <Component {...pageProps} />
    </HackleProvider>
  )
}

export default MyApp
import {createInstance, HackleProvider} from "@hackler/react-sdk";

// YOUR_BROWSER_SDK_KEY ์ž๋ฆฌ์— SDK ํ‚ค๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.
const hackleClient = createInstance("YOUR_BROWSER_SDK_KEY")

function App() {
  return (
    <HackleProvider hackleClient={hackleClient} supportSSR>
      <YourApp />
    </HackleProvider>
  )
}

export default App

์ดˆ๊ธฐํ™” ์„ค์ •์ •๋ณด

์„ค์ •์ •๋ณด๋ฅผ ํฌํ•จํ•˜์—ฌ SDK๋ฅผ ์ดˆ๊ธฐํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋””๋ฒ„๊ทธ ๋ชจ๋“œ

debug ์˜ต์…˜์„ true ๋กœ ์„ค์ •ํ•˜์—ฌ ํ™œ์„ฑํ™” ํ•ฉ๋‹ˆ๋‹ค. ๋””๋ฒ„๊ทธ ๋ชจ๋“œ๋ฅผ ํ™œ์„ฑํ™” ์‹œํ‚ค๋ฉด ๋ชจ๋“  ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋กœ๊ทธ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

import { createInstance, HackleProvider } from "@hackler/react-sdk";

// ์„ค์ •์ •๋ณด๋ฅผ ํฌํ•จํ•˜์—ฌ ์ดˆ๊ธฐํ™”
const config = {
  debug: true
};

const hackleClient = createInstance("YOUR_BROWSER_SDK_KEY", config);

ReactDOM.render(
  <HackleProvider hackleClient={hackleClient}>
    <YourApp />
  </HackleProvider>,
  document.getElementById('root')
);
import {createInstance, HackleProvider} from "@hackler/react-sdk";

// ์„ค์ •์ •๋ณด๋ฅผ ํฌํ•จํ•˜์—ฌ ์ดˆ๊ธฐํ™”
const config = {
  debug: true
};

const hackleClient = createInstance("YOUR_BROWSER_SDK_KEY", config);
        
function MyApp({Component, pageProps}) {
  return (
    <HackleProvider hackleClient={hackleClient} supportSSR>
      <Component {...pageProps} />
    </HackleProvider>
  )
}

export default MyApp

๋ชจ๋“  ์„ค์ •์˜ต์…˜

key

๊ธฐ๋Šฅ

๊ธฐ๋ณธ๊ฐ’

์ง€์› ๋ฒ„์ „

debug

๋ชจ๋“  ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋””๋ฒ„๊ทธ(debug) ๋กœ๊ทธ๋ฅผ ์ฝ˜์†”(console)์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

false

1.0.0+

pollingIntervalMillis

๋Œ€์‹œ๋ณด๋“œ์—์„œ ์„ค์ •ํ•œ ์ •๋ณด๋ฅผ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์†Ÿ๊ฐ’ : 60000 (60์ดˆ)

-1

11.1.0+

exposureEventDedupIntervalMillis

๋™์ผํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ์—ฐ์†์œผ๋กœ ๋ฐœ์ƒ์‹œํ‚จ ๋™์ผํ•œ A/B ํ…Œ์ŠคํŠธ, ๊ธฐ๋Šฅํ”Œ๋ž˜๊ทธ ๋ถ„๋ฐฐ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ๋…ธ์ถœ ์ด๋ฒคํŠธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์ตœ์†Ÿ๊ฐ’: 1000 (1์ดˆ)
์ตœ๋Œ“๊ฐ’: 3600000 (1์‹œ๊ฐ„)

36000(1๋ถ„ / 11.23.0 ๋ฒ„์ „ ์ด์ƒ)

-1 (์ค‘๋ณต์ œ๊ฑฐ ํ•˜์ง€ ์•Š์Œ / 11.23.0 ๋ฒ„์ „ ๋ฏธ๋งŒ)

11.1.0+

sessionTimeoutMillis

์„ธ์…˜๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

1800000 (30๋ถ„)

11.8.0+

devTool

์‚ฌ์šฉ์ž ํƒ์ƒ‰์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
์ž์„ธํ•œ ์„ค๋ช…์€ ์‚ฌ์šฉ์ž ํƒ์ƒ‰ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

undefined

11.13.0+

autoOpenDevTool

์‚ฌ์šฉ์ž ํƒ์ƒ‰ ๋ฒ„ํŠผ์ด ์ž๋™์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋„๋ก ํ•˜๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

false

11.13.0+

๋Œ€์‹œ๋ณด๋“œ ์„ค์ • ์ •๋ณด ๊ฐฑ์‹ 

๋Œ€์‹œ๋ณด๋“œ ์„ค์ • ์ •๋ณด๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๊ฐฑ์‹  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

hackleClient.fetch();
๐Ÿšง

ํ•ด๋‹น ํ•จ์ˆ˜๋Š” 60์ดˆ์— ํ•œ๋ฒˆ ์ œํ•œ์ ์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3. ์‚ฌ์šฉ์ž ์„ค์ •

์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ SDK์— ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ID ์„ค์ •

์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธํ•œ ๊ฒฝ์šฐ, setUserId ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ID๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋กœ๊ทธ์ธ ์‹œ ํ•œ๋ฒˆ๋งŒ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฏธ ๋กœ๊ทธ์ธ์ด ๋˜์–ด์žˆ๋Š” ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ์—๋Š” ๋กœ๊ทธ์ธํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๋Š” ์‹œ์ ์— ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
const userId = ... // ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ID (ํšŒ์›๋ฒˆํ˜ธ, ๋ฉค๋ฒ„ ID ๋“ฑ)
hackleClient.setUserId(userId);

์‚ฌ์šฉ์ž ์†์„ฑ ์„ค์ •

์ด๋ฉ”์ผ์ฃผ์†Œ, ์œ„์น˜, ๋‚˜์ด, ํšŒ์›๋“ฑ๊ธ‰๊ณผ ๊ฐ™์€ ์ •๋ณด๋ฅผ ์‚ฌ์šฉ์ž ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. setUserProperty, setUserProperties ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉ์ž ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { PropertyOperationsBuilder } from "@hackler/react-sdk"

const operations = new PropertyOperationsBuilder()
    .set("age", 42)
    .set("grade", "GOLD")
    .build();

hackleClient.updateUserProperties(operations);

์‚ฌ์šฉ์ž ๋กœ๊ทธ์•„์›ƒ ์‹œ ์žฌ์„ค์ •

์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒ ํ•œ ๊ฒฝ์šฐ resetUser๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ธฐ์กด์— ์„ค์ •ํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฆฌ์…‹ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์ •๋ณด๊ฐ€ ๋ฆฌ์…‹๋ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž ID
  • ์‚ฌ์šฉ์ž ์†์„ฑ
hackleClient.resetUser();

4. ์ด๋ฒคํŠธ ์ „์†ก

์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ํ–‰๋™์„ ์ด๋ฒคํŠธ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์†ก๋œ ์ด๋ฒคํŠธ๋Š” A/B ํ…Œ์ŠคํŠธ ๋ถ„์„, ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋“ฑ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ๊ตฌ๋งค๋ผ๋Š” ํ–‰๋™์„ ํ–ˆ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ์ด๋ฒคํŠธ ์ˆ˜์ง‘
hackleClient.track('purchase')

// ์ด๋ฒคํŠธ๋ฅผ ์†์„ฑ๊ณผ ํ•จ๊ป˜ ์ˆ˜์ง‘
const event = {
  key: "purchase",
  properties: {
    amount: 4200,
    pay_method: "CARD",
    is_discount: false,
    product_ids: [42, 43]
  }
}
hackleClient.track(event);

์ „์†กํ•œ ์ด๋ฒคํŠธ ํ™•์ธํ•˜๊ธฐ

๋Œ€์‹œ๋ณด๋“œ ์ด๋ฒคํŠธ๊ด€๋ฆฌ ๋ฉ”๋‰ด์—์„œ ์ „์†กํ•œ ์ด๋ฒคํŠธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ ์ „์†ก ํ›„ ๋Œ€์‹œ๋ณด๋“œ์— ํ‘œ์‹œ๋˜๊ธฐ๊นŒ์ง€ ์ผ๋ฐ˜์ ์œผ๋กœ ~60์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.


5. A/B ํ…Œ์ŠคํŠธ

์‚ฌ์šฉ์ž๋ฅผ ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์œผ๋กœ ๋ถ„๋ฐฐํ•˜๊ณ  ๋ถ„๋ฐฐ๋œ ๊ฒฐ๊ณผ์— ํ•ด๋‹นํ•˜๋Š” ๋กœ์ง์„ ์ž‘์„ฑํ•˜์—ฌ A/B ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
ํ•ตํด์ด ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ Hooks API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ํŠน์ • ๊ทธ๋ฃน์œผ๋กœ ๋ถ„๋ฐฐํ•˜๊ณ  ๋ถ„๋ฐฐ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„๋ฐฐ ์‹œ์—๋Š” ์‹คํ—˜ ํ‚ค๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‹คํ—˜ํ‚ค: ๊ฐ A/B ํ…Œ์ŠคํŠธ๋ณ„๋กœ ๊ฐ–๊ฒŒ ๋˜๋Š” ๊ณ ์œ  ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค. A/B ํ…Œ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋ฐœ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

import {HackleExperiment, HackleVariation} from "@hackler/react-sdk";

function App() {
  return (
    // ์‹คํ—˜ ํ‚ค๊ฐ€ 42์ธ A/B ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•  ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
    // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน A๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    <HackleExperiment experimentKey={42}> 
      <HackleVariation variation={"A"}>
        <AwesomeFeature />
      </HackleVariation>
      <HackleVariation variation={"B"}>
        <SuperAwesomeFeature />
      </HackleVariation>
    </HackleExperiment>
  )
}
import {useLoadableVariation, useVariation} from "@hackler/react-sdk";

// ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ
function App() {
  // ์‹คํ—˜ ํ‚ค๊ฐ€ 42์ธ A/B ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•  ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน A๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  const variation = useVariation(42)
  
  // ํ• ๋‹น๋ฐ›์€ ๊ทธ๋ฃน์— ๋Œ€ํ•œ ๋กœ์ง
  if (variation === "A") return <AwesomeFeature />
  if (variation === "B") return <SuperAwesomeFeature />
  return <AwesomeFeature />
}

// SSR ์‚ฌ์šฉ ์‹œ
function App() {
  // ์‹คํ—˜ ํ‚ค๊ฐ€ 42์ธ A/B ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•  ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน A๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  const { isLoading, variation } = useLoadableVariation(42)

  // SDK Loading ์ „ ์ปดํฌ๋„ŒํŠธ ๋น„๋…ธ์ถœ
  if (isLoading) return null

  // ํ• ๋‹น๋ฐ›์€ ๊ทธ๋ฃน์— ๋Œ€ํ•œ ๋กœ์ง
  if (variation === "A") return <AwesomeFeature />
  if (variation === "B") return <SuperAwesomeFeature />
  return <AwesomeFeature />
}

๋ถ„๋ฐฐ ๊ฒฐ๊ณผ ํ™•์ธํ•˜๊ธฐ

๋Œ€์‹œ๋ณด๋“œ A/B ํ…Œ์ŠคํŠธ์˜ ์ƒ์„ธํŽ˜์ด์ง€์˜ ์‹ค์‹œ๊ฐ„ ๋…ธ์ถœ ํ˜„ํ™ฉ ํƒญ์—์„œ ๋ถ„๋ฐฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถ„๋ฐฐ ํ›„ ๋Œ€์‹œ๋ณด๋“œ์— ํ‘œ์‹œ๋˜๊ธฐ๊นŒ์ง€ ์ผ๋ฐ˜์ ์œผ๋กœ ~60์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.


6. ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ

๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ๋Š” ์ผœ์ง(on) ์ƒํƒœ์™€ ๊บผ์ง(off) ์ƒํƒœ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋กœ์ง์„ ์ž‘์„ฑํ•˜์—ฌ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
ํ•ตํด์ด ์ œ๊ณตํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ, Hooks API์— ๊ธฐ๋Šฅํ”Œ๋ž˜๊ทธ ํ‚ค๋ฅผ ์ „๋‹ฌํ•˜์—ฌ on/off ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๊ธฐ๋Šฅํ”Œ๋ž˜๊ทธํ‚ค: ๊ฐ ๊ธฐ๋Šฅํ”Œ๋ž˜๊ทธ๋ณ„๋กœ ๊ฐ–๊ฒŒ ๋˜๋Š” ๊ณ ์œ  ๋ฒˆํ˜ธ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋Šฅํ”Œ๋ž˜๊ทธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋ฐœ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

import {HackleFeature} from "@hackler/react-sdk";

function App() {
  return (
    // ๊ธฐ๋Šฅ ํ‚ค๊ฐ€ 42์ธ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ์—์„œ ์‚ฌ์šฉ์ž์˜ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
    // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ false(๊บผ์ง ์ƒํƒœ)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    <HackleFeature featureKey={42}>
      {(featureOn) =>
        featureOn ? (
          <SuperAwesomeFeature /> // ์ผœ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
        ) : (
          <AwesomeFeature /> // ๊บผ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
        )
      }
    </HackleFeature>
  )
}
import {useFeature, useLoadableFeature} from "@hackler/react-sdk";

function App() {
  // ๊ธฐ๋Šฅ ํ‚ค๊ฐ€ 42์ธ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ์—์„œ ์‚ฌ์šฉ์ž์˜ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ false(๊บผ์ง ์ƒํƒœ)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  const featureOn = useFeature(42)
  return (
    <>
    {
      featureOn ? (
        <SuperAwesomeFeature /> // ์ผœ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
      ) : (
        <AwesomeFeature /> // ๊บผ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
      )
    }
    </>
  )
}

// SSR ์‚ฌ์šฉ ์‹œ
function App() {
  // ๊ธฐ๋Šฅ ํ‚ค๊ฐ€ 42์ธ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ์—์„œ ์‚ฌ์šฉ์ž์˜ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  // ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒฝ์šฐ false(๊บผ์ง ์ƒํƒœ)๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  const { isLoading, isOn } = useLoadableFeature(42)
  return (
    <>
    {
      isOn ? (
        <SuperAwesomeFeature /> // ์ผœ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
      ) : (
        <AwesomeFeature /> // ๊บผ์ง ์ƒํƒœ์ผ ๋•Œ์˜ ๊ธฐ๋Šฅ
      )
    }
    </>
  )
}