> ## 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.

# 딥링크 - iOS SDK

에어브릿지 iOS SDK를 설치하고 필요한 설정을 추가할 수 있습니다.

## iOS SDK 설치하기

에어브릿지 iOS SDK는 아래 방법으로 설치할 수 있습니다. 설치한 이후에 [iOS SDK 테스트](#테스트하기)로 SDK가 정상적으로 설치됐는지 확인할 수 있습니다.

<Tabs>
  <Tab title="SwiftPackageManager">
    1. Xcode에서 \[File]에서 \[Add Packages...]를 클릭해 주세요.

    2. 검색창에 아래 주소를 입력하고 \[Add Package]를 클릭합니다.
       * [https://github.com/ab180/airbridge-ios-sdk-deployment](https://github.com/ab180/airbridge-ios-sdk-deployment)

    3. \[Add Package]를 계속해서 클릭합니다.

    4. Xcode의 \[Package Dependencies]에서 에어브릿지 iOS SDK 추가를 확인할 수 있습니다.
  </Tab>

  <Tab title="CocoaPods">
    <Danger>
      **주의하세요**

      \[Xcode]>\[YOUR\_PROJECT]>\[Build Settings]>\[User Script Sandboxing]을 No로 설정한 후에 iOS SDK를 설치해야 합니다. 자세한 내용은 [CocoaPods 문서](https://github.com/CocoaPods/CocoaPods/issues/11946)를 참고해 주세요.
    </Danger>

    1. `brew install cocoapods` 로 CocoaPods를 설치합니다.
    2. `pod init`로 Podfile을 생성합니다.
    3. Podfile에 아래 코드로 SDK를 의존성으로 추가합니다. 그리고 아래 링크에서 최신버전을 확인하고 `$HERE_LATEST_VERSION` 에 입력하세요.
       * SDK 버전 목록: [링크](/ko/developers/release-note-ios-sdk)

    ```ruby Podfile lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    target '[Project Name]' do
        ...
        # Replace $HERE_LATEST_VERSION with latest version
        # - Versions: https://help.airbridge.io/developers/release-note-ios-sdk
        # - Example: pod 'airbridge-ios-sdk', '4.X.X'
        pod 'airbridge-ios-sdk', '$HERE_LATEST_VERSION'
        ...
    end
    ```

    4. `pod install --repo-update`를 입력하면 설치가 진행됩니다
    5. `YOUR_PROJECT.xcworkspace`를 실행하면 에어브릿지 iOS SDK가 정상적으로 설치된 것을 확인할 수 있습니다.
  </Tab>

  <Tab title="Tuist">
    <Danger>
      **주의하세요**

      Tuist의 [Tuist's XcodeProj-based integration](https://docs.tuist.dev/en/guides/develop/projects/dependencies#tuists-xcodeprojbased-integration) 방식으로는 에어브릿지 iOS SDK를 설치할 수 없습니다. 반드시 [Xcode's default integration](https://docs.tuist.dev/en/guides/develop/projects/dependencies#xcodes-default-integration) 방식으로 설치해 주세요.
    </Danger>

    1. `tuist edit` 명령어를 실행합니다.
    2. `project.packages`에 `remote`를 추가합니다. SDK를 `project.targets[...].target.dependencies`에 `package`로, 의존성 Framework를 `sdk`로 추가합니다. 그리고 아래 링크에서 최신버전을 확인하고 `$HERE_LATEST_VERSION` 에 입력하세요.
       * SDK 버전 목록: [링크](/ko/developers/release-note-ios-sdk)

    * 의존성 Framework 목록

    | Framework                         | 설명                                            |
    | --------------------------------- | --------------------------------------------- |
    | AdSupport.framework               | IDFA를 수집하는데 사용합니다.                            |
    | CoreTelephony.framework           | 통신사 정보를 수집하는데 사용합니다.                          |
    | StoreKit.framework                | SKAdNetwork 정보를 수집하는데 사용합니다.                  |
    | AppTrackingTransparency.framework | 추적 허용 상태정보를 수집하는데 사용합니다.                      |
    | AdServices.framework              | Apple Ads의 어트리뷰션 정보를 수집하는데 사용합니다. (iOS 14.3+) |
    | WebKit.framework                  | Web SDK와 연동하여 이벤트를 수집하는데 사용합니다.               |

    ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import ProjectDescription

    let project = Project(
        packages: [
            .remote(
                url: "https://github.com/ab180/airbridge-ios-sdk-deployment",
                // Replace $HERE_LATEST_VERSION with latest version
                // - Versions: https://help.airbridge.io/developers/release-note-ios-sdk
                // - Example: requirement: .exact(from: "4.X.X")
                requirement: .exact(from: "$HERE_LATEST_VERSION")
            ),
            ...
        ],
        targets: [
            .target(
                dependencies: [
                    .package(product: "Airbridge", type: .runtime),
                    .sdk(name: "AdSupport", type: .framework, status: .optional),
                    .sdk(name: "AdServices", type: .framework, status: .optional),
                    .sdk(name: "CoreTelephony", type: .framework, status: .optional),
                    .sdk(name: "StoreKit", type: .framework, status: .optional),
                    .sdk(name: "AppTrackingTransparency", type: .framework, status: .optional),
                    .sdk(name: "WebKit", type: .framework, status: .optional),
                    ...
                ]
            ),
            ...
        ],
        ...
    )
    ```

    3. `tuist generate` 명령어를 실행합니다.
    4. Xcode의 Package Dependencies에 Airbridge가 추가됩니다.
  </Tab>

  <Tab title="직접 설치">
    1. 아래 링크에서 에어브릿지 iOS SDK를 다운로드합니다.
       * [https://sdk-download.airbridge.io/airbridge-ios-sdk/latest/Airbridge.zip](https://sdk-download.airbridge.io/airbridge-ios-sdk/latest/Airbridge.zip)

    2. Airbridge.xcframework를 프로젝트에 추가합니다. \[Xcode]>\[프로젝트 파일]>\[General]>\[Frameworks, Libraries, and Embedded Content]에서 ‘+’를 클릭합니다.

    3. \[Add Other...]에서 ‘Add Files...’를 클릭하고 Airbridge.xcframework를 선택합니다.

    4. Airbridge.xcframework의 Embed를 Embed & Sign로 설정합니다.
  </Tab>
</Tabs>

### 디바이스 ID를 수집하지 않는 SDK

<Info>
  **알립니다**

  일반 SDK와 제한된 SDK 중에서 1가지 버전만 설치해 주세요.
</Info>

정책, 환경 등에 따라 GAID, IDFA 같은 디바이스 ID 수집에 제한이 필요할 수 있습니다. 제한된 SDK(Restricted SDK)를 설치하면 에어브릿지 SDK가 GAID, IDFA 같은 디바이스ID를 수집하지 않습니다.

아래 방법에 따라 제한된 SDK를 설치해 주세요.

<Tabs>
  <Tab title="SwiftPackageManager">
    1. Xcode에서 \[File]>\[Add Packages...]를 클릭합니다.

    2. 검색창에 아래 주소를 입력하고 \[Add Package]를 클릭합니다.
       * [https://github.com/ab180/airbridge-ios-sdk-restricted-deployment](https://github.com/ab180/airbridge-ios-sdk-restricted-deployment)

    3. \[Add Package]를 계속해서 클릭합니다.

    4. Xcode의 \[Package Dependencies]에서 Airbridge가 추가된 것을 확인할 수 있습니다.

    5. SDK의 의존성에 해당하는 Framework를 프로젝트에 추가합니다. \[Xcode]>\[프로젝트 파일]>\[General]>\[Frameworks, Libraries, and Embedded Content]에서 ‘+’를 클릭합니다.

    6. 아래 Framework를 모두 추가합니다. 추가한 Framework의 Embed를 Do not Embed로 설정합니다. 그리고 \[Xcode]>\[프로젝트 파일]>\[Build Phase]>\[Link Binary With Libraries]에서 Status를 Optional로 설정합니다.

    | Framework               | 설명                                            |
    | ----------------------- | --------------------------------------------- |
    | CoreTelephony.framework | 통신사 정보를 수집하는데 사용합니다.                          |
    | StoreKit.framework      | SKAdNetwork 정보를 수집하는데 사용합니다.                  |
    | AdServices.framework    | Apple Ads의 어트리뷰션 정보를 수집하는데 사용합니다. (iOS 14.3+) |
    | WebKit.framework        | Web SDK와 연동하여 이벤트를 수집하는데 사용합니다.               |
  </Tab>

  <Tab title="CocoaPods">
    <Danger>
      **주의하세요**

      \[Xcode]>\[YOUR\_PROJECT]>\[Build Settings]>\[User Script Sandboxing]을 No로 설정한 후에 iOS SDK를 설치해야 합니다. 자세한 내용은 [CocoaPods 문서](https://github.com/CocoaPods/CocoaPods/issues/11946)를 참고해 주세요.
    </Danger>

    1. `brew install cocoapods`로 CocoaPods를 설치합니다.
    2. `pod init`로 Podfile을 생성합니다.
    3. Podfile에 아래 코드로 SDK를 의존성으로 추가합니다. 그리고 아래 링크에서 최신버전을 확인하고 `$HERE_LATEST_VERSION` 에 입력하세요.
       * SDK 버전 목록: [링크](/ko/developers/release-note-ios-sdk)

    ```ruby Podfile lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    target '[Project Name]' do
        ...
        # Replace $HERE_LATEST_VERSION with latest version
        # - Versions: https://help.airbridge.io/developers/release-note-ios-sdk
        # - Example: pod 'airbridge-ios-sdk-restricted', '4.X.X'
        pod 'airbridge-ios-sdk-restricted', '$HERE_LATEST_VERSION'
        ...
    end
    ```

    4. `pod install --repo-update`를 입력하면 설치가 진행됩니다
    5. `YOUR_PROJECT.xcworkspace`를 실행하면 에어브릿지 iOS SDK가 정상적으로 설치된 것을 확인할 수 있습니다.
  </Tab>

  <Tab title="Tuist">
    <Danger>
      **주의하세요**

      Tuist의 [Tuist's XcodeProj-based integration](https://docs.tuist.dev/en/guides/develop/projects/dependencies#tuists-xcodeprojbased-integration) 방식으로는 에어브릿지 iOS SDK를 설치할 수 없습니다. 반드시 [Xcode's default integration](https://docs.tuist.dev/en/guides/develop/projects/dependencies#xcodes-default-integration) 방식으로 설치해 주세요.
    </Danger>

    1. `tuist edit` 명령어를 실행합니다.
    2. `project.packages`에 `remote`를 추가합니다. SDK를 `project.targets[...].target.dependencies`에 `package`로, 의존성 Framework를 `sdk`로 추가합니다. 그리고 아래 링크에서 최신버전을 확인하고 `$HERE_LATEST_VERSION` 에 입력하세요.
       * SDK 버전 목록: [링크](/ko/developers/release-note-ios-sdk)

    * 의존성 Framework 목록

    | Framework               | 설명                                            |
    | ----------------------- | --------------------------------------------- |
    | CoreTelephony.framework | 통신사 정보를 수집하는데 사용합니다.                          |
    | StoreKit.framework      | SKAdNetwork 정보를 수집하는데 사용합니다.                  |
    | AdServices.framework    | Apple Ads의 어트리뷰션 정보를 수집하는데 사용합니다. (iOS 14.3+) |
    | WebKit.framework        | Web SDK와 연동하여 이벤트를 수집하는데 사용합니다.               |

    ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import ProjectDescription

    let project = Project(
        packages: [
            .remote(
                url: "https://github.com/ab180/airbridge-ios-sdk-restricted-deployment",
                // Replace $HERE_LATEST_VERSION with latest version
                // - Versions: https://help.airbridge.io/developers/release-note-ios-sdk
                // - Example: requirement: .exact(from: "4.X.X")
                requirement: .exact(from: "$HERE_LATEST_VERSION")
            ),
            ...
        ],
        targets: [
            .target(
                dependencies: [
                    .package(product: "Airbridge", type: .runtime),
                    .sdk(name: "AdServices", type: .framework, status: .optional),
                    .sdk(name: "CoreTelephony", type: .framework, status: .optional),
                    .sdk(name: "StoreKit", type: .framework, status: .optional),
                    .sdk(name: "WebKit", type: .framework, status: .optional),
                    ...
                ]
            ),
            ...
        ],
        ...
    )
    ```

    3. `tuist generate` 명령어를 실행합니다.
    4. Xcode의 Package Dependencies에 Airbridge가 추가됩니다.
  </Tab>

  <Tab title="직접 설치">
    1. 아래 링크에서 에어브릿지 iOS SDK를 다운로드합니다.
       * [https://sdk-download.airbridge.io/airbridge-ios-sdk-restricted/latest/Airbridge.zip](https://sdk-download.airbridge.io/airbridge-ios-sdk-restricted/latest/Airbridge.zip)

    2. Airbridge.xcframework를 프로젝트에 추가합니다. \[Xcode]>\[프로젝트 파일]>\[General]>\[Frameworks, Libraries, and Embedded Content]에서 ‘+’를 클릭합니다.

    3. \[Add Other...]에서 ‘Add Files...’를 클릭하고 Airbridge.xcframework를 선택합니다.

    4. Airbridge.xcframework의 Embed를 Embed & Sign로 설정합니다.

    5. SDK의 의존성에 해당하는 Framework를 프로젝트에 추가합니다. \[Xcode]>\[프로젝트 파일]>\[General]>\[Frameworks, Libraries, and Embedded Content]에서 ‘+’를 클릭합니다.

    6. 아래 Framework를 모두 추가합니다. 추가한 Framework의 Embed를 Do not Embed로 설정합니다. 그리고 \[Xcode]>\[프로젝트 파일]>\[Build Phase]>\[Link Binary With Libraries]에서 Status를 Optional로 설정합니다.

    | Framework               | 설명                                            |
    | ----------------------- | --------------------------------------------- |
    | CoreTelephony.framework | 통신사 정보를 수집하는데 사용합니다.                          |
    | StoreKit.framework      | SKAdNetwork 정보를 수집하는데 사용합니다.                  |
    | AdServices.framework    | Apple Ads의 어트리뷰션 정보를 수집하는데 사용합니다. (iOS 14.3+) |
    | WebKit.framework        | Web SDK와 연동하여 이벤트를 수집하는데 사용합니다.               |
  </Tab>
</Tabs>

### SDK 초기화하기

시스템 방식에 따라 SDK 초기화 방법이 다릅니다. SceneDelegate Lifecycle 또는 AppDelegate Lifecycle은 AppDelegate를 참고해 주세요. SwiftUI Lifecycle는 SwiftUI를 참고해 주세요.

YOUR\_APP\_NAME과 YOUR\_APP\_SDK\_TOKEN은 에어브릿지 대시보드의 \[설정]>\[토큰 관리]에서 확인할 수 있습니다.

<Tabs>
  <Tab title="AppDelegate (Swift)">
    `AppDelegate`의 `application(_:didFinishLaunchingWithOptions:)` 가장 위에서 `Airbridge.initializeSDK` 함수를 호출합니다.

    ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import UIKit
    import Airbridge

    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
        func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
        ) -> Bool {
            let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
                .build()
            Airbridge.initializeSDK(option: option)
            return true
        }
    }
    ```

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

      `Airbridge.initializeSDK` 함수를 `AppDelegate` 의 `application(_:didFinishLaunchingWithOptions:)` 시점에 호출해야 올바르게 동작합니다.
    </Danger>
  </Tab>

  <Tab title="AppDelegate (Objective-C)">
    AppDelegate의 `application:didFinishLaunchingWithOptions:` 가장 위에서 `Airbridge.initializeSDK` 함수를 호출합니다.

    ```objective-c lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    #import "AppDelegate.h"
    #import <Airbridge/Airbridge.h>

    @interface AppDelegate ()

    @end

    @implementation AppDelegate

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                       token:@"YOUR_APP_SDK_TOKEN"];
        AirbridgeOption* option = [optionBuilder build];
        [Airbridge initializeSDKWithOption:option];
        return YES;
    }

    @end
    ```

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

      `Airbridge.initializeSDK` 함수를 `AppDelegate` 의 `application(_:didFinishLaunchingWithOptions:)` 시점에 호출해야 올바르게 동작합니다.
    </Danger>
  </Tab>

  <Tab title="SwiftUI">
    `init` 가장 위에서 `Airbridge.initializeSDK` 함수를 호출합니다.

    ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import SwiftUI
    import Airbridge

    @main
    struct ExampleApp: App {
        init() {
            let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
                .build()
            Airbridge.initializeSDK(option: option)
        }
        
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    ```

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

      `Airbridge.initializeSDK` 함수를 `App` 의 `init` 시점에 호출해야 올바르게 동작합니다.
    </Danger>

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

      SwiftUI Lifecycle 방식은 리퍼러 URL(ReferrerURL)을 제공하지 않아 [오가닉 리퍼러 어트리뷰션](/ko/guides/organic-referrer-attribution)을 사용할 수 없습니다. UIApplicationDelegateAdaptor를 활용해도 SwiftUI Lifecycle 방식에서는 오가닉 리퍼러 어트리뷰션을 사용할 수 없습니다.
    </Danger>
  </Tab>
</Tabs>

### ATT 프롬프트 제공하기

<Info>
  **알립니다**

  개인정보보호 정책 준수를 위해 필요한 기능은 법률 자문사와 함께 검토해야 합니다.
</Info>

iOS 환경에서는 식별자로 [앱 추적 투명성(App Tracking Transparency, ATT)](https://developer.apple.com/app-store/user-privacy-and-data-use/) 프롬프트에서 정보 수집에 동의한 유저의 [IDFA](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier)만 수집할 수 있습니다.

유저가 추적에 동의하기 전에는 이벤트 수집을 지연해야 합니다. 유저가 ATT 프롬프트에서 정보 수집에 동의하기 전에 앱 설치 이벤트를 수집하면 이벤트에 식별자가 없어 성과 측정이 어렵습니다. 식별자를 수집하기 위한 충분한 이벤트 수집 지연 시간을 설정하는 것을 권장합니다.

1. ATT 프롬프트에 사용하는 문구를 준비합니다.
2. 준비한 문구를 `Info.plist` 파일의 `NSUserTrackingUsageDescription` 키에 입력합니다.

<Tabs>
  <Tab title="Xcode">
    1) Xcode > YOUR\_PROJECT > Info > Custom iOS Target Properties로 이동해주세요.
    2) Key의 항목들에 마우스를 가져가면 표시되는 + 버튼을 누르고 `Privacy - Tracking Usage Description` 를 입력해 주세요.
    3) Value에 표시할 문구를 입력해 주세요.
  </Tab>

  <Tab title="Tuist">
    1. tuist edit 명령어를 실행해주세요.
    2. `project.targets[...].infoPlist` 의 `.extendingDefault` 에 키로 `NSUserTrackingUsageDescription` 를, 밸류로 문구를 입력해주세요.

    ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
    import ProjectDescription

    let project = Project(
        targets: [
            .target(
                infoPlist: .extendingDefault(
                    with: [
                        "NSUserTrackingUsageDescription": "YOUR_DESCRIPTION",
                        ...
                    ]
                ),
                ...
            ),
            ...
        ]
        ...
    )
    ```
  </Tab>
</Tabs>

3. ATT 프롬프트를 제공하는 시점을 결정합니다.

<AccordionGroup>
  <Accordion title="원하는 시점에 ATT 프롬프트 제공하기">
    ATT 프롬프트를 제공하는 시점에 `ATTrackingManager.requestTrackingAuthorization` 함수를 호출합니다.

    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import AppTrackingTransparency
      ...
      ATTrackingManager.requestTrackingAuthorization { _ in }
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import <AppTrackingTransparency/AppTrackingTransparency.h>
      ...
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {}];
      ```
    </CodeGroup>

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

      `ATTrackingManager.requestTrackingAuthorization` 함수는 호출한 앱이 Active 상태가 아니면 ATT 프롬프트를 제공하지 않습니다.
    </Danger>
  </Accordion>

  <Accordion title="앱을 실행하면 ATT 프롬프트 제공하기">
    앱이 실행되는 순간에 바로 ATT 프롬프트를 제공할 수 있습니다.

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

      @main
      class AppDelegate: UIResponder, UIApplicationDelegate {
          var observer: Any?

          func application(
              _ application: UIApplication,
              didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
          ) -> Bool {
              let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
                  .build()
              Airbridge.initializeSDK(option: option)

              observer = NotificationCenter.default.addObserver(
                  forName: UIApplication.didBecomeActiveNotification,
                  object: nil,
                  queue: nil
              ) { [weak self] _ in
                  if #available(iOS 14, *) {
                      ATTrackingManager.requestTrackingAuthorization { _ in }
                  }
                  if let observer = self?.observer {
                      NotificationCenter.default.removeObserver(observer)
                  }
              }

              return true
          }
      }
      ```

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

      @interface AppDelegate ()

      @end

      @implementation AppDelegate {
          id observer;
      }

      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
          AirbridgeOptionBuilder* optionBuilder = [[AirbridgeOptionBuilder alloc] initWithName:@"YOUR_APP_NAME"
                                                                                         token:@"YOUR_APP_SDK_TOKEN"];
          AirbridgeOption* option = [optionBuilder build];
          [Airbridge initializeSDKWithOption:option];
          __weak typeof(self) weakSelf = self;
          observer = [NSNotificationCenter.defaultCenter addObserverForName:UIApplicationDidBecomeActiveNotification
                                                                  object:nil
                                                                      queue:nil
                                                              usingBlock:^(NSNotification * _Nonnull notification) {
              if (@available(iOS 14, *)) {
                  [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {}];
              }
              if (weakSelf != nil && weakSelf->observer != nil) {
                  [NSNotificationCenter.defaultCenter removeObserver:observer];
              }
          }];
          return YES;
      }

      @end
      ```

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

      @main
      struct ExampleApp: App {
          init() {
              let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
                  .build()
              Airbridge.initializeSDK(option: option)

              var observer: Any?
              observer = NotificationCenter.default.addObserver(
                  forName: UIApplication.didBecomeActiveNotification,
                  object: nil,
                  queue: nil
              ) { _ in
                  if #available(iOS 14, *) {
                      ATTrackingManager.requestTrackingAuthorization { _ in }
                  }
                  if let observer {
                      NotificationCenter.default.removeObserver(observer)
                  }
              }
          }
          
          var body: some Scene {
              WindowGroup {
                  ContentView()
              }
          }
      }
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

