SDK ์—ฐ๋™

๐Ÿ“˜

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


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

Hackle iOS SDK๋Š” Swift Package Manager์™€ CocoaPods๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

// ...
dependencies: [
    .package(url: "https://github.com/hackle-io/hackle-ios-sdk.git", from: "2.58.0")
],
targets: [
    .target(
        name: "YOUR_TARGET",
        dependencies: ["Hackle"]
    )
],
// ...
pod 'Hackle', '2.58.0'

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

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

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

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY)
@import Hackle;

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:[HackleConfig DEFAULT]];

์ดˆ๊ธฐํ™” ์™„๋ฃŒ

์ดˆ๊ธฐํ™”๊ฐ€ ์‹œ์ž‘๋˜๋ฉด ํ•ตํด ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ํ•„์š”ํ•œ ์ •๋ณด๋“ค์„ ๊ฐ€์ ธ์™€์„œ SDK์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰๋˜๋ฉฐ, ์ดˆ๊ธฐํ™”์‹œ ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฝœ๋ฐฑ์„ ์ „๋‹ฌํ•˜๋ฉด SDK ์‚ฌ์šฉ ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™”๊ฐ€ ์™„๋ฃŒ ๋˜๊ธฐ ์ „์— A/B ํ…Œ์ŠคํŠธ, ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ธฐ๋ณธ ๊ทธ๋ฃน(A), ๊บผ์ง(false)์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY) {
    // SDK ready to use.
}
[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:[HackleConfig DEFAULT] completion:^{
    // SDK ready to use.
}];

๊ถŒ์žฅ ์ดˆ๊ธฐํ™” ์ „๋žต: ๋กœ๋”ฉ ํ™”๋ฉด์„ ํ†ตํ•œ ์ดˆ๊ธฐํ™”

์•ฑ์„ ์ฆ‰์‹œ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ณ  ๋กœ๋”ฉ ํ™”๋ฉด์„ ํ‘œ์‹œํ•˜๊ณ  SDK๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ ์ฝœ๋ฐฑ์„ ํ†ตํ•ด ๋กœ๋”ฉ ํ™”๋ฉด์„ ๋‹ซ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ๊ณผ ์ƒํ˜ธ์ž‘์šฉ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ด ์ „๋žต์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋กœ๋”ฉ ํ™”๋ฉด์— ์ œํ•œ ์‹œ๊ฐ„์„ ๋‘๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค ๊ฐ€์ ธ์˜ค๊ธฐ

์ดˆ๊ธฐํ™” ์ดํ›„ ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด HackleApp ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™” ์ด์ „์— ํ˜ธ์ถœํ•˜๋ฉด nil์„ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™” ์ดํ›„ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

let hackleApp = Hackle.app()
HackleApp *hackleApp = [Hackle app];

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

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

let config = HackleConfigBuilder()
  .build()

Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY, config: config) {
    // SDK ready to use.
}
HackleConfigBuilder *builder = [[HackleConfigBuilder alloc] init];
[builder exposureEventDedupIntervalSeconds:1];
HackleConfig *config = [builder build];

[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY" config:config completion:^{
    // SDK ready to use.
}];

์„ค์ • ์˜ต์…˜

์„ค์ •

๊ธฐ๋Šฅ

๊ธฐ๋ณธ๊ฐ’

์ง€์› ๋ฒ„์ „

exposureEventDedupIntervalSeconds

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

์ตœ์†Ÿ๊ฐ’: 1 ์ตœ๋Œ“๊ฐ’:

  • ~2.40.1 : 3600 (1์‹œ๊ฐ„)
  • 2.41.0~ : 86400(24์‹œ๊ฐ„)

60 (1๋ถ„)

2.7.0+ (2.41.0 ์ดํ›„๋ถ€ํ„ฐ ์•ฑ ์ข…๋ฃŒ ํ›„ ์žฌ์‹œ์ž‘ ์‹œ์—๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.)

eventFlushInterval

์ˆ˜์ง‘๋œ ์ด๋ฒคํŠธ๋ฅผ ์„œ๋ฒ„๋กœ ์ „์†กํ•˜๋Š” ์ฃผ๊ธฐ์ž…๋‹ˆ๋‹ค.

์ตœ์†Ÿ๊ฐ’: 1 ์ตœ๋Œ“๊ฐ’: 60 (1๋ถ„)

10

2.10.0+

sessionTimeoutIntervalSeconds

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

1800 (30๋ถ„)

2.13.0+

pollingIntervalSeconds

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

