딥링크(Deep Link)는 모바일 앱에서 푸쉬(알림)을 통해 특정한 화면 또는 기능으로 바로 이동할 수 있게 해주는 링크이다.
iOS에서 딥 링크는 URL Scheme 방식과 Universal Link 방식 두가지가 존재한다.
URL Scheme: Scheme을 XCode(URL Types, Queried URL Schemes)에 등록
Universal Link: 웹 사이트의 Domain을 이용하여 등록
여기서 URL Scheme 방식을 알아보도록 한다.
URL Scheme 방식에는 다른 앱에서 나의 앱을 호출 할 수 있도록하는 URL Types,
나의 앱에서 다른 앱을 호출 할 수 있도록하는 Queried URL Schemes가 존재한다.
먼저 기본적인 개념부터 알고가자.
URI(Uniform Resource Identifier): 특정 리소스 식별자
URL(Uniform Resource Location): 특정 리소스 위치
1번은 특정 리소스의 식별자를 의미하므로 URI
2번은 특정 리소스의 위치를 가르키므로 URL
웹과 앱의 Scheme가 다르다.
앱의 Scheme는 XCode 내부의 URL Types를 통해 등록하여야 접근이 가능하다.
또한 URL로 특정한 앱에 접근할 때 Query Prameter로 특정한 동작을 수행 할 수 있다.


상대방의 앱에서 나의 앱을 호출하는 방법이다.
애플에선 이미 지정된 URL Types에 따른 서비스를 제공한다.
ex) safari 검색창에서 tel://010-1111-1111 입력 후 엔터를 누르면,
전화번호 앱에서 present되는 화면 표출

커스텀으로 URL Types를 생성하여 나의 앱을 URL로 통해 실행시키도록 구현할 수 있다.
Xcode - Target - Info - 하단 URL Types

URL Schemes를 test-app으로 설정했을때,
“test-app://…” URL을 통해 나의 앱을 외부에서 호출할 수 있다.
여기서 Query Parameter를 붙여서 보낸다면, 받는쪽에서 URLComponents로 처리할 수 있다.
ex) ”test-app//navigation?name=main”
// ”test-app//navigation?name=main” 의 URL로 앱 호출했다고 가정
// 해당 scheme과 host를 가지고 있는지 파악
guard url.scheme == "test-app", url.host == "navigation" else { return }
// 원하는 query parameter가 있는지 파악
let urlString = url.absoluteString
guard urlString.contains("name") else { return }
let components = URLComponents(string: url.absoluteString)
let urlQueryItems = components?.queryItems ?? [] // [name=main]
var dictionaryData = [String: String]()
urlQueryItems.forEach { dictionaryData[$0.name] = $0.value }
guard let name = dictionaryData["name"] else { return }
print("값 = \(name)")
나의 앱에서 다른 앱을 호출할려면, Queried URL Schemes에 호출할려는 앱의 Scheme가 등록되어야 한다.
Xcode - Target - Info - Queried URL Schemes에서 row 추가
추가된 Scheme를 URL로 앱 호출 가능

// 나의 앱에서 상대방의 앱을 실행시키는 함수
func openOtherApp() {
guard let url = URL(string: "kakaotalk://") else {
return
}
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
// 상대방의 앱이 설치되지 않았을 경우 처리할 로직 추가
}
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else { return }
// URL 처리
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// URL 처리
}
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL { url in
// URL 처리
}
}
}
}