4. 에어브릿지 iOS SDK는 설치 이벤트가 수집되지 않으면 앱이 실행될 때마다 유저가 추적에 동의하기 전까지 30초 동안 설치 이벤트 수집을 지연합니다. 유저가 추적 동의 여부를 결정하기 전에 앱을 종료하면 설치 이벤트를 수집하지 않고 다음 앱 실행에 다시 시도합니다.

`setAutoDetermineTrackingAuthorizationTimeout` 함수로 설치 이벤트 수집 지연 시간을 더 길게 설정할 수 있습니다. `setAutoDetermineTrackingAuthorizationTimeout` 함수의 기본 설정은 30초입니다. 최대 3600초(1시간)까지 설정할 수 있습니다.

<Note>
  **setAutoDetermineTrackingAuthorizationTimeout 함수 0초 권장**

  딥링크 플랜에서는 `setAutoDetermineTrackingAuthorizationTimeout` 함수를 0초로 설정하는 것을 권장합니다. 딥링크 플랜은 식별자를 활용한 어트리뷰션을 지원하지 않습니다. 따라서 해당 함수를 0초로 설정해야 디퍼드 딥링크에서 설정된 목적지로 앱을 설치한 유저를 지연 없이 보냅니다.
</Note>

<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")
      .setAutoDetermineTrackingAuthorizationTimeout(second: 30)
      .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 setAutoDetermineTrackingAuthorizationTimeoutWithSecond:30];
  AirbridgeOption* option = [optionBuilder build];
  [Airbridge initializeSDKWithOption:option];
  ```
</CodeGroup>

## 딥링크

딥링크를 설정하면 트래킹 링크가 있는 광고를 클릭한 유저를 원하는 앱의 특정 페이지로 이동시킬 수 있습니다. 또한 트래킹 링크로 수집된 정보를 바탕으로 딥링크를 통해서 발생한 성과를 에어브릿지에서 확인할 수 있습니다.

### 에어브릿지의 딥링크 작동 방식

에어브릿지는 트래킹 링크가 열릴 때, 트래킹 링크에 설정된 스킴 딥링크를 유저의 환경에 따라 최적인 형태의 에어브릿지 딥링크(HTTP 딥링크 또는 스킴 딥링크)로 변환하여 유저를 앱으로 이동시킵니다. 그리고 에어브릿지 SDK가 에어브릿지 딥링크를 트래킹 링크에 설정된 스킴 딥링크로 다시 변환하여 앱에 전달합니다.

* 트래킹 링크에 설정된 스킴 딥링크 예시: YOUR\_SCHEME://product/12345
* 에어브릿지 딥링크 예시
  * HTTP 딥링크 형태 1: `https://YOUR_APP_NAME.airbridge.io/~~~`
  * HTTP 딥링크 형태 2: `https://YOUR_APP_NAME.abr.ge/~~~`
  * 스킴 딥링크 형태: YOUR\_SCHEME://product/12345?airbridge\_referrer=\~\~\~

