Universal Link는 Safari를 거치지 않고 웹 링크를 앱에서 직접 열 수 있는 Apple의 메커니즘(iOS 9+)입니다. 앱이 설치되지 않은 경우 링크는 브라우저에서 원활하게 열립니다. 이 용어는 2015년 WWDC에서 Handoff 및 Continuity 생태계의 일부로 Apple이 도입했습니다. Apple Developer에 따르면, Universal Link는 선택 대화상자 없이 웹과 네이티브 앱 간의 통합된 사용자 경험을 제공합니다.
핵심 사항
Universal Link는 iOS 기기에서 탭하면 Safari 대신 설치된 앱이 열리는 https://example.com/page와 같은 표준 HTTPS 링크입니다. Custom URL Scheme과의 주요 차이점: Universal Link는 사용자 정의 스킴(myapp://) 등록이 필요 없으며 일반 도메인을 사용합니다. 이렇게 하면 모든 앱이 동일한 스킴을 등록할 수 있는 URL 스킴 하이재킹 문제가 제거됩니다.
Apple은 WWDC 2015에서 iOS 9의 일부로 Universal Link를 발표했습니다. 이 메커니즘은 Handoff 및 Spotlight 생태계의 일부가 되었습니다. Universal Link는 브라우저뿐만 아니라 Spotlight 검색 결과, Mail, Messages 및 기타 시스템 앱에서도 작동합니다. 또한 Universal Link는 watchOS 및 macOS에서도 지원됩니다 — 사용자는 Mac의 링크를 통해 iPhone에서 앱을 열 수 있습니다.
주요 이점: 통합 URL. 개발자는 두 개의 다른 링크(웹용과 앱용)를 관리할 필요가 없습니다. Universal Link는 동일한 https 링크입니다. 앱이 설치되어 있으면 앱이 열리고, 그렇지 않으면 동일한 링크가 Safari에서 일반 웹페이지로 열립니다. 이는 트래픽 손실 없이 이상적인 대체(fallback)를 제공합니다.
Universal Link 메커니즘은 연결 확인, 링크 처리, 브라우저 대체의 세 단계로 구성됩니다. 각 단계는 올바른 작동에 중요합니다. 연결이 구성되지 않은 경우 iOS는 링크를 Safari로의 일반 리디렉션으로 처리합니다. 각 단계를 자세히 살펴보겠습니다.
링크를 처음 탭하면 iOS가 서버에서 https://example.com/.well-known/apple-app-site-association에 있는 apple-app-site-association 파일을 다운로드합니다. 파일에는 앱의 Team ID 및 Bundle ID와 함께 JSON이 포함되어 있으며, 앱이 열어야 하는 경로 목록도 포함됩니다. iOS는 이 파일을 캐시하고 정기적으로 최신 상태인지 확인합니다(앱 업데이트, 기기 재시작 시).
JSON 파일 apple-app-site-association은 리디렉션 없이 HTTPS를 통해 접근 가능해야 합니다. 서버는 Content-Type: application/json을 반환해야 합니다. 중요한 점은 파일에 .json 확장자가 없다는 것입니다 — iOS는 엄격히 /.well-known/apple-app-site-association에서 찾습니다. Apple은 CDN에서 Universal Link 지원을 추가하고 robots.txt에 의해 파일이 차단되지 않았는지 확인할 것을 권장합니다.
// apple-app-site-association — 최소 구성
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/product/*", "/profile/*", "/search"]
}
]
}
}
appID는 Team ID + Bundle ID(TEAMID.com.example.app)로 구성됩니다. paths는 앱이 처리해야 하는 URL 패턴의 배열입니다. *, ? 및 NOT 표기법을 사용할 수 있습니다: ["NOT /admin/*", "/product/*"]. 경로는 나열된 순서대로 확인되며 첫 번째 일치가 동작을 결정합니다. 경로가 일치하지 않으면 링크가 Safari에서 열립니다.
연결 확인이 성공하면 iOS가 링크를 앱에 전달합니다. 처리는 NSUserActivity의 경우 AppDelegate의 application(_:continue:restorationHandler:) 메서드 또는 SceneDelegate의 scene(_:continue:)을 통해 수행됩니다. 개발자는 NSUserActivityTypeBrowsingWeb 유형의 NSUserActivity 개체를 받고, URL을 추출하여 해당 화면으로 이동합니다.
// AppDelegate에서 Universal Link 처리
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping UIUserActivityRestorationHandler
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL
else { return false }
// URL에 따라 화면으로 이동
DeepLinkRouter.navigate(to: url)
return true
}
위 예제의 DeepLinkRouter는 URL을 구문 분석하고 해당 탐색 코디네이터를 호출하는 사용자 정의 클래스입니다. SwiftUI의 경우 처리는 onOpenURL 메서드 또는 environment(\.openURL) 수정자를 통해 수행됩니다. 포그라운드 시작뿐만 아니라 앱이 실행되지 않은 경우(콜드 스타트)도 처리하는 것이 중요합니다. 이 경우 Universal Link는 시작 옵션을 통해 앱을 엽니다.
앱이 설치되지 않은 경우 iOS가 자동으로 Safari에서 Universal Link를 엽니다. 이것이 Custom URL Scheme과의 주요 차이점입니다: 사용자에게 오류가 표시되지 않습니다. 대체는 동일한 도메인의 표준 웹페이지입니다. 개발자는 이 페이지에 App Store 링크, 제품 정보 또는 대체 콘텐츠를 배치할 수 있습니다.
중요: 대체(fallback)는 iOS 수준에서 사용자 정의할 수 없습니다. iOS는 단순히 Safari에서 URL을 엽니다. 앱이 설치된 사용자와 설치되지 않은 사용자에게 다른 콘텐츠를 표시하려면 Smart App Banner(앱 열기를 제안하는 Safari의 메타 태그) 또는 JavaScript 설치 감지를 사용하세요. Apple은 Universal Link를 통한 설치 속성 추적을 위해 SKAdNetwork도 제공합니다.
Universal Link와 기존 Deep Link(Custom URL Scheme)는 동일한 문제를 해결하지만 아키텍처와 보안에서 근본적으로 다릅니다. Custom URL Scheme은 Info.plist에 등록된 사용자 정의 프로토콜(myapp://)입니다. 모든 앱이 동일한 스킴(myapp://)을 등록할 수 있으며, iOS는 어느 것이 ‘진짜’인지 확인할 수 없습니다. 이를 URL 스킴 하이재킹이라고 합니다.
Universal Link는 도메인 확인을 통해 하이재킹 문제를 해결합니다. 도메인 소유자만 서버에 apple-app-site-association을 배치하여 특정 Bundle ID와의 연결을 확인할 수 있습니다. 두 앱이 동일한 Universal Link를 등록할 수 없습니다: 충돌이 발생하면 iOS는 가장 최근에 설치된 앱에 우선순위를 주거나 Safari를 엽니다.
또 다른 차이점: 대체(Fallback). Custom URL Scheme에는 대체가 없습니다 — 앱이 설치되지 않은 경우 브라우저에 오류가 표시됩니다. Universal Link는 웹사이트를 엽니다. 통합 URL은 링크의 SEO 가치가 보존되고(Google이 링크를 인덱싱) 모든 기기의 사용자가 관련 콘텐츠를 받는다는 것을 의미합니다. Universal Link는 딥 링크에서 통합 링크로의 진화적 단계입니다.
| 특성 | Custom URL Scheme | Universal Link |
|---|---|---|
| 형식 | myapp://path | https://domain/path |
| 확인 | 없음 | apple-app-site-association |
| 보안 | 하이재킹에 취약 | 도메인 소유자만 |
| 대체 | 오류 | Safari의 웹사이트 |
| iOS 버전 | iOS 3+ | iOS 9+ |
설정에는 서버 측과 클라이언트 측이 포함됩니다. 서버 측 — https://domain/.well-known/apple-app-site-association에 apple-app-site-association 파일 배치. 클라이언트 측 — Xcode의 Associated Domains에 도메인 등록(Capabilities → Associated Domains → applinks:example.com). 그 후 앱은 지정된 도메인에 대한 모든 Universal Link를 자동으로 수신합니다.
설정 단계:
디버깅은 iOS 개발자에게 일반적인 골칫거리입니다. 링크가 작동하지 않는 주요 원인: apple-app-site-association 파일이 HTTPS를 통해 접근 불가, 잘못된 appID, Content-Type이 application/json이 아님, /.well-known 경로에서 리디렉션, 이전 버전 캐싱(Settings → Developer → Associated Domains Development를 통해 재설정). Apple은 연결 테스트를 위해 Apple Developer Console에서 Validation Checker 도구를 제공합니다.
Branch 및 기타 MMP 플랫폼은 Universal Link 설정을 간소화합니다: 자동으로 apple-app-site-association을 생성하고 자체 도메인에서 호스팅합니다. 개발자는 Associated Domains에 Branch 도메인을 추가하고 SDK를 통합하기만 하면 됩니다. 이는 AASA 파일을 호스팅할 자체 서버 인프라가 없는 스타트업에게 특히 편리합니다.
Universal Link에는 몇 가지 제한 사항이 있습니다. 첫째: apple-app-site-association 파일은 엄격히 HTTPS를 통해 접근 가능해야 합니다(HTTP는 지원되지 않음). 둘째: 링크는 Associated Domains에 지정된 동일한 도메인을 가리켜야 합니다. 교차 도메인 Universal Link는 작동하지 않습니다 — 각 도메인에 대해 Capabilities에 별도 항목과 별도 AASA 파일이 필요합니다. 셋째: Universal Link는 WKWebView에서 작동하지 않습니다 — Safari 및 시스템 구성 요소에서만 작동합니다.
호환성: iOS 9.0+(Universal Link), watchOS 6.0+(Handoff Universal Link), macOS 10.15+(Catalyst 및 Mac 앱). 이전 iOS 버전에서는 링크가 Safari에서 열립니다. 즉, iOS 8(기기의 1% 미만)에서는 Universal Link가 작동하지 않습니다. 대상 사용자에 이전 버전 사용자가 포함된 경우 이전 기기용 대체로 Custom URL Scheme도 지원하는 것이 좋습니다.
iOS 16+ 변경 사항: Apple이 SwiftUI의 Universal Link 처리를 개선했습니다. 지연 처리 기능이 있는 새로운 environment(\.openURL) 수정자가 도입되었습니다. iOS 16은 SFSafariViewController를 통해서도 앱에서 Universal Link를 열 수 있습니다. iOS 16 사용자의 경우 완전히 SwiftUI Universal Link 처리로 전환하고 AppDelegate 코드는 이전 버전과의 호환성을 위해서만 유지하는 것이 좋습니다.
자주 묻는 질문
Universal Link는 표준 HTTPS URL을 사용하며 서버의 파일을 통해 확인됩니다. Custom URL Scheme은 확인 없이 사용자 정의 프로토콜(myapp://)을 사용하므로 동일한 스킴을 등록한 다른 앱에 의한 가로채기에 취약합니다.
파일은 HTTPS 서버 루트의 /.well-known/apple-app-site-association(.json 확장자 없음)에 배치됩니다. 서버는 Content-Type: application/json을 반환해야 합니다. 중요: 리디렉션 없이 파일에 직접 접근할 수 있어야 합니다.
주요 원인: AASA 파일의 Team ID 또는 Bundle ID 오류, HTTPS를 통해 파일에 접근 불가, 리디렉션, 잘못된 Content-Type, 이전 버전 캐싱. Developer → Associated Domains Development를 통해 확인하고 기기를 재시동하여 캐시를 지우세요.
아니요 — Universal Link에는 apple-app-site-association을 호스팅하는 HTTPS 서버가 필요합니다. 도메인 없이는 Universal Link가 작동하지 않습니다. 대안: Custom URL Scheme(덜 안전함) 또는 자체 도메인이 있는 타사 서비스(Branch, Firebase).
아니요 — Universal Link는 iOS, iPadOS, watchOS, macOS를 위한 Apple의 독점 기술입니다. Android에서는 이에 해당하는 기능이 App Link(Android 6.0+)라고 하며, apple-app-site-association 대신 Digital Asset Links(assetlinks.json)를 사용합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.