> ## Documentation Index
> Fetch the complete documentation index at: https://help.airbridge.io/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK 마이그레이션 가이드 - iOS SDK

에어브릿지 iOS SDK를 업데이트하는 과정에 필요한 내용을 확인할 수 있습니다. 현재 버전 이후부터 업데이트 이후 버전까지의 내용을 모두 확인하는 것을 권장합니다.

## v1.x에서 v4.0으로 업데이트

에어브릿지 iOS SDK를 v4.0으로 업데이트하면 확인해 주세요.

iOS SDK 이름이 AirBridge에서 Airbridge로 변경되었습니다. AirBridge 클래스가 Airbridge 클래스로 변경되었습니다. 함수와 옵션의 이름이 변경되었습니다.

<Accordion title="전체 변경사항">
  #### 옵션

  | AirBridge                                                  | AirbridgeOptionBuilder                                       | 변경점                                                          |
  | ---------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
  | -                                                          | AirbridgeOptionBuilder(name: String, token: String)          | 옵션을 Builder를 통해 설정하실 수 있도록 변경되었습니다.                          |
  | -                                                          | build()                                                      | SDK 초기화 이후 옵션을 수정하실 수 없도록 변경되었습니다.                           |
  | setLogLevel(ABLogLevel)                                    | setLogLevel(AirbridgeLogLevel)                               | 타입 이름이 변경되었습니다.                                              |
  | setPaginateLogEnabled(Bool)                                | setPaginateLogEnabled(Bool)                                  | -                                                            |
  | state().setSDKDevelopmentPlatform(String)                  | setSDKDevelopmentPlatform(String)                            | 이름이 변경되었습니다.                                                 |
  | -                                                          | setAppGroup(String)                                          | 새로운 기능이 추가되었습니다.                                             |
  | setSDKEnabled(Bool)                                        | setSDKEnabled(Bool)                                          | -                                                            |
  | -                                                          | setTrackingLinkCustomDomains(\[String])                      | Info.plist를 통해 설정하던 것이 옵션으로 변경되었습니다.                         |
  | setIsFacebookDeferredAppLinkEnabled(Bool)                  | setTrackMetaDeferredAppLinkEnabled(Bool)                     | 이름이 변경되었습니다.                                                 |
  | deeplink().setDeeplinkCallback((String) -> Void)           | -                                                            | handleDeeplink 함수로 역할이 이전되었습니다.                              |
  | deeplink().setDeferredDeeplinkCallback((String) -> Void)   | -                                                            | handleDeferredDeeplink 함수로 역할이 이전되었습니다.                      |
  | deeplink().setHandleTrackingLinkTimeout: UInt              | -                                                            | 기능이 제거되었습니다. (기본값인 3초로 고정됩니다.)                               |
  | setAutoStartTrackingEnabled(Bool)                          | setAutoStartTrackingEnabled(Bool)                            | -                                                            |
  | -                                                          | setAutoDetermineTrackingAuthorizationEnabled(Bool)           | 새로운 기능이 추가되었습니다.                                             |
  | setting().trackingAuthorizeTimeout: UInt                   | setAutoDetermineTrackingAuthorizationTimeout(second: Double) | 이름이 변경되었습니다. 그리고 단위가 밀리초에서 초로 변경되었습니다. 또 최대 1시간 제한이 추가되었습니다. |
  | setting().isRestartTrackingAuthorizeTimeout: Bool          | -                                                            | 기능이 제거되었습니다. (기본값인 true로 고정됩니다.)                             |
  | setIsUserInfoHashed(Bool)                                  | setHashUserInformationEnabled(Bool)                          | 이름이 변경되었습니다.                                                 |
  | setSessionTimeout(Int)                                     | setSessionTimeout(second: Double)                            | 단위가 밀리초에서 초로 변경되었습니다. 그리고 최대 7일 제한이 추가되었습니다.                 |
  | setIsTrackAirbridgeDeeplinkOnly(Bool)                      | setTrackAirbridgeDeeplinkOnlyEnabled(Bool)                   | 이름이 변경되었습니다.                                                 |
  | setSDKSignature(id: String, secret: String)                | setSDKSignature(id: String, secret: String)                  | -                                                            |
  | resetEventBufferEnabled(Bool)                              | setClearEventBufferOnInitializeEnabled(Bool)                 | 이름이 변경되었습니다.                                                 |
  | setting().isResetEventBufferEnabled: Bool                  | setClearEventBufferOnInitializeEnabled(Bool)                 | 이름이 변경되었습니다.                                                 |
  | -                                                          | setPauseEventTransmitOnBackgroundEnabled(Bool)               | 새로운 기능이 추가되었습니다.                                             |
  | setting().setEventMaximumBufferCount(UInt)                 | setEventBufferCountLimit(Int)                                | 이름이 변경되었습니다.                                                 |
  | setting().setEventMaximumBufferSize(UInt)                  | setEventBufferSizeLimit(gibibyte: Double)                    | 이름이 변경되었습니다. 그리고 단위가 byte에서 gibibyte로 변경되었습니다.               |
  | setting().setEventTransmitInterval(UInt)                   | setEventTransmitInterval(second: Double)                     | 이름이 변경되었습니다. 그리고 단위가 밀리초에서 초로 변경되었습니다. 또 최대 1일 제한이 추가되었습니다.  |
  | setting().attributionCallback: (\[String: String]) -> Void | setOnAttributionReceived((\[String: String]) -> Void)        | 이름이 변경되었습니다.                                                 |

  #### 함수

  | AirBridge                                                                | Airbridge                                                                                                  | 변경점                                                 |
  | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
  | getInstance(String, appName: String)                                     | initializeSDK(option: AirbridgeOption)                                                                     | 이름이 변경되었습니다.                                        |
  | isSDKEnabled: Bool                                                       | isSDKEnabled: Bool                                                                                         | -                                                   |
  | enableSDK()                                                              | enableSDK()                                                                                                | -                                                   |
  | disableSDK()                                                             | disableSDK()                                                                                               | SDK 구성요소에 접근을 제한하던 구현방식이 구성요소를 메모리에서 제거하도록 변경되었습니다. |
  | startTracking()                                                          | startTracking()                                                                                            | -                                                   |
  | deeplink().handleURLSchemeDeeplink(URL)                                  | trackDeeplink(url: URL)                                                                                    | 이름이 변경되었습니다.                                        |
  | deeplink().handleUserActivity(NSUserActivity)                            | trackDeeplink(userActivity: NSUserActivity)                                                                | 이름이 변경되었습니다.                                        |
  | -                                                                        | handleDeeplink(url: URL, onSuccess: (URL) -> Void, onFailure: (Error) -> Void) -> Bool                     | setDeeplinkCallback 옵션이 이동되었습니다.                    |
  | -                                                                        | handleDeeplink(userActivity: NSUserActivity, onSuccess: (URL) -> Void, onFailure: (Error) -> Void) -> Bool | setDeeplinkCallback 옵션이 이동되었습니다.                    |
  | -                                                                        | handleDeferredDeeplink(url: URL, onSuccess: (URL) -> Void, onFailure: (Error) -> Void) -> Bool             | setDeferredDeeplinkCallback 옵션이 이동되었습니다.            |
  | -                                                                        | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any])         | 이벤트 전송방식이 변경되었습니다.                                  |
  | placement().click(URL, completion: (Error?) -> Void)                     | click(trackingLink: URL, onSuccess: () -> Void, onFailure: (Error) -> Void) -> Bool                        | 이름이 변경되었습니다.                                        |
  | placement().impression(URL, completion: (Error?) -> Void)                | impression(trackingLink: URL, onSuccess: () -> Void, onFailure: (Error) -> Void) -> Bool                   | 이름이 변경되었습니다.                                        |
  | webInterface().inject(to: WKUserContentController, withWebToken: String) | setWebInterface(controller: WKUserContentController, webToken: String)                                     | 이름이 변경되었습니다. 그리고 DeviceAlias 연동기능이 추가되었습니다.         |
  | deviceUUID: String                                                       | fetchDeviceUUID(onSuccess: (String) -> Void, onFailure: (Error) -> Void) -> Bool                           | 이름이 변경되었습니다. 함수가 비동기적으로 동작하도록 수정되었습니다.              |
  | fetchAirbridgeGeneratedUUID((String) -> Void) -> Bool                    | fetchAirbridgeGeneratedUUID(onSuccess: (String) -> Void, onFailure: (Error) -> Void) -> Bool               | 이름이 변경되었습니다.                                        |
  | -                                                                        | isUninstallTrackingNotification(\[String: Any]) -> Bool                                                    | 새로운 기능이 추가되었습니다.                                    |
  | state().setUserID(String)                                                | setUserID(String)                                                                                          | 이름이 변경되었습니다.                                        |
  | -                                                                        | clearUserID()                                                                                              | 새로운 기능이 추가되었습니다.                                    |
  | state().setUserEmail(String)                                             | setUserEmail(String)                                                                                       | 이름이 변경되었습니다.                                        |
  | -                                                                        | clearUserEmail()                                                                                           | 새로운 기능이 추가되었습니다.                                    |
  | state().setUserPhone(String)                                             | setUserPhone(String)                                                                                       | 이름이 변경되었습니다.                                        |
  | -                                                                        | clearUserPhone()                                                                                           | 새로운 기능이 추가되었습니다.                                    |
  | addUserAttribute(key: String, value: Any)                                | setUserAttribute(key: String, value: Any)                                                                  | 이름이 변경되었습니다.                                        |
  | removeUserAttribute(String)                                              | removeUserAttribute(key: String)                                                                           | 이름이 변경되었습니다.                                        |
  | clearUserAttributes()                                                    | clearUserAttributes()                                                                                      | -                                                   |
  | addUserAlias(key: String, value: String)                                 | setUserAlias(key: String, value: String)                                                                   | 이름이 변경되었습니다.                                        |
  | removeUserAlias(String)                                                  | removeUserAlias(key: String)                                                                               | 이름이 변경되었습니다.                                        |
  | clearUserAlias()                                                         | clearUserAlias()                                                                                           | -                                                   |
  | -                                                                        | clearUser()                                                                                                | 새로운 기능이 추가되었습니다.                                    |
  | addDeviceAlias(key: String, value: String)                               | setDeviceAlias(key: String, value: String)                                                                 | 이름이 변경되었습니다.                                        |
  | setDeviceAlias(key: String, value: String)                               | setDeviceAlias(key: String, value: String)                                                                 | -                                                   |
  | removeDeviceAlias(key: String)                                           | removeDeviceAlias(key: String)                                                                             | -                                                   |
  | clearDeviceAlias()                                                       | clearDeviceAlias()                                                                                         | -                                                   |
  | registerPushToken(Data)                                                  | registerPushToken(Data)                                                                                    | -                                                   |

  #### 클래스

  | ABInAppEvent                 | Airbridge                                                                                          | 변경점                                                                                                                                                                                                     |
  | ---------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | setCategory(String)          | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | AirbridgeCategory 또는 String을 category 파라미터에 입력해주세요.                                                                                                                                                     |
  | setAction(String)            | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | AirbridgeAttribute.ACTION를 키로 사용해서 semanticAttributes 파라미터에 입력해주세요.                                                                                                                                     |
  | setLabel(String)             | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | AirbridgeAttribute.LABEL를 키로 사용해서 semanticAttributes 파라미터에 입력해주세요.                                                                                                                                      |
  | setValue(NSNumber)           | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | AirbridgeAttribute.VALUE를 키로 사용해서 semanticAttributes 파라미터에 입력해주세요.                                                                                                                                      |
  | setSemantics(\[String: Any]) | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | ABSemanticsKey를 사용한 키는 AirbridgeAttribute를 사용하고 String을 사용한 키는 그대로 semanticAttributes 파라미터에 입력해주세요.<br />그리고 products의 value에는 ABProductKey를 사용한 키는 AirbridgeAttribute를 사용하고 String을 사용한 키는 그대로 입력해주세요. |
  | setCustoms(\[String: Any])   | trackEvent(category: String, semanticAttributes: \[String: Any], customAttributes: \[String: Any]) | 키, 밸류를 그대로 customAttributes에 입력해주세요.                                                                                                                                                                    |

  #### 상수

  | ABCategory        | AirbridgeCategory       | 변경점              |
  | ----------------- | ----------------------- | ---------------- |
  | signUp            | SIGN\_UP                | 이름이 변경되었습니다.     |
  | signIn            | SIGN\_IN                | 이름이 변경되었습니다.     |
  | signOut           | SIGN\_OUT               | 이름이 변경되었습니다.     |
  | viewHome          | HOME\_VIEWED            | 이름이 변경되었습니다.     |
  | viewProductList   | PRODUCT\_LIST\_VIEWED   | 이름이 변경되었습니다.     |
  | viewSearchResult  | SEARCH\_RESULTS\_VIEWED | 이름이 변경되었습니다.     |
  | viewProductDetail | PRODUCT\_VIEWED         | 이름이 변경되었습니다.     |
  | -                 | ADD\_PAYMENT\_INFO      | 새로운 기능이 추가되었습니다. |
  | -                 | ADD\_TO\_WISHLIST       | 새로운 기능이 추가되었습니다. |
  | addToCart         | ADDED\_TO\_CART         | 이름이 변경되었습니다.     |
  | -                 | INITIATE\_CHECKOUT      | 새로운 기능이 추가되었습니다. |
  | purchase          | ORDER\_COMPLETED        | 이름이 변경되었습니다.     |
  | -                 | ORDER\_CANCELED         | 새로운 기능이 추가되었습니다. |
  | -                 | START\_TRIAL            | 새로운 기능이 추가되었습니다. |
  | -                 | SUBSCRIBE               | 새로운 기능이 추가되었습니다. |
  | -                 | UNSUBSCRIBE             | 새로운 기능이 추가되었습니다. |
  | -                 | AD\_IMPRESSION          | 새로운 기능이 추가되었습니다. |
  | -                 | AD\_CLICK               | 새로운 기능이 추가되었습니다. |
  | -                 | COMPLETE\_TUTORIAL      | 새로운 기능이 추가되었습니다. |
  | -                 | ACHIEVE\_LEVEL          | 새로운 기능이 추가되었습니다. |
  | -                 | UNLOCK\_ACHIEVEMENT     | 새로운 기능이 추가되었습니다. |
  | -                 | RATE                    | 새로운 기능이 추가되었습니다. |
  | -                 | SHARE                   | 새로운 기능이 추가되었습니다. |
  | -                 | SCHEDULE                | 새로운 기능이 추가되었습니다. |
  | -                 | SPEND\_CREDITS          | 새로운 기능이 추가되었습니다. |

  | ABSemanticsKey | AirbridgeAttribute                    | 변경점                         |
  | -------------- | ------------------------------------- | --------------------------- |
  | -              | ACTION                                | 새로운 기능이 추가되었습니다.            |
  | -              | LABEL                                 | 새로운 기능이 추가되었습니다.            |
  | -              | VALUE                                 | 새로운 기능이 추가되었습니다.            |
  | totalValue     | -                                     | 기능이 제거되었습니다. VALUE에 입력해주세요. |
  | currency       | CURRENCY                              | 이름이 변경되었습니다.                |
  | -              | ORIGINAL\_CURRENCY                    | 새로운 기능이 추가되었습니다.            |
  | products       | PRODUCTS                              | 이름이 변경되었습니다.                |
  | -              | PERIOD                                | 새로운 기능이 추가되었습니다.            |
  | -              | IS\_RENEWAL                           | 새로운 기능이 추가되었습니다.            |
  | -              | RENEWAL\_COUNT                        | 새로운 기능이 추가되었습니다.            |
  | productListID  | PRODUCT\_LIST\_ID                     | 이름이 변경되었습니다.                |
  | cartID         | CART\_ID                              | 이름이 변경되었습니다.                |
  | transactionID  | TRANSACTION\_ID                       | 이름이 변경되었습니다.                |
  | -              | TRANSACTION\_TYPE                     | 새로운 기능이 추가되었습니다.            |
  | -              | TRANSACTION\_PAIRED\_EVENT\_CATEGORY  | 새로운 기능이 추가되었습니다.            |
  | -              | TRANSACTION\_PAIRED\_EVENT\_TIMESTAMP | 새로운 기능이 추가되었습니다.            |
  | totalQuantity  | TOTAL\_QUANTITY                       | 이름이 변경되었습니다.                |
  | query          | QUERY                                 | 이름이 변경되었습니다.                |
  | inAppPurchased | IN\_APP\_PURCHASED                    | 이름이 변경되었습니다.                |
  | -              | CONTRIBUTION\_MARGIN                  | 새로운 기능이 추가되었습니다.            |
  | -              | ORIGINAL\_CONTRIBUTION\_MARGIN        | 새로운 기능이 추가되었습니다.            |
  | -              | LIST\_ID                              | 새로운 기능이 추가되었습니다.            |
  | -              | RATE\_ID                              | 새로운 기능이 추가되었습니다.            |
  | -              | RATE                                  | 새로운 기능이 추가되었습니다.            |
  | -              | MAX\_RATE                             | 새로운 기능이 추가되었습니다.            |
  | -              | ACHIEVEMENT\_ID                       | 새로운 기능이 추가되었습니다.            |
  | -              | SHARED\_CHANNEL                       | 새로운 기능이 추가되었습니다.            |
  | -              | DATE\_TIME                            | 새로운 기능이 추가되었습니다.            |
  | -              | DESCRIPTION                           | 새로운 기능이 추가되었습니다.            |
  | -              | IS\_REVENUE                           | 새로운 기능이 추가되었습니다.            |
  | -              | PLACE                                 | 새로운 기능이 추가되었습니다.            |
  | -              | SCHEDULE\_ID                          | 새로운 기능이 추가되었습니다.            |
  | -              | TYPE                                  | 새로운 기능이 추가되었습니다.            |
  | -              | LEVEL                                 | 새로운 기능이 추가되었습니다.            |
  | -              | SCORE                                 | 새로운 기능이 추가되었습니다.            |
  | -              | AD\_PARTNERS                          | 새로운 기능이 추가되었습니다.            |
  | -              | IS\_FIRST\_PER\_USER                  | 새로운 기능이 추가되었습니다.            |

  | ABProductKey | AirbridgeAttribute      | 변경점              |
  | ------------ | ----------------------- | ---------------- |
  | productID    | PRODUCT\_ID             | 이름이 변경되었습니다.     |
  | name         | PRODUCT\_NAME           | 이름이 변경되었습니다.     |
  | price        | PRODUCT\_PRICE          | 이름이 변경되었습니다.     |
  | quantity     | PRODUCT\_QUANTITY       | 이름이 변경되었습니다.     |
  | currency     | PRODUCT\_CURRENCY       | 이름이 변경되었습니다.     |
  | position     | PRODUCT\_POSITION       | 이름이 변경되었습니다.     |
  | -            | PRODUCT\_CATEGORY\_ID   | 새로운 기능이 추가되었습니다. |
  | -            | PRODUCT\_CATEGORY\_NAME | 새로운 기능이 추가되었습니다. |
  | -            | PRODUCT\_BRAND\_ID      | 새로운 기능이 추가되었습니다. |
  | -            | PRODUCT\_BRAND\_NAME    | 새로운 기능이 추가되었습니다. |