앱이 설치된 상태에서 유저가 트래킹 링크를 열면 에어브릿지 딥링크로 앱이 열립니다. 그리고 에어브릿지 SDK는 해당 에어브릿지 딥링크를 트래킹 링크에 설정되어 있는 스킴 딥링크로 변환한 후에 이를 앱에 전달합니다.

앱이 설치되어 있지 않은 상태에서 유저가 트래킹 링크를 열면 SDK는 에어브릿지 딥링크를 저장합니다. 유저가 앱스토어 또는 웹 사이트로 이동하여 앱 설치 후 앱을 실행하면 에어브릿지 SDK는 저장한 에어브릿지 딥링크를 트래킹 링크에 설정된 스킴 딥링크로 변환한 후에 이를 앱에 전달합니다.

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/6CTRFgWYblklSTQJ/asset/image/deep-link-deferred-routing-diagram.png?fit=max&auto=format&n=6CTRFgWYblklSTQJ&q=85&s=feca42b0a16d964f5950eb31e0fe53cb" alt="에어브릿지 딥링크 간단구조" width="1500" height="506" data-path="asset/image/deep-link-deferred-routing-diagram.png" />
</Frame>

### 딥링크 설정하기

딥링크를 설정합니다. 에어브릿지 대시보드에서 설정한 정보와 유저가 이동하는 목적지로 사용되는 앱 페이지 주소가 필요합니다.

먼저 에어브릿지에 딥링크 정보를 등록합니다.