์ตœ์†Ÿ๊ฐ’ : 60 (1๋ถ„)

-1 (์ฃผ๊ธฐ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์Œ)

2.18.0+

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

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

hackleApp.fetch { 
  // done
}
[hackleApp fetch:^{
    // done
}];
๐Ÿšง

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


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

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

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

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

  • ๋กœ๊ทธ์ธ ์‹œ ํ•œ๋ฒˆ๋งŒ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • ์ด๋ฏธ ๋กœ๊ทธ์ธ์ด ๋˜์–ด์žˆ๋Š” ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ์—๋Š” ๋กœ๊ทธ์ธํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๋Š” ์‹œ์ ์— ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
let userId: String = ... // ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ID (ํšŒ์›๋ฒˆํ˜ธ, ๋ฉค๋ฒ„ ID ๋“ฑ)
hackleApp.setUserId(userId: userId)
NSString *userId = ... // ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ID (ํšŒ์›๋ฒˆํ˜ธ, ๋ฉค๋ฒ„ ID ๋“ฑ)
[hackleApp setUserIdWithUserId:userId];

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

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

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

hackleApp.updateUserProperties(operations: operations)
PropertyOperationsBuilder *builder = [HacklePropertyOperations builder];
[builder set:@"age" :@42];
[builder set:@"grade" :@"GOLD"];
HacklePropertyOperations *operations = [builder build];

[hackleApp updateUserPropertiesWithOperations:operations];

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

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

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

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

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

import Hackle

// ์ด๋ฒคํŠธ ์ „์†ก
hackleApp.track(eventKey: "purcahse")

// ์ด๋ฒคํŠธ๋ฅผ ์†์„ฑ๊ณผ ํ•จ๊ป˜ ์ „์†ก
let event = Event.builder("purchase")
    .property("amount", 4200)
    .property("pay_method", "CARD")
    .property("is_discount", false)
    .build()

hackleApp.track(event: event)
@import Hackle;

// ์ด๋ฒคํŠธ ์ „์†ก
[hackleApp trackWithEventKey:@"purchase"];

// ์ด๋ฒคํŠธ๋ฅผ ์†์„ฑ๊ณผ ํ•จ๊ป˜ ์ „์†ก
HackleEventBuilder *builder = [HackleEvent builder:@"purchase"];
[builder property:@"amount" :@4200];
[builder property:@"pay_method" :@"CARD"];
[builder property:@"is_discount" :@false];
HackleEvent *event = [builder build];

[hackleApp trackWithEvent:event];

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

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


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

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

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

// ์‹คํ—˜ ํ‚ค๊ฐ€ 42์ธ A/B ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•  ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
let variation = hackleApp.variation(experimentKey: 42)

// ํ• ๋‹น๋ฐ›์€ ๊ทธ๋ฃน์— ๋Œ€ํ•œ ๋กœ์ง
if variation == "A" {
  // ๊ทธ๋ฃน A ๋กœ์ง
} else if variation == "B" {
  // ๊ทธ๋ฃน B ๋กœ์ง
}
// ์‹คํ—˜ ํ‚ค๊ฐ€ 42์ธ A/B ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋…ธ์ถœํ•  ํ…Œ์ŠคํŠธ ๊ทธ๋ฃน์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
NSString *variation = [hackleApp variationWithExperimentKey:42 defaultVariation:@"A"];

// ํ• ๋‹น๋ฐ›์€ ๊ทธ๋ฃน์— ๋Œ€ํ•œ ๋กœ์ง
if([variation isEqual:@"A"]) {
    // ๊ทธ๋ฃน A ๋กœ์ง
} else if ([variation isEqual:@"B"]) {
    // ๊ทธ๋ฃน B ๋กœ์ง
}

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

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


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

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

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

// ๊ธฐ๋Šฅ ํ‚ค๊ฐ€ 42์ธ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ์—์„œ ์‚ฌ์šฉ์ž์˜ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
let isFeatureOn: Bool = hackleApp.isFeatureOn(featureKey: 42)

if isFeatureOn {
    // ON ๊ธฐ๋Šฅ
} else {
    // OFF ๊ธฐ๋Šฅ
}
// ๊ธฐ๋Šฅ ํ‚ค๊ฐ€ 42์ธ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ์—์„œ ์‚ฌ์šฉ์ž์˜ ์ƒํƒœ๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
bool isFeatureOn = [hackleApp isFeatureOnFeatureKey:@42];

if (isFeatureOn) {
    // ON ๊ธฐ๋Šฅ      
} else {
    // OFF ๊ธฐ๋Šฅ
}