</Accordion>

### SDK 설치 및 초기화

CocoaPods 패키지명, SwiftPackageManager Git 주소, 직접 설치 다운로드 URL 등이 변경되었습니다. 기존 iOS SDK를 삭제한 후에 [에어브릿지 가이드](/ko/developers/ios-sdk-v4#ios-sdk-설치하기)에 따라 다시 설치해 주세요.

SDK 초기화에 사용하는 `AirBridge.getInstance` 함수가 `Airbridge.initializeSDK` 함수로 변경되었습니다. 또한 옵션 설정 함수가 `AirbridgeOption`, `AirbridgeOptionBuilder` 클래스들로 변경되었습니다. SDK의 옵션은 더는 런타임에 변경되지 않습니다.

아래 맵핑을 참고해 새로운 SDK 초기화 코드를 작성해 주세요.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  import Airbridge
  ...
  let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
      .setLogLevel(.warning)
      .setSessionTimeout(second: 300)
      .build()
  Airbridge.initializeSDK(option: option)
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  #import <Airbridge/Airbridge.h>
  ...
  AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                 token:@"YOUR_APP_SDK_TOKEN"];
  [optionBuilder setLogLevel:AirbridgeLogLevelWarning];
  [optionBuilder setSessionTimeoutWithSecond:300];
  AirbridgeOption* option = [optionBuilder build];
  [Airbridge initializeSDKWithOption:option];
  ```
</CodeGroup>

<AccordionGroup>
  <Accordion title="AirbridgeOptionBuilder 맵핑">
    | AirBridge                                                  | Default              | AirbridgeOptionBuilder                                       | Default                           |
    | ---------------------------------------------------------- | -------------------- | ------------------------------------------------------------ | --------------------------------- |
    | setLogLevel(ABLogLevel)                                    | LOG\_WARNING         | setLogLevel(AirbridgeLogLevel)                               | .warning                          |
    | setSDKEnabled(Bool)                                        | true                 | setSDKEnabled(Bool)                                          | true                              |
    | setIsFacebookDeferredAppLinkEnabled(Bool)                  | false                | setTrackMetaDeferredAppLinkEnabled(Bool)                     | false                             |
    | setAutoStartTrackingEnabled(Bool)                          | true                 | setAutoStartTrackingEnabled(Bool)                            | true                              |
    | setting().trackingAuthorizeTimeout // UInt                 | 30000 (millisecond)  | setAutoDetermineTrackingAuthorizationTimeout(second: Double) | 300.0 (second) (0 \~ 1 hour)      |
    | setting().isRestartTrackingAuthorizeTimeout // Bool        | true                 | 기능이 제거되었습니다.                                                 | -                                 |
    | deeplink().setDeeplinkCallback((String) -> Void)           | -                    | 다른 기능으로 대체되었습니다. 딥링크 항목을 참고해주세요.                             | -                                 |
    | deeplink().setDeferredDeeplinkCallback((String) -> Void)   | -                    | 다른 기능으로 대체되었습니다. 딥링크 항목을 참고해주세요.                             | -                                 |
    | deeplink().setHandleTrackingLinkTimeout(UInt)              | 3000 (millisecond)   | 기능이 제거되었습니다. (3초 고정)                                         | -                                 |
    | setIsUserInfoHashed(Bool)                                  | true                 | setHashUserInformationEnabled(Bool)                          | true                              |
    | setSessionTimeout(Int)                                     | 300000 (millisecond) | setSessionTimeout(second: Double)                            | 300.0 (second) (0 \~ 7 day)       |
    | setIsTrackAirbridgeDeeplinkOnly(Bool)                      | false                | setTrackAirbridgeDeeplinkOnlyEnabled(Bool)                   | false                             |
    | setSDKSignatureSecret(id: String, secret: String)          | -                    | setSDKSignature(id: String, secret: String)                  | -                                 |
    | setResetEventBufferEnabled(Bool)                           | false                | setClearEventBufferOnInitializeEnabled(Bool)                 | false                             |
    | setting().isResetEventBufferEnabled // Bool                | false                | setClearEventBufferOnInitializeEnabled(Bool)                 | false                             |
    | setting().setEventMaximumBufferCount(UInt)                 | INT\_MAX             | setEventBufferCountLimit(Int)                                | INT\_MAX                          |
    | setting().setEventMaximumBufferCount(UInt)                 | INT\_MAX (byte)      | setEventBufferSizeLimit(gibibyte: Double)                    | 1024 (gibibyte) (0 \~ 1 tebibyte) |
    | setting().setEventTransmitInterval(UInt)                   | 0 (millisecond)      | setEventTransmitInterval(second: Double)                     | 0 (second) (0 \~ 1 day)           |
    | setting().attributionCallback((\[String: String]) -> Void) | -                    | setOnAttributionReceived((\[String: String]) -> Void)        | -                                 |
  </Accordion>

  <Accordion title="예시) AirbridgeOptionBuilder">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import Airbridge
      ...
      let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
          .setLogLevel(.warning)
          .setSessionTimeout(second: 300)
          .build()
      Airbridge.initializeSDK(option: option)
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import <Airbridge/Airbridge.h>
      ...
      AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                     token:@"YOUR_APP_SDK_TOKEN"];
      [optionBuilder setLogLevel:AirbridgeLogLevelWarning];
      [optionBuilder setSessionTimeoutWithSecond:300];
      AirbridgeOption* option = [optionBuilder build];
      [Airbridge initializeSDKWithOption:option];
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

### 딥링크

`AirBridge.setDeeplinkCallback` 함수가 `Airbridge.handleDeeplink` 함수와 `handleDeferredDeeplink` 함수로 대체되었습니다.

<Accordion title="필요한 작업 - 딥링크 콜백 설정">
  기존 `AirBridge.setDeeplinkCallback` 함수를 에어브릿지 대시보드에 등록한 스킴딥링크를 처리하는 함수와 다른 딥링크를 처리하는 함수로 분리해 구현해야 합니다. 아래 DeeplinkHandler 클래스를 참고해 주세요.

  <CodeGroup>
    ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import Foundation

    final class DeeplinkHandler {
        private init() {}

        static func handleSchemeDeeplink(url: URL) -> Bool {
            if url.scheme != "YOUR_SCHEME" {
                return false
            }

            // REQUIRE: show content

            return true
        }

        static func handleOtherDeeplink(url: URL) -> Bool {
            // OPTION: show content

            return true
        }
    }
    ```

    ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    #import <Foundation/Foundation.h>

    @implementation ABDeeplinkHandler

    - (instancetype) init __unavailable;

    + (BOOL)handleSchemeDeeplink:(NSURL *)url;
    + (BOOL)handleOtherDeeplink:(NSURL *)url;

    @end
    ...
    #import "ABDeeplinkHandler.h"

    @interface ABDeeplinkHandler : NSObject

    + (BOOL)handleSchemeDeeplink:(NSURL *)url {
        if (![url.scheme isEqualToString:@"YOUR_SCHEME"]) {
            return NO;
        }

        // REQUIRE: show content

        return YES;
    }

    + (BOOL)handleOtherDeeplink:(NSURL *)url {
        // OPTION: show content

        return YES;
    }

    @end
    ```
  </CodeGroup>
</Accordion>

`AirBridge.deeplink().handle` (또는 `handleUniversalLink`)와 `AirBridge.deeplink().handleURLSchemeDeeplink`는 `Airbridge.trackDeeplink`로 대체되었습니다.

<AccordionGroup>
  <Accordion title="필요한 작업 - 딥링크 처리">
    1. 시스템 방식에 따라 `AirBridge.deeplink().handle` (또는 `handleUniversalLink`)와 `AirBridge.deeplink().handleURLSchemeDeeplink` 함수를 호출하는 부분을 삭제합니다.

    2. `Airbridge.trackDeeplink` 함수와 `Airbridge.handleDeeplink` 함수를 호출합니다.

    `Airbridge.handleDeeplink` 함수는 에어브릿지 딥링크가 입력되면 true와 함께 스킴 딥링크를 콜백으로 제공합니다. 에어브릿지 딥링크가 아니면 false와 함께 콜백을 제공하지 않습니다.

    3. `onSuccess` 콜백에서 에어브릿지로 실행된 스킴 딥링크를 처리하는 함수를 호출합니다.

    <CodeGroup>
      ```swift SceneDelegate (Swift) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import UIKit
      import Airbridge

      class SceneDelegate: UIResponder, UIWindowSceneDelegate {
          var window: UIWindow?

          // when terminated app is opened with scheme deeplink or universal links
          func scene(
              _ scene: UIScene,
              willConnectTo session: UISceneSession,
              options connectionOptions: UIScene.ConnectionOptions
          ) {
              // when app is opened with scheme deeplink
              if let url = connectionOptions.urlContexts.first?.url {
                  // track deeplink
                  Airbridge.trackDeeplink(url: url)

                  // handle airbridge deeplink
                  var isHandled = Airbridge.handleDeeplink(url: url) { url in
                      DeeplinkHandler.handleSchemeDeeplink(url: url)
                  }
                  if isHandled { return }

                  // handle scheme deeplink
                  isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
                  if isHandled { return }

                  // handle other deeplink
                  isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
              }
              // when app is opened with universal links
              else if let userActivity = connectionOptions.userActivities.first {
                  // track deeplink
                  Airbridge.trackDeeplink(userActivity: userActivity)

                  // handle airbridge deeplink
                  var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                      DeeplinkHandler.handleSchemeDeeplink(url: url)
                  }
                  if isHandled { return }

                  // handle other deeplink
                  if let url = userActivity.webpageURL {
                      isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
                  }
              }
          }

          // when backgrounded app is opened with scheme deeplink
          func scene(
              _ scene: UIScene,
              openURLContexts URLContexts: Set<UIOpenURLContext>
          ) {
              guard let url = URLContexts.first?.url else { return }

              // track deeplink
              Airbridge.trackDeeplink(url: url)

              // handle airbridge deeplink
              var isHandled = Airbridge.handleDeeplink(url: url) { url in
                  DeeplinkHandler.handleSchemeDeeplink(url: url)
              }
              if isHandled { return }

              // handle scheme deeplink
              isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
              if isHandled { return }

              // handle other deeplink
              isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
          }

          // when backgrounded app is opened with universal links
          func scene(
              _ scene: UIScene,
              continue userActivity: NSUserActivity
          ) {
              // track deeplink
              Airbridge.trackDeeplink(userActivity: userActivity)

              // handle airbridge deeplink
              var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                  DeeplinkHandler.handleSchemeDeeplink(url: url)
              }
              if isHandled { return }

              // handle other deeplink
              if let url = userActivity.webpageURL {
                  isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
              }
          }
      }
      ```

      ```swift AppDelegate (Swift) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import UIKit
      import Airbridge

      @main
      class AppDelegate: UIResponder, UIApplicationDelegate {   
          var window: UIWindow?

          // when app is opened with scheme deeplink
          func application(
              _ app: UIApplication,
              open url: URL,
              options: [UIApplication.OpenURLOptionsKey : Any] = [:]
          ) -> Bool {
              // track deeplink
              Airbridge.trackDeeplink(url: url)

              // handle airbridge deeplink
              var isHandled = Airbridge.handleDeeplink(url: url) { url in
                  DeeplinkHandler.handleSchemeDeeplink(url: url)
              }
              if isHandled { return isHandled }

              // handle scheme deeplink
              isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
              if isHandled { return isHandled }

              // handle other deeplink
              isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)

              return isHandled
          }

          // when app is opened with universal links
          func application(
              _ application: UIApplication,
              continue userActivity: NSUserActivity,
              restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
          ) -> Bool {
              // track deeplink
              Airbridge.trackDeeplink(userActivity: userActivity)

              // handle airbridge deeplink
              var isHandled = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                  DeeplinkHandler.handleSchemeDeeplink(url: url)
              }
              if isHandled { return isHandled }

              // handle other deeplink
              if let url = userActivity.webpageURL {
                  isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
              }

              return isHandled
          }
      }
      ```

      ```swift SwiftUI (Swift) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import SwiftUI
      import Airbridge

      @main
      struct ActualApp: App {
          var body: some Scene {
              WindowGroup {
                  ContentView()
                      // when app is opened with scheme deeplink or universal links
                      .onOpenURL { url in
                          // track deeplink
                          Airbridge.trackDeeplink(url: url)

                          // handle airbridge deeplink
                          var isHandled = Airbridge.handleDeeplink(url: url) { url in
                              DeeplinkHandler.handleSchemeDeeplink(url: url)
                          }
                          if isHandled { return }

                          // handle scheme deeplink
                          isHandled = DeeplinkHandler.handleSchemeDeeplink(url: url)
                          if isHandled { return }

                          // handle other deeplink
                          isHandled = DeeplinkHandler.handleOtherDeeplink(url: url)
                      }
              }
          }
      }
      ```

      ```objective-c SceneDelegate (Objective-C) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import "SceneDelegate.h"
      #import "ABDeeplinkHandler.h"
      #import <Airbridge/Airbridge.h>

      @interface SceneDelegate ()

      @end

      @implementation SceneDelegate

      // when terminated app is opened with scheme deeplink or universal links
      - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
          // when app is opened with scheme deeplink
          NSURL* url = connectionOptions.URLContexts.allObjects.firstObject.URL;
          NSUserActivity* userActivity = connectionOptions.userActivities.allObjects.firstObject;
          if (url != nil) {
              // track deeplink
              [Airbridge trackDeeplinkWithUrl:url];

              // handle airbridge deeplink
              BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
                  [ABDeeplinkHandler handleSchemeDeeplink:url];
              }];
              if (isHandled) { return; }

              // handle scheme deeplink
              isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
              if (isHandled) { return; }

              // handle other deeplink
              isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
          }
          else if (userActivity != nil) {
              // track deeplink
              [Airbridge trackDeeplinkWithUserActivity:userActivity];

              // handle airbridge deeplink
              BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
                  [ABDeeplinkHandler handleSchemeDeeplink:url];
              }];
              if (isHandled) { return; }

              // handle other deeplink
              NSURL* url = userActivity.webpageURL;
              if (url != nil) {
                  isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
              }
          }
      }

      // when backgrounded app is opened with scheme deeplink
      - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
          NSURL* url = URLContexts.allObjects.firstObject.URL;
          if (url == nil) { return; }

          // track deeplink
          [Airbridge trackDeeplinkWithUrl:url];

          // handle airbridge deeplink
          BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
              [ABDeeplinkHandler handleSchemeDeeplink:url];
          }];
          if (isHandled) { return; }

          // handle scheme deeplink
          isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
          if (isHandled) { return; }

          // handle other deeplink
          isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
      }

      // when backgrounded app is opened with universal links
      - (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
          // track deeplink
          [Airbridge trackDeeplinkWithUserActivity:userActivity];

          // handle airbridge deeplink
          BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
              [ABDeeplinkHandler handleSchemeDeeplink:url];
          }];
          if (isHandled) { return; }

          // handle other deeplink
          NSURL* url = userActivity.webpageURL;
          if (url != nil) {
              isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
          }
      }

      @end
      ```

      ```objective-c AppDelegate (Objective-C) lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import "AppDelegate.h"
      #import "ABDeeplinkHandler.h"
      #import <Airbridge/Airbridge.h>

      @interface AppDelegate ()

      @end

      @implementation AppDelegate

      // when app is opened with scheme deeplink
      - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
          // track deeplink
          [Airbridge trackDeeplinkWithUrl:url];

          // handle airbridge deeplink
          BOOL isHandled = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
              [ABDeeplinkHandler handleSchemeDeeplink:url];
          }];
          if (isHandled) { return isHandled; }
          
          // handle scheme deeplink
          isHandled = [ABDeeplinkHandler handleSchemeDeeplink:url];
          if (isHandled) { return isHandled; }
          
          // handle other deeplink
          isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
          
          return isHandled;
      }

      // when app is opened with universal links
      - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
          // track deeplink
          [Airbridge trackDeeplinkWithUserActivity:userActivity];

          // handle airbridge deeplink
          BOOL isHandled = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
              [ABDeeplinkHandler handleSchemeDeeplink:url];
          }];
          if (isHandled) { return isHandled; }
          
          // handle other deeplink
          NSURL* url = userActivity.webpageURL;
          if (url != nil) {
              isHandled = [ABDeeplinkHandler handleOtherDeeplink:url];
          }
          
          return isHandled;
      }

      @end
      ```
    </CodeGroup>

    <Note>
      `Airbridge.handleDeeplink` 함수는 에어브릿지 딥링크가 입력되면 true를 반환하고 Scheme 딥링크로 변환하여 `onSuccess`에 전달합니다. 그리고 에어브릿지 딥링크가 아닌 URL이 입력되거나 SDK가 초기화되지 않았으면 false를 반환하기만 합니다.
    </Note>
  </Accordion>

  <Accordion title="필요한 작업 - 디퍼드 딥링크 처리">
    SDK를 초기화하는 부분에서`Airbridge.handleDeferredDeeplink` 함수를 호출합니다. `onSuccess` 콜백에서 에어브릿지로 실행된 스킴 딥링크를 처리하는 함수를 호출합니다.

    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import Airbridge
      ...
      let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
          .build()
      Airbridge.initializeSDK(option: option)
      ...
      let isHandled = Airbridge.handleDeferredDeeplink() { url in
          if let url {
              DeeplinkHandler.handleSchemeDeeplink(url)
          }
      }
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import <Airbridge/Airbridge.h>
      ...
      AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                     token:@"YOUR_APP_SDK_TOKEN"];
      AirbridgeOption* option = [optionBuilder build];
      [Airbridge initializeSDKWithOption:option];
      ...
      [Airbridge handleDeferredDeeplinkOnSuccess:^(NSURL* url) {
          if (url != nil) {
              [ABDeeplinkHandler handleSchemeDeeplink:url];
          }
      }];
      ```
    </CodeGroup>

    `Airbridge.handleDeferredDeeplink` 함수는 에어브릿지 딥링크가 입력되면 true와 함께 에어브릿지 딥링크 획득을 기다리거나 스킴 딥링크로 변환해 onSuccess로 전달합니다. 해당 스킴 딥링크를 활용해 유저를 설정한 목적지로 보낼 수 있습니다.

    또는 저장된 에어브릿지 딥링크가 없으면 nil을 전달합니다. SDK가 초기화되지 않았거나 `Airbridge.handleDeferredDeeplink` 함수를 처음으로 호출하지 않았다면 false를 전달합니다.
  </Accordion>