<Accordion title="에어브릿지에 딥링크 정보 등록하기">
  에어브릿지 대시보드의 \[트래킹링크]>\[딥링크]에 딥링크 정보를 등록해주세요.

  **iOS URI 스킴**

  딥링크에 사용할 스킴을 입력해주세요. 에어브릿지는 입력한 스킴을 사용하는 딥링크만 트래킹링크에 설정할 수 있고, 트래킹링크로 앱이 열릴 때 설정한 스킴 딥링크가 전달됩니다. 예: `scheme://`

  **iOS 앱 ID**

  [애플 개발자 대시보드](https://developer.apple.com/account/resources)의 앱의 \[Identifier]에서 `App ID Prefix` , `Bundle ID` 값을 가져와서 `App ID Prefix` + . + `Bundle ID` 형식으로 입력해주세요. 예: `9JA89QQLNQ.com.apple.wwdc`

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

    실제 출시 앱과 개발용 앱의 iOS URI 스킴과 iOS 앱 ID를 다르게 등록해야 유저를 정상적으로 이동 시킬 수 있습니다.
  </Danger>
</Accordion>

에어브릿지에 딥링크 정보를 등록한 후에 앱에 딥링크를 설정해야 합니다. 앱에서 딥링크를 위해 필요한 개발은 아래와 같습니다.

* 에어브릿지 딥링크로 앱이 실행되도록 설정합니다.
* 에어브릿지 딥링크로 유저를 이동시킵니다.

아래 내용을 참고해 주세요.

<AccordionGroup>
  <Accordion title="에어브릿지 딥링크로 앱이 실행되도록 설정하기">
    유저가 트래킹 링크를 클릭한 후에 앱이 에어브릿지 딥링크로 실행되도록 설정합니다.

    **스킴 딥링크 앱 설정**

    1. Xcode에서 \[YOUR\_PROJECT]>\[Info]>\[URL Types]로 이동합니다.
    2. '+'를 클릭한 후에 URL Schemes에 대시보드에서 입력한 iOS URI 스킴을 입력합니다.

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

      `://`를 제외한 iOS URL 스킴을 입력해야 합니다.
    </Danger>

    **유니버셜 링크 앱 설정**

    1. Xcode에서 \[YOUR\_PROJECT]>\[Signing & Capabilities]로 이동합니다.
    2. '+ Capability'를 클릭하면 Associated Domains를 추가할 수 있습니다.
    3. Associated Domains에 `applinks:YOUR_APP_NAME.airbridge.io`와 `applinks:YOUR_APP_NAME.abr.ge` 를 추가합니다. (`YOUR_APP_NAME` 은 에어브릿지 대시보드의 \[설정]>\[토큰 관리]에서 확인할 수 있습니다.)

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

      [Password AutoFill](https://developer.apple.com/documentation/security/password-autofill) 기능을 사용하고 있거나 사용할 계획이 있다면 Webcredentials 도메인을 반드시 추가해야 합니다. Password AutoFill 기능으로 저장된 암호의 도메인이 `airbridge.io` 또는 `abr.ge`로 보이는 현상이 앱을 사용하는 유저에게 발생할 수 있습니다.
    </Danger>
  </Accordion>

  <Accordion title="에어브릿지 딥링크로 유저를 이동시키기">
    앱이 딥링크로 열릴 때, `trackDeeplink` 함수를 호출해 SDK가 딥링크 오픈 이벤트를 수집할 수 있게 해주세요. 그리고 `handleDeeplink` 함수를 호출해 에어브릿지 딥링크를 원래 트래킹링크에 설정된 스킴 딥링크로 변환해주세요. 그리고 유저를 의도된 화면으로 이동시켜주세요.

    앱이 에어브릿지 딥링크로 열리면 `isAirbridgeDeeplink` 는 `true` 가 되고, 콜백의 `uri` 에는 설정된 스킴 딥링크가 전달됩니다. 앱이 다른 딥링크로 열리면 `isAirbridgeDeeplink` 는 `false` 가 되고, 콜백은 호출되지 않습니다. 이를 활용하면 에어브릿지 딥링크를 별도로 처리할 수 있습니다.

    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      import Airbridge
      ...
      /** when app is opened with deeplink */

      // track deeplink
      Airbridge.trackDeeplink(url: url)
      // handle deeplink
      var isAirbridgeDeeplink = Airbridge.handleDeeplink(url: url) { url in
          // when app is opened with airbridge deeplink
          // show proper content using url (YOUR_SCHEME://...)
          handleAirbridgeDeeplink(url: url)
      }
      if isAirbridgeDeeplink { return }
      // when app is opened with other deeplink
      // use existing logic as it is
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      #import <Airbridge/Airbridge.h>
      ...
      /** when app is opened with deeplink */

      // track deeplink
      [Airbridge trackDeeplinkWithUrl:url];
      // handle deeplink
      BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
          // when app is opened with airbridge deeplink
          // show proper content using url (YOUR_SCHEME://...)
      }];
      if (isAirbridgeDeeplink) { return; }
      // when app is opened with other deeplink
      // use existing logic as it is
      ```
    </CodeGroup>

    앱이 딥링크로 열릴 때마다 `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 유저를 의도한 화면으로 이동시켜주세요.

    SceneDelegate와 AppDelegate가 모두 있다면 SceneDelegate 클래스에, AppDelegate만 있다면 AppDelegate 클래스에, 모두 없고 SwiftUI를 사용한다면 App 클래스에 아래와 같은 콜백 설정이 필요합니다.

    <Tabs>
      <Tab title="SceneDelegate (Swift)">
        앱이 딥링크로 열릴 때 SceneDelegate 클래스에서 호출되는 콜백은 아래와 같습니다.

        | 앱이 딥링크로 열리는 상황                          | 콜백                             |
        | --------------------------------------- | ------------------------------ |
        | 앱이 꺼진 상태에서 `URL 스킴` 또는 `유니버셜 링크` 로 열릴 때 | `scene:willConnectTo:options:` |
        | 앱이 백그라운드에 있는 상태에서 `URL 스킴` 으로 열릴 때      | `scene:openURLContexts:`       |
        | 앱이 백그라운드에 있는 상태에서 `유니버셜 링크` 로 열릴 때      | `scene:continue:`              |

        1. 앱이 에어브릿지 딥링크로 열렸을 때 유저를 이동시키는 함수를 구현하세요. 이는 유저를 의도한 화면으로 이동키시기 위해 각각의 콜백에 추가해야하는 함수입니다.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
            ...
            // when app is opened with airbridge deeplink
            func handleAirbridgeDeeplink(url: URL) {
                // show proper content using url (YOUR_SCHEME://...)
            }
            ...
        }
        ```

        2. `scene:willConnectTo:options:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
            ...
            // when terminated app is opened with scheme deeplink or universal links
            func scene(
                _ scene: UIScene,
                willConnectTo session: UISceneSession,
                options connectionOptions: UIScene.ConnectionOptions
            ) {
                // track deeplink
                Airbridge.trackDeeplink(connectionOptions: connectionOptions)
                // handle deeplink

                var isAirbridgeDeeplink = Airbridge.handleDeeplink(connectionOptions: connectionOptions)
                    // when app is opened with airbridge deeplink
                    // show proper content using url (YOUR_SCHEME://...)
                    handleAirbridgeDeeplink(url: url)
                }
                
                if isAirbridgeDeeplink { return }
                // when app is opened with other deeplink
                // use existing logic as it is
            }
            ...
        }
        ```

        3. `scene:openURLContexts:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
            ...
            // when backgrounded app is opened with scheme deeplink
            func scene(
                _ scene: UIScene,
                openURLContexts URLContexts: Set<UIOpenURLContext>
            ) {
                // track deeplink
                Airbridge.trackDeeplink(openURLContexts: openURLContexts)
                // handle deeplink

                var isAirbridgeDeeplink = Airbridge.handleDeeplink(openURLContexts: openURLContexts) { url in
                    // when app is opened with airbridge deeplink
                    // show proper content using url (YOUR_SCHEME://...)
                    handleAirbridgeDeeplink(url: url)
                }
                
                if isAirbridgeDeeplink { return }
                // when app is opened with other deeplink
                // use existing logic as it is
            }
            ...
        }
        ```

        4. `scene:continue:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class SceneDelegate: UIResponder, UIWindowSceneDelegate {
            ...
            // when backgrounded app is opened with universal links
            func scene(
                _ scene: UIScene,
                continue userActivity: NSUserActivity
            ) {
                // track deeplink
                Airbridge.trackDeeplink(userActivity: userActivity)
                // handle deeplink
                var isAirbridgeDeeplink = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                    // when app is opened with airbridge deeplink
                    // show proper content using url (YOUR_SCHEME://...)
                    handleAirbridgeDeeplink(url: url)
                }
                if isAirbridgeDeeplink { return }
                // when app is opened with other deeplink
                // use existing logic as it is
            }
            ...
        }
        ```
      </Tab>

      <Tab title="AppDelegate (Swift)">
        앱이 딥링크로 열릴 때 AppDelegate 클래스에서 호출되는 콜백은 아래와 같습니다.

        | 앱이 딥링크로 열리는 상황                          | 콜백                                         |
        | --------------------------------------- | ------------------------------------------ |
        | 앱이 꺼지거나 백그라운드에 있는 상태에서 `URL 스킴` 으로 열릴 때 | `application:open:options:`                |
        | 앱이 꺼지거나 백그라운드에 있는 상태에서 `유니버셜 링크` 로 열릴 때 | `application:continue:restorationHandler:` |

        1. 앱이 에어브릿지 딥링크로 열렸을 때 유저를 이동시키는 함수를 구현하세요. 이는 유저를 의도한 화면으로 이동키시기 위해 각각의 콜백에 추가해야하는 함수입니다.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class AppDelegate: UIResponder, UIApplicationDelegate {
            ...
            // when app is opened with airbridge deeplink
            func handleAirbridgeDeeplink(url: URL) {
                // show proper content using url (YOUR_SCHEME://...)
            }
            ...
        }
        ```

        2. `application:open:options:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class AppDelegate: UIResponder, UIApplicationDelegate {
            ...
            // 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 deeplink
                var isAirbridgeDeeplink = Airbridge.handleDeeplink(url: url) { url in
                    // when app is opened with airbridge deeplink
                    // show proper content using url (YOUR_SCHEME://...)
                    handleAirbridgeDeeplink(url: url)
                }
                
                if isAirbridgeDeeplink { return true }
                // when app is opened with other deeplink
                // use existing logic as it is
                return isAirbridgeDeeplink
            }
            ...
        }
        ```

        3. `application:continue:restorationHandler:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        import UIKit
        import Airbridge
        ...
        class AppDelegate: UIResponder, UIApplicationDelegate {
            ...
            // 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 deeplink
                var isAirbridgeDeeplink = Airbridge.handleDeeplink(userActivity: userActivity) { url in
                    // when app is opened with airbridge deeplink
                    // show proper content using url (YOUR_SCHEME://...)
                    handleAirbridgeDeeplink(url: url)
                }
                if isAirbridgeDeeplink { return true }
                // when app is opened with other deeplink
                // use existing logic as it is
                return isAirbridgeDeeplink
            }
            ...
        }
        ```
      </Tab>

      <Tab title="SwiftUI (Swift)">
        앱이 딥링크로 열릴 때 App 클래스에서 호출되는 콜백은 아래와 같습니다.

        | 앱이 딥링크로 열리는 상황                                          | 콜백          |
        | ------------------------------------------------------- | ----------- |
        | 앱이 꺼지거나 백그라운드에 있는 상태에서 `URL Scheme` 또는 `유니버셜 링크` 로 열릴 때 | `onOpenURL` |

        1. `onOpenURL` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```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 deeplink
                            var isAirbridgeDeeplink = Airbridge.handleDeeplink(url: url) { url in
                                // when app is opened with airbridge deeplink
                                // show proper content using url (YOUR_SCHEME://...)
                            }
                            if isAirbridgeDeeplink { return }
                            // when app is opened with other deeplink
                            // use existing logic as it is
                        }
                }
            }
        }
        ```
      </Tab>

      <Tab title="SceneDelegate (Objective-C)">
        앱이 딥링크로 열릴 때 SceneDelegate 클래스에서 호출되는 콜백은 아래와 같습니다.

        | 앱이 딥링크로 열리는 상황                          | 콜백                                    |
        | --------------------------------------- | ------------------------------------- |
        | 앱이 꺼진 상태에서 `URL 스킴` 또는 `유니버셜 링크` 로 열릴 때 | `scene:willConnectToSession:options:` |
        | 앱이 백그라운드에 있는 상태에서 `URL 스킴` 으로 열릴 때      | `scene:openURLContexts:`              |
        | 앱이 백그라운드에 있는 상태에서 `유니버셜 링크` 로 열릴 때      | `scene:continueUserActivity:`         |

        1. 앱이 에어브릿지 딥링크로 열렸을 때 유저를 이동시키는 함수를 구현하세요. 이는 유저를 의도한 화면으로 이동키시기 위해 각각의 콜백에 추가해야하는 함수입니다.

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

        @interface SceneDelegate ()

        @end

        @implementation SceneDelegate
        ...
        // when app is opened with airbridge deeplink
        - (void)handleAirbridgeDeeplink:(NSURL *)url {
            // show proper content using url (YOUR_SCHEME://...)
        }
        ...
        @end
        ```

        2. `scene:willConnectToSession:options:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```objective-c lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        #import "SceneDelegate.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 {
            // track deeplink
            [Airbridge trackDeeplinkWithConnectionOptions:connectionOptions];
            // handle deeplink
            BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithConnectionOptions:connectionOptions onSuccess:^(NSURL* url) {
                // when app is opened with airbridge deeplink
                // show proper content using url (YOUR_SCHEME://...)
                [self handleAirbridgeDeeplink:url];
            }];
            if (isAirbridgeDeeplink) { return; }
            // when app is opened with other deeplink
            // use existing logic as it is
        }
        ...
        @end
        ```

        3. `scene:openURLContexts:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

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

        @interface SceneDelegate ()

        @end

        @implementation SceneDelegate
        ...
        // when backgrounded app is opened with scheme deeplink
        - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
            // track deeplink
            [Airbridge trackDeeplinkWithOpenURLContexts:URLContexts];
            // handle deeplink
            BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithOpenURLContexts:URLContexts onSuccess:^(NSURL* url) {
                // when app is opened with airbridge deeplink
                // show proper content using url (YOUR_SCHEME://...)
                [self handleAirbridgeDeeplink:url];
            }];
            if (isAirbridgeDeeplink) { return; }
            // when app is opened with other deeplink
            // use existing logic as it is
        }
        ...
        @end
        ```

        4. `scene:continueUserActivity:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

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

        @interface SceneDelegate ()

        @end

        @implementation SceneDelegate
        ...
        // when backgrounded app is opened with universal links
        - (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
            // track deeplink
            [Airbridge trackDeeplinkWithUserActivity:userActivity];
            // handle deeplink
            BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
                // when app is opened with airbridge deeplink
                // show proper content using url (YOUR_SCHEME://...)
                [self handleAirbridgeDeeplink:url];
            }];
            if (isAirbridgeDeeplink) { return; }
            // when app is opened with other deeplink
            // use existing logic as it is
        }
        ...
        @end
        ```
      </Tab>

      <Tab title="AppDelegate (Objective-C)">
        앱이 딥링크로 열릴 때 AppDelegate 클래스에서 호출되는 콜백은 아래와 같습니다.

        | 앱이 딥링크로 열리는 상황                          | 콜백                                                     |
        | --------------------------------------- | ------------------------------------------------------ |
        | 앱이 꺼지거나 백그라운드에 있는 상태에서 `URL 스킴` 으로 열릴 때 | `application:openURL:options:`                         |
        | 앱이 꺼지거나 백그라운드에 있는 상태에서 `유니버셜 링크` 로 열릴 때 | `application:continueUserActivity:restorationHandler:` |

        1. 앱이 에어브릿지 딥링크로 열렸을 때 유저를 이동시키는 함수를 구현하세요. 이는 유저를 의도한 화면으로 이동키시기 위해 각각의 콜백에 추가해야하는 함수입니다.

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

        @interface AppDelegate ()

        @end

        @implementation AppDelegate
        ...
        // when app is opened with airbridge deeplink
        - (void)handleAirbridgeDeeplink:(NSURL *)url {
            // show proper content using url (YOUR_SCHEME://...)
        }
        ...
        @end
        ```

        2. `application:openURL:options:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

        ```objective-c lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
        #import "AppDelegate.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 deeplink
            BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithUrl:url onSuccess:^(NSURL* url) {
                // when app is opened with airbridge deeplink
                // show proper content using url (YOUR_SCHEME://...)
                [self handleAirbridgeDeeplink:url];
            }];
            if (isAirbridgeDeeplink) { return; }
            // when app is opened with other deeplink
            // use existing logic as it is
            return isAirbridgeDeeplink;
        }
        ...
        @end
        ```

        3. `application:continueUserActivity:restorationHandler:` 콜백을 설정하세요. `trackDeeplink` 함수와 `handleDeeplink` 함수를 호출하여 딥링크 오픈 이벤트를 수집하고 위에서 구현한 함수를 호출하여 유저를 이동시키세요.

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

        @interface AppDelegate ()

        @end

        @implementation AppDelegate
        ...
        // 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 deeplink
            BOOL isAirbridgeDeeplink = [Airbridge handleDeeplinkWithUserActivity:userActivity onSuccess:^(NSURL* url) {
                // when app is opened with airbridge deeplink
                // show proper content using url (YOUR_SCHEME://...)
                [self handleAirbridgeDeeplink:url];
            }];
            if (isAirbridgeDeeplink) { return YES; }
            // when app is opened with other deeplink
            // use existing logic as it is
            return isAirbridgeDeeplink;
        }
        ...
        @end
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### 디퍼드 딥링크 설정하기

