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

# 딥 링킹

> Universal Links, App Links 또는 커스텀 URI 스킴을 사용하여 푸시 알림, 이메일, 인앱 메시지에서 Android 또는 iOS 앱의 특정 화면으로 사용자를 연결하는 딥 링킹을 설정합니다.

## 개요

딥 링킹은 사용자가 링크를 탭할 때 이메일, SMS, 웹사이트, 푸시 알림, 인앱 메시지 등 어떤 소스에서든 앱 내 특정 화면으로 연결합니다. 앱이 설치되지 않은 경우 운영 체제가 사용자를 앱 스토어 또는 대체 웹 페이지로 리다이렉트할 수 있습니다.

이 가이드에서 다루는 내용:

* **딥 링크 유형**과 각각의 사용 시기
* Android와 iOS의 **플랫폼 설정**
* OneSignal SDK를 사용한 앱에서의 **딥 링크 처리**
* 푸시, 이메일, 인앱 메시지의 **채널별 동작**

<Info>
  일반적인 URL 및 링크 구성(실행 URL, UTM 매개변수, 동적 URL, 링크 추적)에 대해서는 [URL, 링크 및 딥 링크](./links)를 참조하세요.
</Info>

***

## 사전 요구 사항

딥 링크를 설정하기 전에 필요한 것:

* 앱이 구성된 [OneSignal 계정](https://dashboard.onesignal.com)
* 모바일 앱에 설치된 [OneSignal SDK](./mobile-sdk-setup)
* Universal Links 또는 App Links를 위해 **HTTPS**로 호스팅된 본인 소유의 도메인
* 앱의 소스 코드 및 빌드 구성에 대한 액세스 권한(iOS는 Xcode, Android는 Android Studio)

***

## 딥 링크 유형

딥 링킹에는 세 가지 일반적인 메커니즘이 있습니다. 각각의 동작은 앱 설치 여부에 따라 다릅니다.

| 유형                  | 플랫폼           | 형식                            | 앱 미설치 시          |
| ------------------- | ------------- | ----------------------------- | ---------------- |
| **Universal Links** | iOS 9+        | `https://yourdomain.com/path` | Safari에서 URL 열기  |
| **App Links**       | Android 6.0+  | `https://yourdomain.com/path` | 브라우저에서 URL 열기    |
| **커스텀 URI 스킴**      | iOS & Android | `myapp://path`                | 자동으로 실패하거나 오류 표시 |

**권장 사항:** 가장 안정적인 경험을 위해 Universal Links(iOS)와 App Links(Android)를 사용하세요. 표준 `https://` URL을 사용하고, 채널(푸시, 이메일, SMS) 전반에서 작동하며, 앱이 설치되지 않았을 때 대체 동작을 제공합니다. 커스텀 URI 스킴(`myapp://`)은 설정이 더 간단하지만 대체 동작을 제공하지 않으며 일부 컨텍스트(예: 이메일 클라이언트)에서 작동하지 않을 수 있습니다.

<Warning>
  Universal Links와 App Links는 도메인에 검증 파일을 호스팅해야 합니다. 이 파일이 없으면 OS가 링크를 일반 웹 URL로 처리합니다.
</Warning>

***

## Android 설정 (App Links)

Android Studio의 [App Links Assistant](https://developer.android.com/training/app-links)를 사용하여 필요한 구성을 생성합니다.

### 인텐트 필터 구성

딥 링크를 처리할 Activity에 인텐트 필터를 추가합니다:

```xml theme={null}
<activity android:name=".DeepLinkActivity" android:exported="true">
  <intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" android:host="yourdomain.com" />
  </intent-filter>
</activity>
```

### 수신 인텐트 처리

```java theme={null}
Intent appLinkIntent = getIntent();
String appLinkAction = appLinkIntent.getAction();
Uri appLinkData = appLinkIntent.getData();
```

### Digital Asset Links 파일 호스팅

Android Studio의 App Links Assistant를 사용하여 `assetlinks.json` 파일을 생성하고 다음 위치에 호스팅합니다:

```
https://yourdomain.com/.well-known/assetlinks.json
```

전체 파일 형식과 검증 단계는 Google의 [Verify App Links](https://developer.android.com/training/app-links/verify-android-applinks) 문서를 참조하세요.

***

## iOS 설정 (Universal Links)

Apple [Universal Links](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app)는 사용자가 일치하는 `https://` URL을 탭하면 앱을 엽니다. 앱이 설치되어 있음이 보장되는 간단한 사용 사례의 경우 [URL 스킴](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)을 대신 사용할 수 있습니다.

### Associated Domains 활성화

1. Xcode에서 타겟 선택 → **Signing & Capabilities** → **Associated Domains** 추가
2. 도메인 추가: `applinks:yourdomain.com`

### 앱에서 Universal Link 처리

<CodeGroup>
  ```swift Swift theme={null}
  func application(_ application: UIApplication,
                   continue userActivity: NSUserActivity,
                   restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else {
      return false
    }
    // Route to the correct screen based on the URL path
    return true
  }
  ```

  ```objectivec Objective-C theme={null}
  - (BOOL)application:(UIApplication *)application
      continueUserActivity:(NSUserActivity *)userActivity
      restorationHandler:(void (^)(NSArray *))restorationHandler {
    if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
      NSURL *url = userActivity.webpageURL;
      // Route to the correct screen based on the URL path
      return YES;
    }
    return NO;
  }
  ```
</CodeGroup>

### Apple App Site Association 파일 호스팅

`apple-app-site-association`(AASA) 파일을 생성하고 다음 위치에 호스팅합니다:

```
https://yourdomain.com/.well-known/apple-app-site-association
```

`TEAMID`를 Apple Team ID로, `com.example.app`을 번들 식별자로 교체하세요:

```json theme={null}
{
  "applinks": {
    "apps": [],
    "details": [{
      "appID": "TEAMID.com.example.app",
      "paths": ["/path/*", "/another-path"]
    }]
  }
}
```

전체 사양은 Apple의 [Supporting Associated Domains](https://developer.apple.com/documentation/xcode/supporting-associated-domains) 문서를 참조하세요.

### iOS 실행 URL 동작

OneSignal의 iOS SDK는 실행 URL(`url` 속성)을 처리하기 위해 `openURL`을 사용합니다. 이로 인해 링크가 먼저 브라우저에서 열리고 그 다음 앱으로 다시 리다이렉트됩니다——사용자 경험이 좋지 않을 수 있습니다.

이를 방지하려면 다음 방법 중 하나를 사용하세요:

1. API 페이로드에서 **`url` 대신 `data` 사용**하고 [푸시 알림 클릭 리스너](./mobile-sdk-reference#addclicklistener-push)에서 딥 링크 처리
2. `Info.plist`에 Boolean 값 `YES`로 `OneSignal_suppress_launch_urls`를 추가하여 **실행 URL 억제**하고, 클릭 리스너에서 모든 내비게이션 처리

<Tip>
  방법 1(`data` + 클릭 리스너 사용)을 권장합니다. OS가 URL을 해석하는 것에 의존하지 않고 내비게이션을 완전히 제어할 수 있습니다.
</Tip>

***

## OneSignal SDK로 딥 링크 처리

OneSignal 메시지의 딥 링크를 처리하는 가장 안정적인 방법은 OS 수준의 링크 해석에 의존하는 대신 SDK의 클릭 리스너를 사용하는 것입니다. 이를 통해 앱 내비게이션을 완전히 제어할 수 있습니다.

### 푸시 알림 클릭 리스너

`addClickListener`를 사용하여 알림 클릭을 인터셉트하고 딥 링크 URL 또는 추가 데이터를 기반으로 사용자를 라우팅합니다:

<CodeGroup>
  ```kotlin Kotlin theme={null}
  OneSignal.Notifications.addClickListener { event ->
    val url = event.notification.launchURL
    val data = event.notification.additionalData
    // Route to the correct screen based on url or data
  }
  ```

  ```swift Swift theme={null}
  class AppDelegate: UIResponder, UIApplicationDelegate, OSNotificationClickListener {
    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
      OneSignal.Notifications.addClickListener(self)
      return true
    }

    func onClick(event: OSNotificationClickEvent) {
      let url = event.notification.launchURL
      let data = event.notification.additionalData
      // Route to the correct screen based on url or data
    }
  }
  ```

  ```javascript React Native theme={null}
  OneSignal.Notifications.addEventListener('click', (event) => {
    const url = event.notification.launchURL;
    const data = event.notification.additionalData;
    // Route to the correct screen based on url or data
  });
  ```

  ```dart Flutter theme={null}
  OneSignal.Notifications.addClickListener((event) {
    final url = event.notification.launchUrl;
    final data = event.notification.additionalData;
    // Route to the correct screen based on url or data
  });
  ```

  ```csharp Unity (C#) theme={null}
  OneSignal.Notifications.Clicked += (sender, e) => {
    var url = e.Notification.LaunchURL;
    var data = e.Notification.AdditionalData;
    // Route to the correct screen based on url or data
  };
  ```
</CodeGroup>

Java, Objective-C, Cordova/Ionic을 포함한 전체 API 참조는 [`addClickListener()` 푸시](./mobile-sdk-reference#addclicklistener-push)를 참조하세요.

### 인앱 메시지 클릭 리스너

인앱 메시지 버튼과 액션에서 딥 링크를 처리하려면 인앱 메시지 클릭 리스너를 사용합니다:

<CodeGroup>
  ```kotlin Kotlin theme={null}
  OneSignal.InAppMessages.addClickListener { event ->
    val actionId = event.result.actionId
    // Route based on the action ID (your deep link URI)
  }
  ```

  ```swift Swift theme={null}
  func onClick(event: OSInAppMessageClickEvent) {
    let actionId = event.result.actionId
    // Route based on the action ID (your deep link URI)
  }
  ```

  ```javascript React Native theme={null}
  OneSignal.InAppMessages.addEventListener('click', (event) => {
    const actionId = event.result.actionId;
    // Route based on the action ID (your deep link URI)
  });
  ```

  ```dart Flutter theme={null}
  OneSignal.InAppMessages.addClickListener((event) {
    final actionId = event.result.actionId;
    // Route based on the action ID (your deep link URI)
  });
  ```
</CodeGroup>

전체 API 참조는 [`addClickListener()` 인앱](./mobile-sdk-reference#addclicklistener-in-app)을 참조하세요.

***

## 푸시 알림

두 가지 방법 중 하나로 딥 링크를 포함합니다:

| 방법              | API 속성                      | 동작                                              |
| --------------- | --------------------------- | ----------------------------------------------- |
| **실행 URL**      | `url` (또는 모바일 전용 `app_url`) | OS가 URL을 직접 엽니다. iOS에서는 억제하지 않으면 먼저 브라우저가 열립니다. |
| **추가 데이터** (권장) | `data`                      | URL이 클릭 리스너로 전달됩니다. 내비게이션을 완전히 제어합니다.           |

### 플랫폼 동작

* **Android**: App Links를 통해 일치하는 Activity를 직접 엽니다
* **iOS**: Safari를 열고 그 다음 앱을 엽니다([실행 URL을 억제](#ios-실행-url-동작)하고 클릭 리스너에서 내비게이션을 처리하지 않는 경우)

`url`, `web_url`, `app_url` 타겟팅에 대한 자세한 내용은 [URL, 링크 및 딥 링크](./links)를 참조하세요.

***

## 이메일

기본적으로 OneSignal은 클릭 추적을 위해 이메일 링크를 재작성합니다. 이로 인해 URL이 변경되어 OS가 도메인을 앱의 Associated Domain과 일치하는 것으로 인식하지 못하게 되어 딥 링킹이 중단됩니다.

### 이메일에서 딥 링크 활성화

딥 링크를 유지하려면 다음 방법 중 하나를 사용하여 클릭 추적을 비활성화합니다:

* **대시보드**: 이메일 편집기에서 **Track link clicks** 체크 해제
* **API**: `disable_email_click_tracking: true` 설정
* **링크별**: 앵커 태그에 `disable-tracking=true` 속성(`<a href="https://yourdomain.com/path" disable-tracking=true>…</a>`)을 추가하여 다른 링크의 추적은 유지하면서 개별 링크의 추적 비활성화

<Frame caption="이메일 편집기에서 Track link clicks가 비활성화되었습니다.">
  <img src="https://mintcdn.com/onesignal/jBdBk5XvQR5eKOks/images/docs/787e21d-Screenshot_2024-05-29_at_2.21.43_PM.png?fit=max&auto=format&n=jBdBk5XvQR5eKOks&q=85&s=f7e1079f4860ecf34fd95375a4332573" alt="Track link clicks 체크박스가 해제된 OneSignal 이메일 편집기" width="1756" height="492" data-path="images/docs/787e21d-Screenshot_2024-05-29_at_2.21.43_PM.png" />
</Frame>

<Warning>
  클릭 추적을 비활성화하면 [이메일 보고서](./email-message-reports)에서 클릭 지표를 잃게 됩니다. 딥 링크가 아닌 URL의 분석을 유지하려면 링크별 추적 제외 사용을 고려하세요.
</Warning>

### 이메일 딥 링크 동작

| 시나리오                                        | 결과                      |
| ------------------------------------------- | ----------------------- |
| iOS + Safari + Universal Link + 추적 비활성화     | 앱을 직접 엽니다               |
| iOS + Safari + Universal Link + 추적 활성화      | Safari를 열고 앱 열기를 유도합니다  |
| iOS + 비(非) Safari 메일 클라이언트 + Universal Link | 앱 미설치 시 App Store를 엽니다  |
| Android + App Link + 추적 비활성화                | 앱을 직접 엽니다               |
| Android + App Link + 추적 활성화                 | 먼저 브라우저를 열고 그 다음 앱을 엽니다 |

***

## 인앱 메시지

인앱 메시지의 딥 링크는 클릭 리스너 패턴을 사용합니다. 메시지 편집기에서 커스텀 액션 식별자를 설정하고 앱 코드에서 처리합니다.

### 드래그 앤 드롭 편집기

1. 버튼 또는 클릭 가능한 요소 추가
2. 클릭 액션을 [Custom Action ID](./iam-click-actions#custom-action-id)로 설정
3. **Action Name**으로 딥 링크 URI 입력 (예: `https://yourdomain.com/promo` 또는 `myapp://promo`)

### HTML 편집기

커스텀 HTML에서 딥 링크를 트리거하려면 인앱 JS 라이브러리의 [`openUrl`](./in-app-message-api#click-name) 메서드를 사용합니다.

### 클릭 처리

[인앱 메시지 클릭 리스너](#인앱-메시지-클릭-리스너)를 사용하여 액션을 인터셉트하고 앱에서 사용자를 안내합니다.

***

## 딥 링크 테스트

### Android

알림 없이 App Links를 테스트하려면 `adb`를 사용합니다:

```bash theme={null}
adb shell am start -a android.intent.action.VIEW \
  -d "https://yourdomain.com/path" \
  com.your.package
```

`assetlinks.json`에 접근 가능한지 확인합니다:

```bash theme={null}
curl -I https://yourdomain.com/.well-known/assetlinks.json
```

### iOS

Apple의 [Associated Domains 유효성 검사 도구](https://search.developer.apple.com/appsearch-validation-tool/)를 사용하여 AASA 파일을 확인합니다. 다음 방법으로도 Universal Links를 테스트할 수 있습니다:

1. 메모 앱에 링크 붙여넣기
2. 링크를 길게 눌러 "\[앱]에서 열기" 옵션이 나타나는지 확인
3. 링크를 탭하여 앱이 열리는지 확인

<Note>
  Universal Links는 Safari 주소창에 직접 입력할 때 작동하지 않습니다——다른 앱(메모, 메일, 메시지 등)에서 탭해야 합니다.
</Note>

### OneSignal 테스트 메시지

1. OneSignal 대시보드에서 딥 링크 URL을 실행 URL 또는 추가 데이터로 설정하여 테스트 푸시 전송
2. 알림이 앱에서 올바른 화면을 여는지 확인
3. 클릭 리스너 로그를 확인하여 URL 또는 데이터가 수신되었는지 확인

***

## 문제 해결

### iOS 딥 링크가 앱 대신 Safari를 열 때

가장 일반적인 문제입니다. 가능한 원인:

* **AASA 파일이 올바르게 호스팅되지 않음** — `https://yourdomain.com/.well-known/apple-app-site-association`에 `Content-Type: application/json`으로 리다이렉트 없이 있는지 확인
* **Associated Domains 미구성** — Xcode → Signing & Capabilities → Associated Domains에 `applinks:yourdomain.com`이 포함되어 있는지 확인
* **실행 URL 동작** — OneSignal의 iOS SDK는 `url` 속성에 `openURL`을 사용하여 브라우저 우선 동작을 트리거합니다. 대신 `data` + 클릭 리스너를 사용하거나 [실행 URL을 억제](#ios-실행-url-동작)하세요
* **Safari에서 테스트** — Universal Links는 Safari 주소창에서 활성화되지 않습니다. 메모, 메일 또는 다른 앱에서 테스트하세요.

### Android 딥 링크가 브라우저를 열 때

* **`autoVerify` 누락** — 인텐트 필터에 `android:autoVerify="true"`가 포함되어 있는지 확인
* **`assetlinks.json` 미발견** — 파일이 `https://yourdomain.com/.well-known/assetlinks.json`에 있고 HTTP 200을 반환하는지 확인
* **SHA256 지문 불일치** — `assetlinks.json`의 지문은 앱 서명 인증서와 일치해야 합니다. 디버그 빌드와 릴리스 빌드는 다른 인증서를 사용합니다.

### 딥 링크가 푸시에서는 작동하지만 이메일에서는 작동하지 않을 때

이메일 클릭 추적이 URL을 재작성하여 도메인 검증을 방해합니다. 딥 링크가 포함된 이메일의 클릭 추적을 [비활성화](#이메일에서-딥-링크-활성화)하세요.

### 딥 링크는 수신되지만 앱이 이동하지 않을 때

* 클릭 리스너가 앱 생명주기 초반에 등록되었는지 확인 (예: `Application.onCreate()` 또는 `AppDelegate.didFinishLaunchingWithOptions`)
* URL 또는 액션 ID가 라우팅 로직이 예상하는 것과 일치하는지 확인
* iOS에서 실행 URL을 억제하지 않고 `url`에 의존하지 않는지 확인——리스너가 실행되기 전에 브라우저가 링크를 소비할 수 있습니다

***

## 자주 묻는 질문

### 앱이 설치되지 않은 경우 어떻게 됩니까?

Universal Links(iOS)의 경우 URL이 일반 웹 페이지로 Safari에서 열립니다. App Links(Android)의 경우 URL이 기본 브라우저에서 열립니다. 두 경우 모두 웹 페이지를 적절한 앱 스토어로 리다이렉트하도록 구성할 수 있습니다. 커스텀 URI 스킴(`myapp://`)은 앱이 설치되지 않은 경우 자동으로 실패하거나 오류를 표시합니다.

### 딥 링킹에 실행 URL과 추가 데이터 중 어느 것을 사용해야 합니까?

추가 데이터(`data`)는 클릭 리스너를 통해 내비게이션을 완전히 제어할 수 있으므로 모바일 딥 링크에 권장됩니다. 실행 URL(`url`)은 더 간단하지만 iOS에서 제한이 있고(브라우저 리다이렉트) 커스텀 라우팅 로직을 허용하지 않습니다.

### 사용자 데이터로 딥 링크를 개인화할 수 있습니까?

예. Liquid 구문이 있는 [동적 URL](./links#dynamic-urls)을 사용하여 딥 링크 URL에 사용자 속성, 태그 또는 커스텀 데이터를 주입합니다. 예: `https://yourdomain.com/profile/{{subscription.external_id}}`

### 커스텀 URI 스킴으로 딥 링크를 사용할 수 있습니까?

예. 커스텀 스킴(예: `myapp://screen`)을 실행 URL 또는 추가 데이터 값으로 설정합니다. 커스텀 스킴은 푸시 및 인앱 메시지에서는 잘 작동하지만 이메일 클라이언트에서는 작동하지 않을 수 있습니다. 또한 앱이 설치되지 않은 경우 대체 방안을 제공하지 않습니다.

### OneSignal Journeys에서 딥 링크가 작동합니까?

예. Journey에서 메시지 단계를 구성할 때 실행 URL 또는 추가 데이터를 딥 링크로 설정합니다. 동작은 독립적인 푸시 또는 인앱 메시지와 동일합니다.

***

<Columns cols={2}>
  <Card title="URL, 링크 및 딥 링크" icon="link" href="./links">
    실행 URL, UTM 매개변수, 동적 URL 및 링크 추적 구성.
  </Card>

  <Card title="모바일 SDK 참조" icon="code" href="./mobile-sdk-reference">
    클릭 리스너 및 알림 이벤트 처리를 위한 전체 API 참조.
  </Card>

  <Card title="인앱 클릭 액션" icon="hand-pointer" href="./iam-click-actions">
    인앱 메시지 버튼 및 요소에 대한 클릭 액션 구성.
  </Card>

  <Card title="모바일 푸시 설정" icon="mobile" href="./mobile-push-setup">
    Android 및 iOS용 플랫폼별 푸시 알림 설정.
  </Card>
</Columns>