</AccordionGroup>

커스텀 도메인을 등록하는 방법이 변경되었습니다. 기존에는 Info.plist의 `co.ab180.airbridge.trackingLink.customDomains` 키에 커스텀 도메인을 밸류로 추가했습니다.

변경된 방식은 SDK 초기화 단계에서 `setTrackingLinkCustomDomains` 함수를 호출하여 추가하는 방식입니다.

<Accordion title="필요한 작업 - 커스텀 도메인">
  SDK 초기화 코드에서 `setTrackingLinkCustomDomains` 함수를 호출해 주세요.

  <CodeGroup>
    ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import Airbridge
    ...
    // YOUR_APP_NAME: input your app name
    // YOUR_APP_SDK_TOKEN: input your app token
    // YOUR_APP_CUSTOM_DOMAIN: input your app custom domain. ex) example.domain.com
    let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME",
                                        token: "YOUR_APP_SDK_TOKEN")
        .setTrackingLinkCustomDomains(["YOUR_APP_CUSTOM_DOMAIN"])
        .build()
    Airbridge.initializeSDK(option: option)
    ```

    ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    #import <Airbridge/Airbridge.h>
    ...
    // YOUR_APP_NAME: input your app name
    // YOUR_APP_SDK_TOKEN: input your app token
    // YOUR_APP_CUSTOM_DOMAIN: input your app custom domain. ex) example.domain.com
    AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                   token:@"YOUR_APP_SDK_TOKEN"];
    [optionBuilder setTrackingLinkCustomDomains:@[@"YOUR_APP_CUSTOM_DOMAIN"]];
    AirbridgeOption* option = [optionBuilder build];
    [Airbridge initializeSDKWithOption:option];
    ```
  </CodeGroup>