앱이 설치되지 않은 상태에서 디퍼드 딥링크를 설정한 트래킹 링크를 클릭하면 에어브릿지 딥링크를 저장합니다. 디퍼드 딥링크를 설정하면 에어브릿지 SDK는 아래와 같은 방식으로 딥링크를 획득합니다.

<Accordion title="에어브릿지 SDK의 디퍼드 딥링크 획득 방식">
  에어브릿지 SDK는 SDK 초기화 이후에 아래 조건을 모두 만족하면 딥링크 획득을 시도합니다. 획득 도중에 앱이 종료되면 에어브릿지 SDK는 저장된 에어브릿지 딥링크는 없는 것으로 처리됩니다.

  * 옵트인(Opt-In)을 설정한 상태에서  `Airbridge.startTracking` 함수를 호출합니다. 또는 옵트인을 설정하지 않았습니다.
  * ATT 추적 동의 여부가 결정되었습니다. 또는 ATT 프롬프트에서 설정한 이벤트 수집 지연 시간이 종료되었습니다.
</Accordion>

`Airbridge.handleDeferredDeeplink` 함수는 저장된 에어브릿지 딥링크를 획득한 후에 스킴 딥링크로 변환해 앱에 전달합니다. 변환된 스킴 딥링크를 활용해 유저를 설정한 목적지로 보냅니다.

<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 isFirstCalled = Airbridge.handleDeferredDeeplink() { url in
      // when handleDeferredDeeplink is called firstly after install
      if let url {
          // show proper content using url (YOUR_SCHEME://...)
      }
  }
  ```

  ```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];
  ...
  BOOL isFirstCalled = [Airbridge handleDeferredDeeplinkOnSuccess:^(NSURL* url) {
      // when handleDeferredDeeplink is called firstly after install
      if (url != nil) {
          // show proper content using url (YOUR_SCHEME://...)
      }
  }];
  ```
</CodeGroup>

`Airbridge.handleDeferredDeeplink` 함수는 앱이 설치되고 처음으로 호출되었으면 true를 반환하고, 에어브릿지 딥링크 획득을 기다려 스킴 딥링크로 변환해 onSuccess로 전달합니다. 해당 스킴 딥링크를 활용해 유저를 설정한 목적지로 보낼 수 있습니다.

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

전달되는 스킴 딥링크는 일반적으로 `YOUR_SCHEME://...` 형태의 URL입니다. 메타 디퍼드 앱 링크(Meta Deferred App Links) 같은 서비스를 이용하면 다른 형태의 URL이 전달될 수 있습니다.

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

  앱이 딥링크로 열리면 에어브릿지는 디퍼드딥링크 유무에 관계없이 null을 onSuccess에 전달해서 딥링크만 처리되도록 합니다.
</Danger>

## 테스트하기

SDK 작동 테스트와 딥링크 테스트로 정상적으로 에어브릿지 SDK와 딥링크가 작동하는지 확인할 수 있습니다.

### SDK 작동 테스트하기

설치한 에어브릿지 iOS SDK가 정상적으로 작동하는지 확인해 주세요. 앱 설치 이벤트는 추가 설정 여부와 관계없이 iOS SDK에 수집됩니다.

#### 앱 설치 이벤트 수집 여부 확인하기

앱 설치 이벤트가 iOS SDK로 수집되는지 확인해 주세요. 앱 설치 이벤트는 항상 수집됩니다.

1. 앱을 설치하지 않은 테스트 디바이스를 준비합니다. 또는 테스트하기 전에 앱을 삭제해 주세요.
2. SDK 로그 레벨을 `debug`로 설정합니다.

```swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
let option = AirbridgeOptionBuilder(name: "YOUR_APP_NAME", token: "YOUR_APP_SDK_TOKEN")
    .setLogLevel(.debug)
    .build()
Airbridge.initializeSDK(option: option)
```

3. 테스트 디바이스에 앱을 설치합니다. 앱을 설치한 이후 실행을 해야 앱 설치 이벤트가 수집됩니다. 앱을 실행해 주세요.

에어브릿지에서 처음 수집된 실행(Open) 이벤트는 Install로 기록됩니다. 따라서 앱 설치 이벤트가 수집되면 Open은 기록되지 않습니다.

4. Xcode의 Console에서 테스트 디바이스의 IDFA로 발생한 이벤트의 로그를 확인합니다. Console Filter에 `Library:Airbridge`를 입력합니다. 앱 설치 이벤트가 정상적으로 수집되고 있다면 로그를 아래처럼 확인할 수 있습니다.
   * `Send event packets to Airbridge: categories=9161`
   * `Send event packets to Airbridge: categories=9163`

Xcode Console 메시지의 의미는 아래를 참고해 주세요.

<Accordion title="Xcode Console 메세지 의미">
  * `Event packet is stored in storage: categories={event_category}`: Event category가 단말에서 적재됐습니다.
  * `Send event packets to Airbridge: categories={event_category}`: Event category를 전송합니다.
  * `Client receive response: method=post url=https://event-track.airbridge.io/v1/apps/{app_name}`: 네트워크를 통해 성공적으로 전송됐습니다.
</Accordion>