</Accordion>

### 인앱 이벤트 및 유저 정보

<Danger>
  **주의하세요**

  기존 totalValue 대신 AirbridgeAttribute.VALUE에 값을 입력해 주세요.

  setSemantics의 totalValue를 사용하고 setValue로 밸류를 정의하면 totalValue가 밸류를 덮어 쓰는 로직은 iOS SDK v4부터 삭제되었습니다.
</Danger>

ABInAppEvent 클래스가 `Airbridge.trackEvent` 함수로 대체되었습니다.

아래 가이드에 따라 ABInAppEvent 클래스와 setAction, setLabel, setValue, setSemantics, setCustoms를 `Airbridge.trackEvent`함수로 변경해 주세요.

* setCategory: ABCategory를 사용하고 있다면 AirbridgeCategory를 사용해야 합니다. String을 사용하고 있다면 그대로 category 파라미터에 입력합니다.
* setAction: semanticAttributes 파라미터의 AirbridgeAttribute.ACTION 키에 입력합니다.
* setLabel: semanticAttributes 파라미터의 AirbridgeAttribute.LABEL 키에 입력합니다.
* setValue: semanticAttributes 파라미터의 AirbridgeAttribute.VALUE 키에 입력합니다.
* setSemantics: semanticAttributes 파라미터에 키로 ABSemanticsKey를 사용하고 있다면 AirbridgeAttribute를 사용합니다. String을 사용하고 있다면 그대로 입력합니다. 밸류는 키와 관계 없이 그대로 입력합니다.
* setCustoms: customAttributes 파라미터에 키, 밸류를 그대로 입력합니다.

아래에서 AirbridgeCategory, AirbridgeAttribute 매핑과 Airbridge.trackEvent 함수를 참고해 주세요.

<AccordionGroup>
  <Accordion title="AirbridgeCategory 맵핑">
    | ABCategory        | AirbridgeCategory       |
    | ----------------- | ----------------------- |
    | signIn            | SIGN\_IN                |
    | signUp            | SIGN\_UP                |
    | signOut           | SIGN\_OUT               |
    | viewHome          | HOME\_VIEWED            |
    | viewProductList   | PRODUCT\_LIST\_VIEWED   |
    | viewSearchResult  | SEARCH\_RESULTS\_VIEWED |
    | viewProductDetail | PRODUCT\_VIEWED         |
    | addToCart         | ADDED\_TO\_CART         |
    | purchase          | ORDER\_COMPLETED        |
  </Accordion>

  <Accordion title="AirbridgeAttribute 맵핑">
    | ABSemanticsKey | AirbridgeAttribute      |
    | -------------- | ----------------------- |
    | products       | PRODUCTS                |
    | transactionID  | TRANSACTION\_ID         |
    | inAppPurchased | IN\_APP\_PURCHASED      |
    | cartID         | CART\_ID                |
    | query          | QUERY                   |
    | productListID  | PRODUCT\_LIST\_ID       |
    | currency       | CURRENCY                |
    | totalValue     | 제거되었습니다. VALUE에 입력해주세요. |
    | totalQuantity  | TOTAL\_QUANTITY         |

    | ABProductKey | AirbridgeAttribute |
    | ------------ | ------------------ |
    | productID    | PRODUCT\_ID        |
    | name         | PRODUCT\_NAME      |
    | price        | PRODUCT\_PRICE     |
    | currency     | PRODUCT\_CURRENCY  |
    | position     | PRODUCT\_POSITION  |
    | quantity     | PRODUCT\_QUANTITY  |
  </Accordion>

  <Accordion title="예시) Airbridge.trackEvent 함수">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import Airbridge
      ...
      // setCategory
      Airbridge.trackEvent(
          category: AirbridgeCategory.ORDER_COMPLETED,
          semanticAttributes: [
              // setAction
              AirbridgeAttribute.ACTION: "Tool",
              // setLabel
              AirbridgeAttribute.LABEL: "Hammer",
              // setValue
              AirbridgeAttribute.VALUE: 10,
              // setSemantics (using ABSemanticsKey)
              AirbridgeAttribute.CURRENCY: "USD",
              AirbridgeAttribute.PRODUCTS: [
                  [
                      // setSemantics value (using ABProductKey)
                      AirbridgeAttribute.PRODUCT_ID: "12345",
                      // setSemantics value (using String)
                      "name": "PlasticHammer",
                  ],
              ],
              // setSemantics (using String)
              "totalQuantity": 1,
          ],
          customAttributes: [
              // setCustoms
              "promotion": "FirstPurchasePromotion",
          ]
      )
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import <Airbridge/Airbridge.h>
      ...
      [Airbridge trackEventWithCategory:@"event" semanticAttributes:@{
          // action
          AirbridgeAttribute.ACTION: @"Tool",
          // label
          AirbridgeAttribute.LABEL: @"Hammer",
          // value
          AirbridgeAttribute.VALUE: @(10),
          // semantic attribute (provided by sdk)
          AirbridgeAttribute.CURRENCY: @"USD",
          AirbridgeAttribute.PRODUCTS: @[
              @{
                  // semantic attribute value (provided by sdk)
                  AirbridgeAttribute.PRODUCT_ID: @"12345",
                  // semantic attribute value (not provided by sdk)
                  @"name": @"PlasticHammer",
              },
          ],
          // semantic attribute (not provided by sdk)
          @"totalQuantity": @(1),
      }, customAttributes:@{
          // custom attribute
          @"promotion": @"FirstPurchasePromotion",
      }];
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