5. 충분한 시간이 지나도 Xcode의 Console에서 로그가 나타나지 않는다면 SDK 초기화 여부 또는 설정, 네트워크 상태 등을 확인해 주세요.

앱 설치 이벤트가 확인되지 않는 상황이 반복된다면 SDK 로그와 함께 [문의하기](https://app.airbridge.io/supports)를 통해 요청해 주세요.

### 딥링크 테스트하기

에어브릿지 대시보드 \[설정]>\[테스트 콘솔]의 \[딥링킹] 탭에서 딥링킹이 정상적으로 작동하는지 테스트할 수 있습니다.

#### 사전 확인사항

딥링크를 테스트하기 전에 아래 사항을 설정했는지 먼저 확인해 주세요.

| <span style={{ display: 'inline-block', minWidth: '120px' }} /> | <span style={{ display: 'inline-block', minWidth: '240px' }}>설명</span>                                                           | <span style={{ display: 'inline-block', minWidth: '140px' }}>가이드</span>                                            |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| 유니버셜 링크 설정                                                      | - 필수로 설정해 주세요.                                                                                                                   | - [대시보드 설정](/ko/guides/retargeting-with-deep-links)<br />- [딥링크 설정하기](/ko/deeplink-developers/ios-sdk-v4#딥링크-설정하기) |
| 스킴 딥링크 설정                                                       | - 필수로 설정해 주세요.                                                                                                                   | - [대시보드 설정](/ko/guides/retargeting-with-deep-links)<br />- [딥링크 설정하기](/ko/deeplink-developers/ios-sdk-v4#딥링크-설정하기) |
| 디퍼드 딥링크 설정                                                      | - 자동으로 설정되기 때문에 추가 설정이 필요하지 않습니다.                                                                                                | - [디퍼드 딥링크 설정하기](/ko/deeplink-developers/ios-sdk-v4#디퍼드-딥링크-설정하기)                                                  |
| 커스텀 도메인 설정                                                      | - 필요하다면 선택적으로 설정해 주세요.                                                                                                           | - [대시보드 설정](/ko/guides/custom-domain)                                                                              |
| 앱 설치                                                            | - 디퍼드 딥링크를 테스트하지 않는다면 미리 앱을 테스트 디바이스에 설치해 주세요.<br />- 디퍼드 딥링크를 테스트한다면 테스트 디바이스에 앱이 설치되지 않아야 합니다. 앱이 설치됐다면 테스트 디바이스에서 앱을 삭제해 주세요. |                                                                                                                    |

#### 테스트 준비하기

테스트를 시작하는 데 필요한 딥링크 정보와 앱 정보가 모두 등록됐는지 확인합니다. 딥링크 정보와 앱 정보가 모두 등록된 상태라면 이 단계는 대시보드에 나타나지 않습니다. 바로 다음 단계인 테스트 진행하기를 참고해 주세요.

##### 딥링크 정보 등록

딥링킹을 테스트하려면 최소 1개 운영체제의 딥링크 정보가 모두 등록되어 있어야 합니다. 운영체제가 요구하는 정보들과 각각의 등록 상태를 확인하세요. 보완할 정보가 있다면 \[설정하러 가기] 버튼을 클릭해 \[트래킹 링크]>\[딥링크] 메뉴에서 해당 정보를 등록해 주세요. 자세한 방법은 [에어브릿지 가이드](/ko/guides/retargeting-with-deep-links#에어브릿지에-딥링크-정보-등록하기)를 참고하세요.

<Note>
  **최신 상태를 보려면 새로고침 하세요**

  다른 브라우저 탭에서 설정을 마치고 다시 대시보드 탭으로 돌아오면 새로고침을 해주세요. 그래야 각 정보의 등록 상태가 최신으로 반영됩니다.
</Note>

##### 앱 정보 등록

딥링킹이 작동할 때 앱을 설치하지 않은 유저를 보낼 폴백 경로가 미리 설정되어 있어야 합니다. \[설정하러 가기] 버튼을 클릭해 \[설정]>\[에어브릿지 앱 설정]>\[서비스] 항목에 운영체제별 앱 또는 웹사이트 정보를 등록해 주세요. 자세한 방법은 [에어브릿지 가이드](/ko/guides/retargeting-with-deep-links#%ED%8F%B4%EB%B0%B1-%EA%B2%BD%EB%A1%9C-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0)를 참고하세요.

##### 테스트용 딥링크 입력

테스트 할 앱에 사용 중인 URL 스킴 형태의 딥링크를 입력하세요. 홈 화면이나 전체 목록보다는 특정한 상세페이지의 주소로 테스트할 것을 권장합니다.

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

  딥링크를 입력하기 전에 반드시 인코딩해 주세요. 인코딩하지 않으면 URL 표준 형식에 맞지 않아 딥링킹이 정상 작동하지 않을 수 있습니다.
</Danger>

오른쪽에 있는 양방향 화살표 아이콘을 클릭해 입력 방식을 변경하면 직접 패쓰(path)와 파라미터를 추가해서 딥링크를 입력할 수 있습니다.

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/Z47Ur28bRajj9qGT/asset/image/deep-link-test-path-parameters-ko.png?fit=max&auto=format&n=Z47Ur28bRajj9qGT&q=85&s=f61f1416bee59040e0f196a18ab8acd1" alt="2009-DeepLinkingTest-KR-01" width="1400" height="800" data-path="asset/image/deep-link-test-path-parameters-ko.png" />
</Frame>

##### 테스트 가능 여부 확인

운영체제별로 테스트를 시작하는 데 필요한 조건을 모두 충족했는지 확인하세요. 모든 조건을 충족한 운영체제는 \[테스트 가능]으로 표시되고, 그렇지 않은 운영체제는 \[조건 미충족]으로 표시됩니다. 각 운영체제 옆에 있는 툴팁을 클릭하면 필요한 정보들과 각각의 등록 상태를 확인할 수 있습니다. \[조건 미충족]인 경우 ‘설정하러 가기’ 버튼을 클릭해 부족한 정보를 보완하거나 잘못된 정보를 바로잡아 주세요.

<Note>
  **최신 상태를 보려면 새로고침 하세요**

  다른 브라우저 탭에서 설정을 마치고 다시 대시보드 탭으로 돌아오면 새로고침을 해주세요. 그래야 각 정보의 등록 상태가 최신으로 반영됩니다.
</Note>

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/Z47Ur28bRajj9qGT/asset/image/deep-link-test-ios-requirements-ko.png?fit=max&auto=format&n=Z47Ur28bRajj9qGT&q=85&s=beeb1d03d252ae38129216d169f1b682" alt="2009-DeepLinkingTest-KR-02" width="1400" height="800" data-path="asset/image/deep-link-test-ios-requirements-ko.png" />
</Frame>

#### 테스트 진행하기

테스트 케이스는 크게 \[앱 설치 유저 케이스]와 \[앱 미설치 유저 케이스]로 나뉘며 총 4개의 테스트가 제공됩니다. 각 테스트는 딥링킹 작동에 필요한 항목들을 단계별로 검토하며, 모든 테스트가 성공적으로 완료되어야 딥링킹의 정상 작동을 기대할 수 있습니다. 트래킹 링크 생성 시 커스텀 도메인을 적용했다면 4개 테스트, 커스텀 도메인을 적용하지 않았다면 해당 테스트를 제외한 3개 테스트를 진행해 주세요.

<Note>
  **왜 테스트가 여러 종류인가요?**

  에어브릿지는 URL 스킴 딥링크, 유니버설 링크, 앱 링크 등 다양한 딥링킹 방식을 지원하며, 앱이 실행될 때 운영체제, 브라우저, 앱 설치 여부 등에 따라 이 중 가장 적합한 방식으로 딥링킹 됩니다. 다양한 상황에서 유저를 문제 없이 의도한 상세페이지로 이동시키려면 모든 테스트를 진행하세요.
</Note>

##### 앱 설치 유저 케이스 테스트

유저가 이미 앱을 설치한 상태에서 딥링크로 이동하는 케이스에 관한 테스트입니다. URL 스킴 딥링크로 작동하는 경우, 유니버설 링크 또는 앱 링크로 작동하는 경우, 트래킹 링크 생성 시 커스텀 도메인을 적용한 경우 등 3개의 테스트가 제공됩니다.

###### 사전 준비사항

테스트를 시작하기 전에 아래 사항을 모두 확인해 주세요.

1. 테스트용 모바일 디바이스를 준비하세요.
2. 디바이스에 앱이 설치되어 있는지 확인하세요. 설치되지 않았다면 앱을 설치하세요.
3. 디바이스에 설치된 앱을 최소 1번 이상 실행했다 닫아주세요.
4. 디바이스의 기본 브라우저가 크롬 또는 사파리로 설정되어 있는지 확인하세요. 다른 브라우저에서는 테스트가 정상적으로 완료되지 않을 수 있습니다.
5. 테스트 도중 변동이 없도록 안정적인 네트워크 환경에서 시작하세요.

<Info>
  **알립니다**

  딥링크 설정에 문제가 없고 딥링킹 테스트가 성공적으로 완료됐다면 에어브릿지 딥링킹은 대부분의 브라우저에서 작동합니다. 딥링킹 테스트만 크롬과 사파리 브라우저에서 지원됩니다.
</Info>

###### 테스트 방법

1. 진행할 테스트를 클릭하세요.
2. 디바이스의 카메라로 QR 코드를 스캔해 테스트 페이지로 이동하세요. QR 코드를 스캔할 수 없는 경우 QR 코드 아래에 있는 URL을 활용하세요.
3. QR 코드 스캔 후 디바이스에 나타난 화면에서 ‘딥링크 실행’ 버튼을 클릭하면 아래 5개 항목을 순서대로 검토합니다. 각 항목에 문제가 없으면 자동으로 다음 항목을 검토하기 시작합니다. 문제가 있으면 제공된 안내와 에어브릿지 가이드를 참고해 문제를 해결해 주세요. 그리고 해당 테스트를 처음부터 다시 진행해 주세요.

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/Z47Ur28bRajj9qGT/asset/image/deep-link-essential-test-success-ko.png?fit=max&auto=format&n=Z47Ur28bRajj9qGT&q=85&s=777b4d3ed595b89407aa97167e1ea684" alt="2009-DeepLinkingTest-KR-05" width="1400" height="800" data-path="asset/image/deep-link-essential-test-success-ko.png" />
</Frame>

4. 모든 항목의 검토가 성공적으로 끝나면 딥링크 실행 이벤트를 에어브릿지 대시보드 \[원본 데이터]>\[앱 이벤트 실시간 로그]에서 확인할 수 있습니다.

<AccordionGroup>
  <Accordion title="필수 설정 확인 1">
    필수 설정 1 버튼을 클릭해서 테스트를 완료하면 SDK 로그에서 아래 항목을 확인할 수 있습니다.

    * `eventData.deeplink`가 입력한 딥링크 `{YOUR_SCHEME}://...` 입니다.
    * 입력한 딥링크 `{YOUR_SCHEME}://...` 가 딥링크 콜백 함수에 전달됩니다.
  </Accordion>

  <Accordion title="필수 설정 확인 2">
    필수 설정 2 버튼을 클릭해서 테스트를 완료하면 SDK 로그에서 아래 항목을 확인할 수 있습니다.

    * `eventData.deeplink`가 `https://{YOUR_APP_NAME}.airbridge.io...` 입니다.
    * 입력한 딥링크 `{YOUR_SCHEME}://...` 가 딥링크 콜백 함수에 전달됩니다.
  </Accordion>

  <Accordion title="커스텀 도메인 설정 확인">
    커스텀 도메인 설정 버튼을 클릭해서 테스트를 완료하면 SDK 로그에서 아래 항목을 확인할 수 있습니다.

    * `eventData.deeplink`가 `https://{YOUR_CUSTOM_DOMAIN}...` 입니다.
    * 입력한 딥링크 `{YOUR_SCHEME}://...` 가 딥링크 콜백 함수에 전달됩니다.
  </Accordion>
</AccordionGroup>

5. 테스트 콘솔 탭으로 돌아온 후 ‘완료’ 버튼을 클릭해 해당 테스트 창을 닫아주세요.

##### 앱 미설치 유저 케이스 테스트

유저가 아직 앱을 설치하지 않은 상태에서 딥링크로 이동하는 케이스에 관한 테스트입니다. 디퍼드 딥링크 작동을 확인하는 1개의 테스트가 제공됩니다.

###### 사전 준비사항

테스트를 시작하기 전에 아래 사항을 모두 확인해 주세요.

1. 테스트용 모바일 디바이스를 준비하세요.
2. 디바이스에 앱이 설치되지 않은 상태인지 확인하고, 설치되어 있다면 앱을 삭제하세요.
3. 디바이스의 기본 브라우저가 크롬 또는 사파리로 설정되어 있는지 확인하세요. 다른 브라우저에서는 딥링킹이 정상 작동하지 않을 수 있습니다.
4. 테스트 도중 변동이 없도록 안정적인 네트워크 환경에서 시작하세요.

###### 테스트 방법

1. 진행할 테스트를 클릭하세요.
2. 디바이스의 카메라로 QR 코드를 스캔해 테스트 페이지로 이동하세요. QR 코드를 스캔할 수 없는 경우 QR 코드 아래에 있는 URL을 활용하세요.
3. QR 코드 스캔 후 디바이스에 나타난 화면에서 ‘딥링크 실행’ 버튼을 클릭하면 아래 3개 항목을 순서대로 검토합니다. 각 항목에 문제가 없으면 자동으로 다음 항목을 검토하기 시작합니다. 문제가 있으면 제공된 안내와 에어브릿지 가이드를 참고해 문제를 해결해 주세요.

<Frame>
  <img src="https://mintcdn.com/airbridge-help-center/Z47Ur28bRajj9qGT/asset/image/deep-link-deferred-navigation-ko.png?fit=max&auto=format&n=Z47Ur28bRajj9qGT&q=85&s=4199e0cbae240be324d3d7ba91dae83c" alt="2009-DeepLinkingTest-KR-06" width="1400" height="800" data-path="asset/image/deep-link-deferred-navigation-ko.png" />
</Frame>

4. 모든 항목의 검토가 성공적으로 끝나면 딥링크 실행 이벤트를 에어브릿지 대시보드 \[원본 데이터]>\[앱 이벤트 실시간 로그]에서 확인할 수 있습니다.

<Accordion title="디퍼드 딥링크 설정 확인">
  디퍼드 딥링크 설정 확인 버튼을 클릭해서 테스트를 완료하면 SDK 로그에서 아래 항목을 확인할 수 있습니다.

  * `eventData.deeplink`가 입력한 딥링크 `{YOUR_SCHEME}://...` 입니다.
  * 입력한 딥링크 `{YOUR_SCHEME}://...` 가 디퍼드 딥링크 콜백 함수에 전달됩니다.
</Accordion>

5. 테스트 콘솔 탭으로 돌아온 후 ‘완료’ 버튼을 클릭해 해당 테스트 창을 닫아주세요.

#### 문제 해결하기

아래를 참고해 문제를 해결할 수 있습니다.

| 문제 상황                                                   | 해결 방법                                                 |
| ------------------------------------------------------- | ----------------------------------------------------- |
| 딥링크를 클릭했지만, 앱이 실행되지 않습니다. 또는 설정과 다른 내용이 SDK 로그에서 확인됩니다. | 딥링크를 정상적으로 설정했는지 확인해 주세요.                             |
| 딥링크를 클릭한 후에 앱이 실행됐지만, 설정한 앱 페이지로 이동하지 않습니다.             | `onSuccess` 함수로 전달된 딥링크 경로에 따라 유저가 이동하도록 직접 구현해야 합니다. |

## 추가 설정하기

iOS SDK를 추가로 설정할 수 있습니다.

<Info>
  **알립니다**

  필수 설정 기능이 아닙니다. 필요한 경우에만 설정해 주세요.
</Info>

### 인앱에서 트래킹 링크 생성하기

<Info>
  **알립니다**

  에어브릿지 iOS SDK 4.3.0 이상이 필요합니다.
</Info>

트래킹 링크는 유저가 발생시킨 터치포인트 데이터를 에어브릿지에 전달하기 위해 만드는 링크입니다.

트래킹 링크를 활용하면 광고를 보거나 클릭한 유저를 원하는 목적지로 보낼 수 있습니다. 에어브릿지는 트래킹 링크로 수집한 터치포인트 데이터를 활용해 전환에 기여한 채널을 분석할 수 있습니다.

트래킹 링크 생성을 하기 위해서는 `createTrackingLink` 함수를 사용합니다. 파라미터의 필수 여부와 타입은 아래와 같습니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  public static func createTrackingLink(
      channel: String,
      option: [String: Any],
      onSuccess: @escaping (AirbridgeTrackingLink) -> Void
  )

  public static func createTrackingLink(
      channel: String,
      option: [String: Any],
      onSuccess: @escaping (AirbridgeTrackingLink) -> Void,
      onFailure: @escaping (Error) -> Void
  )
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  + (void)createTrackingLinkWithChannel:(NSString*)channel
                                 option:(NSDictionary<NSString*, id>*)option
                              onSuccess:(void (^)(AirbridgeTrackingLink*))onSuccess;
  + (void)createTrackingLinkWithChannel:(NSString*)channel
                                 option:(NSDictionary<NSString*, id>*)option
                              onSuccess:(void (^)(AirbridgeTrackingLink*))onSuccess
                              onFailure:(void (^)(NSError*))onFailure;
  ```
</CodeGroup>

| 이름        | 필수 여부 | 타입                              | 설명                |
| --------- | ----- | ------------------------------- | ----------------- |
| channel   | 필수    | String                          | 트래킹 링크를 사용할 광고 채널 |
| option    | 필수    | \[String: Any]                  | 트래킹 링크 생성 옵션      |
| onSuccess | 필수    | (AirbridgeTrackingLink) -> Void | 성공 콜백             |
| onFailure | 선택    | (Error) -> Void                 | 실패 콜백             |

`createTrackingLink` 함수는 `option` 파라미터를 통해 생성 옵션을 설정할 수 있습니다.

<Accordion title="트래킹 링크 생성 옵션">
  | 키                                                             | 타입                                   | 설명                                                                                                                                                                                                                        |
  | ------------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | AirbridgeTrackingLinkOption.CAMPAIGN                          | String                               | 캠페인 이름                                                                                                                                                                                                                    |
  | AirbridgeTrackingLinkOption.AD\_GROUP                         | String                               | 광고 그룹                                                                                                                                                                                                                     |
  | AirbridgeTrackingLinkOption.AD\_CREATIVE                      | String                               | 광고 소재                                                                                                                                                                                                                     |
  | AirbridgeTrackingLinkOption.CONTENT                           | String                               | 광고 콘텐츠                                                                                                                                                                                                                    |
  | AirbridgeTrackingLinkOption.TERM                              | String                               | 검색 광고 키워드                                                                                                                                                                                                                 |
  | AirbridgeTrackingLinkOption.SUB\_ID                           | String                               | 하위 네트워크 혹은 제휴 매체사 등을 나타내는 아이디.                                                                                                                                                                                            |
  | AirbridgeTrackingLinkOption.SUB\_ID\_1                        | String                               | 하위 네트워크 또다른 하위 네트워크 아이디(sub-sub publisher). 하위 매체 순서(계층)에 맞게 사용해야합니다 (sub\_id\_1 > sub\_id\_2 > sub\_id\_3)                                                                                                               |
  | AirbridgeTrackingLinkOption.SUB\_ID\_2                        | String                               | 하위 네트워크 또다른 하위 네트워크 아이디(sub-sub publisher). 하위 매체 순서(계층)에 맞게 사용해야합니다 (sub\_id\_1 > sub\_id\_2 > sub\_id\_3)                                                                                                               |
  | AirbridgeTrackingLinkOption.SUB\_ID\_3                        | String                               | 하위 네트워크 또다른 하위 네트워크 아이디 (sub-sub publisher). 하위 매체 순서(계층)에 맞게 사용해야합니다 (sub\_id\_1 > sub\_id\_2 > sub\_id\_3)                                                                                                              |
  | AirbridgeTrackingLinkOption.DEEPLINK\_URL                     | (Custom Scheme URL String)           | Deeplink URL                                                                                                                                                                                                              |
  | AirbridgeTrackingLinkOption.DEEPLINK\_STOPOVER                | Bool                                 | Deeplink 의 스탑오버 기능 활성화 여부<br />true : 활성화<br />false : 비활성화                                                                                                                                                               |
  | AirbridgeTrackingLinkOption.FALLBACK\_IOS                     | ("store" \| Web URL String)          | App 미설치시 ios fallback                                                                                                                                                                                                     |
  | AirbridgeTrackingLinkOption.FALLBACK\_ANDROID                 | ("store" \| Web URL String)          | App 미설치시 android fallback                                                                                                                                                                                                 |
  | AirbridgeTrackingLinkOption.FALLBACK\_DESKTOP                 | (Web URL String)                     | App 미설치시 desktop fallback                                                                                                                                                                                                 |
  | AirbridgeTrackingLinkOption.FALLBACK\_IOS\_STORE\_PPID        | String                               | 애플 앱 스토어의 맞춤형 제품 페이지(Custom Product Page)의 ppid.<br />앱 스토어로 랜딩할 경우 맞춤형 제품 페이지를 보여줄 수 있도록 설정합니다.                                                                                                                          |
  | AirbridgeTrackingLinkOption.FALLBACK\_ANDROID\_STORE\_LISTING | String                               | 구글 플레이 스토어의 맞춤 스토어 등록정보(Custom Store Listing) listing 값.<br />구글 플레이 스토어로 랜딩할 경우 맞춤 스토어 등록정보를 보여줄 수 있도록 설정합니다.                                                                                                            |
  | AirbridgeTrackingLinkOption.OGTAG\_TITLE                      | String                               | 트래킹 링크의 og:title                                                                                                                                                                                                          |
  | AirbridgeTrackingLinkOption.OGTAG\_DESCRIPTION                | String                               | 트래킹 링크의 og:description                                                                                                                                                                                                    |
  | AirbridgeTrackingLinkOption.OGTAG\_IMAGE\_URL                 | (Web URL String)                     | 트래킹 링크의 og:image                                                                                                                                                                                                          |
  | AirbridgeTrackingLinkOption.OGTAG\_WEBSITE\_CRAWL             | ("desktop")                          | 트래킹 링크가 소셜 미디어에 공유될 때 소셜 미디어가 fallbackPaths에 지정된 desktop URL의 Open Graph 태그를 직접 크롤링해 소셜 쉐어 프리뷰에 사용합니다. 동적(Dynamic) URL도 지원하며, Open Graph 태그의 변경 사항은 다음 공유 시점부터 자동으로 반영됩니다. 이때 title, description, imageUrl로 설정한 값은 무시됩니다. |
  | AirbridgeTrackingLinkOption.CUSTOM\_SHORT\_ID                 | String                               | Custom 채널의 트래킹 링크 생성시 축약된 링크 숏 아이디. [커스텀 도메인](/ko/guides/custom-domain) 설정을 해야 사용할 수 있습니다.<br />입력하지 않으면 랜덤 아이디가 생성되며, 트래킹 링크 생성 완료 후에는 변경할 수 없습니다.                                                                       |
  | AirbridgeTrackingLinkOption.IS\_REENGAGEMENT                  | ("off" \| "on\_true" \| "on\_false") | re-engagement 파라미터.<br />off: 해당 트래킹 링크에 발생한 터치포인트로 설치 및 인앱 이벤트를 기여합니다.<br />on\_true: 딥링크 오픈 및 그에 기인한 이벤트만 기여됩니다. Re-engagement 캠페인에 활용 가능합니다.<br />on\_false: 설치 이벤트 및 그에 기인한 인앱 이벤트만 기여됩니다. UA 캠페인에 활용 가능합니다.          |
</Accordion>

`createTrackingLink` 함수는 `onSuccess` 콜백을 통해 `AirbridgeTrackingLink` 를 전달합니다.

<CodeGroup>
  ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  public final class AirbridgeTrackingLink: NSObject {
      public let shortURL: URL
      public let qrcodeURL: URL
  }
  ```

  ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
  @interface AirbridgeTrackingLink : NSObject

  + (NSURL*)shortURL;
  + (NSURL*)qrcodeURL;

  @end
  ```
</CodeGroup>

| 이름        | 타입  | 설명                  |
| --------- | --- | ------------------- |
| shortURL  | URL | 트래킹 링크의 단축 URL      |
| qrcodeURL | URL | 트래킹 링크의 QR Code URL |

아래 예시 코드를 참고해 주세요.

<AccordionGroup>
  <Accordion title="앱이 열리거나 스토어로 이동하는 트래킹 링크 생성하기">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      Airbridge.createTrackingLink(
          channel: "test_channel",
          option: [
              AirbridgeTrackingLinkOption.CAMPAIGN: "test_campaign",
              AirbridgeTrackingLinkOption.DEEPLINK_URL: "YOUR_SCHEME://...",
              AirbridgeTrackingLinkOption.FALLBACK_IOS: "store",
              AirbridgeTrackingLinkOption.FALLBACK_ANDROID: "store",
              AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: "https://example.com/"
          ],
          onSuccess: { trackingLink in
              // Handling created tracking-link
          },
          onFailure: { error in
              // Handling error
          }
      )
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      [Airbridge createTrackingLinkWithChannel:@"test_channel" option:@{
          AirbridgeTrackingLinkOption.CAMPAIGN: @"test_campaign",
          AirbridgeTrackingLinkOption.DEEPLINK_URL: @"YOUR_SCHEME://...",
          AirbridgeTrackingLinkOption.FALLBACK_IOS: @"store",
          AirbridgeTrackingLinkOption.FALLBACK_ANDROID: @"store",
          AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: @"https://example.com/"
      } onSuccess:^(AirbridgeTrackingLink* trackingLink) {
          // Handling created tracking-link
      } onFailure:^(NSError* error) {
          // Handling error
      }];
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="앱이 열리거나 웹페이지로 이동하는 트래킹 링크 생성">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      Airbridge.createTrackingLink(
          channel: "test_channel",
          option: [
              AirbridgeTrackingLinkOption.CAMPAIGN: "test_campaign",
              AirbridgeTrackingLinkOption.DEEPLINK_URL: "YOUR_SCHEME://...",
              AirbridgeTrackingLinkOption.FALLBACK_IOS: "https://example.com/",
              AirbridgeTrackingLinkOption.FALLBACK_ANDROID: "https://example.com/",
              AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: "https://example.com/"
          ],
          onSuccess: { trackingLink in
              // Handling created tracking-link
          },
          onFailure: { error in
              // Handling error
          }
      )
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      [Airbridge createTrackingLinkWithChannel:@"test_channel" option:@{
          AirbridgeTrackingLinkOption.CAMPAIGN: @"test_campaign",
          AirbridgeTrackingLinkOption.DEEPLINK_URL: @"YOUR_SCHEME://...",
          AirbridgeTrackingLinkOption.FALLBACK_IOS: @"https://example.com/",
          AirbridgeTrackingLinkOption.FALLBACK_ANDROID: @"https://example.com/",
          AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: @"https://example.com/"
      } onSuccess:^(AirbridgeTrackingLink* trackingLink) {
          // Handling created tracking-link
      } onFailure:^(NSError* error) {
          // Handling error
      }];
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="스토어로만 이동하는 트래킹 링크 생성하기">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      Airbridge.createTrackingLink(
          channel: "test_channel",
          option: [
              AirbridgeTrackingLinkOption.CAMPAIGN: "test_campaign",
              AirbridgeTrackingLinkOption.FALLBACK_IOS: "store",
              AirbridgeTrackingLinkOption.FALLBACK_ANDROID: "store",
              AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: "https://example.com/"
          ],
          onSuccess: { trackingLink in
              // Handling created tracking-link
          },
          onFailure: { error in
              // Handling error
          }
      )
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      [Airbridge createTrackingLinkWithChannel:@"test_channel" option:@{
          AirbridgeTrackingLinkOption.CAMPAIGN: @"test_campaign",
          AirbridgeTrackingLinkOption.FALLBACK_IOS: @"store",
          AirbridgeTrackingLinkOption.FALLBACK_ANDROID: @"store",
          AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: @"https://example.com/"
      } onSuccess:^(AirbridgeTrackingLink* trackingLink) {
          // Handling created tracking-link
      } onFailure:^(NSError* error) {
          // Handling error
      }];
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="웹페이지로만 이동하는 트래킹 링크 생성하기">
    <CodeGroup>
      ```swift Swift lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      Airbridge.createTrackingLink(
          channel: "test_channel",
          option: [
              AirbridgeTrackingLinkOption.CAMPAIGN: "test_campaign",
              AirbridgeTrackingLinkOption.FALLBACK_IOS: "https://example.com/",
              AirbridgeTrackingLinkOption.FALLBACK_ANDROID: "https://example.com/",
              AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: "https://example.com/"
          ],
          onSuccess: { trackingLink in
              // Handling created tracking-link
          },
          onFailure: { error in
              // Handling error
          }
      )
      ```

      ```objective-c Objective-C lines theme={"theme":{"light":"github-dark-dimmed","dark":"github-dark-dimmed"}}
      [Airbridge createTrackingLinkWithChannel:@"test_channel" option:@{
          AirbridgeTrackingLinkOption.CAMPAIGN: @"test_campaign",
          AirbridgeTrackingLinkOption.FALLBACK_IOS: @"https://example.com/",
          AirbridgeTrackingLinkOption.FALLBACK_ANDROID: @"https://example.com/",
          AirbridgeTrackingLinkOption.FALLBACK_DESKTOP: @"https://example.com/"
      } onSuccess:^(AirbridgeTrackingLink* trackingLink) {
          // Handling created tracking-link
      } onFailure:^(NSError* error) {
          // Handling error
      }];
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

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

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