`AirBridge.setDeviceAlias` 관련 함수가 [Airbridge.setDeviceAlias 관련 함수](/ko/developers/ios-sdk-v4#디바이스-식별자-설정하기)로 대체되었습니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  import Airbridge
  ...
  Airbridge.setDeviceAlias(key: "string", value: "string")
  Airbridge.removeDeviceAlias(key: "string")
  Airbridge.clearDeviceAlias()
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  #import <Airbridge/Airbridge.h>
  ...
  BOOL isHandled = [Airbridge impressionWithTrackingLink:url onSuccess:^{
      // when url is tracking link and succeed
  } onFailure:^(NSError * _Nonnull) {
      // when url is tracking link and failed
  }];
  if (!isHandled) {
      // when url is not tracking link
  }
  ```
</CodeGroup>

`AirBridge.state().setUser` 관련 함수가 [Airbridge.setUser 관련 함수](/ko/developers/ios-sdk-v4#유저-속성-설정하기)로 대체되었습니다. 유저 정보를 한번에 설정하는 `setUser` 함수는 지원하지 않습니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  import Airbridge
  ...
  // identifier
  Airbridge.setUserID("string")
  Airbridge.clearUserID()
  // addtional identifier
  Airbridge.setUserAlias(key: "string", value: "string")
  Airbridge.removeUserAlias(key: "string")
  Airbridge.clearUserAlias()
  ...
  // email, phone
  Airbridge.setUserEmail("string")
  Airbridge.clearUserEmail()
  Airbridge.setUserPhone("string")
  Airbridge.clearUserPhone()
  // addtional attribute
  Airbridge.setUserAttribute(key: "string", value: "string")
  Airbridge.setUserAttribute(key: "number", value: 1000)
  Airbridge.removeUserAttribute(key: "string")
  Airbridge.clearUserAttributes()
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  #import <Airbridge/Airbridge.h>
  ...
  // identifier
  [Airbridge setUserID:@"string"];
  [Airbridge clearUserID];
  // additional identifier
  [Airbridge setUserAliasWithKey:@"string" value:@"string"];
  [Airbridge removeUserAliasWithKey:@"string"];
  [Airbridge clearUserAlias];
  ...
  // email, phone
  [Airbridge setUserEmail:@"string"];
  [Airbridge clearUserEmail];
  [Airbridge setUserPhone:@"string"];
  [Airbridge clearUserPhone];
  // addtional attribute
  [Airbridge setUserAttributeWithKey:@"string" value:@"string"];
  [Airbridge setUserAttributeWithKey:@"number" value:@(1000)];
  [Airbridge removeUserAttributeWithKey:@"string"];
  [Airbridge clearUserAttributes];
  ```
</CodeGroup>

### 추가 설정하기

`AirBridge.placement().click` 함수와 `AirBridge.placement().impression` 함수가 `Airbridge.click` 함수와 `Airbridge.impression` 함수로 대체되었습니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  import Airbridge
  ...
  let isHandled = Airbridge.click(trackingLink: url) {
      // when url is tracking link and succeed
  } onFailure: { error in
      // when url is tracking link and failed
      // example: url is another app's tracking link, internet is not connected
  }
  if !isHandled {
      // when url is not tracking link
  }
  ...
  let isHandled = Airbridge.impression(trackingLink: url) {
      // when url is tracking link and succeed
  } onFailure: { error in
      // when url is tracking link and failed
  }
  if !isHandled {
      // when url is not tracking link
  }
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  #import <Airbridge/Airbridge.h>
  ...
  BOOL isHandled = [Airbridge clickWithTrackingLink:url onSuccess:^{
      // when url is tracking link and succeed
  } onFailure:^(NSError * _Nonnull) {
      // when url is tracking link and failed
      // example: url is another app's tracking link, internet is not connected
  }];
  if (!isHandled) {
      // when url is not tracking link
  }
  ...
  BOOL isHandled = [Airbridge impressionWithTrackingLink:url onSuccess:^{
      // when url is tracking link and succeed
  } onFailure:^(NSError * _Nonnull) {
      // when url is tracking link and failed
  }];
  if (!isHandled) {
      // when url is not tracking link
  }
  ```
</CodeGroup>

`AirBridge.webInterface().inject` 함수가 `Airbridge.setWebInterface` 함수로 대체되었습니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  import Airbridge
  ...
  Airbridge.setWebInterface(
      controller: controller,
      webToken: "YOUR_WEB_TOKEN"
  )
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  #import <Airbridge/Airbridge.h>
  ...
  [Airbridge setWebInterfaceWithController:controller webToken:@"YOUR_WEB_TOKEN"];
  ```
</CodeGroup>

## v1.x 업데이트

iOS SDK 각 버전의 주요 변경사항을 참고해 주세요.

### v1.36.0 - 딥링크

2023년 9월 4일 이후 생성된 에어브릿지 앱은 딥링크 콜백에서 제공되는 딥링크 URL이 에어브릿지 대시보드에 입력된 내용을 2번 디코딩해 제공하는 문제를 해결했습니다.

해당 문제는 iOS SDK v1.34.0 \~ 1.35.1에서 발생했습니다.

### v1.34.0 - 딥링크

2023년 9월 4일 이후 생성된 에어브릿지 앱은 딥링크 콜백에 제공되는 딥링크 URL에 airbridge\_referrer를 추가하지 않고 에어브릿지 대시보드에 입력한 정보로 전달됩니다.

2023년 9월 4일 이전에 생성된 에어브릿지 앱을 사용하는 고객사 중에서 해당 기능이 필요한 고객사는 에어브릿지 CSM에게 요청해 주세요. 담당 CSM이 없는 경우 [문의하기](https://app.airbridge.io/supports)를 통해 요청해 주세요.

### v1.33.0 - SKAdNetwork

SKAdNetwork 4.0을 지원하면서 전환값 계산 방식이 변경되었습니다. 유저가 iOS SDK v1.33.0 미만을 설치한 앱에서 v1.33.0 이상이 있는 앱으로 업데이트하면 마지막에 계산된 전환값을 최종 값으로 확정합니다.

### v1.32.1 - 개인정보보호 설정

`trackingAuthorizeTimeout`의 기본 설정이 0초에서 30초로 변경되었습니다.

<link rel="alternate" hrefLang="en" href="https://help.airbridge.io/en/developers/migration-guide-for-ios-sdk-v4" />

<link rel="alternate" hrefLang="ko" href="https://help.airbridge.io/ko/developers/migration-guide-for-ios-sdk-v4" />
