일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- RxCocoa
- 리팩토링
- combine
- 클린 코드
- ribs
- HIG
- 애니메이션
- Observable
- map
- Refactoring
- MVVM
- SWIFT
- clean architecture
- swiftUI
- rxswift
- UITextView
- ios
- collectionview
- Clean Code
- UICollectionView
- 리펙토링
- Protocol
- tableView
- Human interface guide
- 리펙터링
- uiscrollview
- 스위프트
- uitableview
- Xcode
- swift documentation
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 5. DeepLink (딥 링크) - URL Scheme과 Dynamic Link를 이용한 딥 링크 처리 방법 본문
[iOS - swift] 5. DeepLink (딥 링크) - URL Scheme과 Dynamic Link를 이용한 딥 링크 처리 방법
jake-kim 2021. 10. 11. 20:47
1. DeepLink (딥 링크) - 앱 푸시, APNs (Apple Push Notification service ) 개념
2. DeepLink (딥 링크) - URL Scheme, URLComponents, Foreground, Background, Not Running 기초 개념
3. DeepLink (딥 링크) - FCM(Firebase Cloud Messaging) remote 푸시 사용 방법
4. DeepLink (딥 링크) -Dynamic Link (다이나믹 링크) 사용 방법 (Firebase, 공유하기 기능)
5. DeepLink (딥 링크) - URL Scheme과 Dynamick Link를 이용한 딥 링크 처리방법
cf) Push Notification 처리 관련 메소드 총 정리 글은 이 포스팅 글 참고
Deep Link 방식
- URL Scheme
- URL을 Xcode에서 정의하여, 그 URL을 앱이 아닌 곳에서 탭하면 해당 앱으로 이동시키고, 앱에서 그 URL을 받아 파싱하여 원하는 페이지로 이동시키는 방법
- 단점은 앱이 설치되어 있을 경우만 동작하고, 설치되어 있지 않으면 아래와 같은 문구 표출
- Dynamic Link
- 앱이 미설치 되어 있어도 딥링크 기능 가능: 친구에서 새로운 앱에서의 특정 페이지 공유받은 경우 > 앱 설치 링크 오픈 > 설치 후 직접 찾아가지 않아도 Dynamic Link를 사용하면 설치 후 링크 정보가 남아있어서 바로 공유 받은 페이지로 자동으로 이동
- 친구에게 앱에 특정 페이지를 링크로 줄 때, Dynamic Link에서 Redirection 링크를 만들어서 줄 수 있고 특정 사진을 포함하여 공유 메시지를 커스텀하여 공유 가능
- FCM과 같은 Provider Server 솔루션을 통해서 사용
- Universal Link
- Universal: '만능의'
- Universal Link란, 사용자가 딥링크 URL을 탭한 경우 현재 앱이 설치되어 있지 않으면 Web Page를 띄워주고 앱이 설치되어 있다면 앱을 띄워주는 기능
- Link하나로 앱이 설치되어 있는지 유무에 따라 웹이나 앱을 띄워주는 기능
- 애플은 2015년, iOS 9.2버전부터 URL Scheme보다는 Universal Link를 구현이 사용자 경험을 향상시키기 있기 때문에 URL Scheme 방식보다 지향
- 서버 + 앱 + 웹 작업이 동시에 이루어져야 구현이 가능하므로 번거로움이 존재하는 단점
URL Scheme을 이용한 Deep Link 준비
Deep Link 방식 2가지
1) present로 Deep Link 타켓 화면만 띄워주는 방법
- 사용자가 push나 링크를 탭하면 이동하려는 화면을, 현재 보고있는 화면과 문맥이 다르므로 해당 화면만 resent로 띄워주는 것
2) Deep Link 타겟 화면을 거쳐가는 모든 화면을 순서대로 띄워주는 방법
- 타겟 화면을 거쳐가는 화면들을 기존에 화면전환 하던대로 차례대로 띄워주는 방법
딥링크 준비
상황) 로그인이 되어 있으면 세번째 화면에 promotion코드를 바로 보여주고, 로그인이 되어 있지 않으면 로그인했을때 바로 세번째 화면으로 이동 후 promotion코드 표출
- url 정의
my-app://navigation?target=thirdScene&promotionCode=K1aBqd
- Firebase > Cloud Messaging에서 생성
- 관련 개념은 여기 참고
- AppDelegate에서 URL 파싱
// FCM에서 푸시를 탭했을 때 url 처리
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
let userInfo = response.notification.request.content.userInfo
print(userInfo)
print(userInfo["url"] as? String)
guard let deepLinkUrl = userInfo["url"] as? String,
let url = URL(string: deepLinkUrl) else { return }
// 해당 host를 가지고 있는지 확인
guard url.host == "navigation" else { return }
// 원하는 query parameter가 있는지 확인
let urlString = url.absoluteString
guard urlString.contains("target"), urlString.contains("promotionCode") else { return }
// URL을 URLComponent로 만들어서 parameter값 가져오기 쉽게 접근
let components = URLComponents(string: urlString)
// URLQueryItem 형식은 [name: value] 쌍으로 되어있으서 Dctionary로 변형
let urlQueryItems = components?.queryItems ?? []
var dictionaryData = [String: String]()
urlQueryItems.forEach { dictionaryData[$0.name] = $0.value }
guard let target = dictionaryData["target"],
let promotionCode = dictionaryData["promotionCode"] else { return }
print("결과 = \(target), \(promotionCode)")
switch DeepLinkTarget(rawValue: target) {
case .thirdScene: routeToThirdScene(with: promotionCode)
default: return
}
}
enum DeepLinkTarget: String {
case thirdScene
}
Deep Link 처리 - present로 타겟 화면 하나만 띄워주는 방법
- 로그인이 되어있는지에 관한 상태를 UserDefualts에 기록, 만약 로그인이 필요한 화면이라면
- 딥링크 시작 > 로그인이 이미 완료되어 있는 경우 > 바로 화면 띄우기
- 로그인이 완료되면 바로 나오는 페이지의 ViewWillAppear에 UserDefaults의 didLogin를 true로 기록
class ViewController2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "로그인 완료 시 첫 화면"
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UserDefaults.standard.set(true, forKey: "didLogin") // <-
}
}
- AppDelegate에서 window.rootViewController의 객체를 참조하여 present
private func routeToThirdScene(with promotinoCode: String) {
// 타겟 화면인 ViewController3 초기화
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
guard let viewController3 = storyboard.instantiateViewController(withIdentifier: "ViewController3") as? ViewController3 else { return }
viewController3.promotionCode = promotinoCode
/// 이미 로그인 이 된 경우, 바로 present
if UserDefaults.standard.bool(forKey: "didLogin") {
// 타겟 화면을 띄울 window의 rootViewController 참조
let sceneDelegate = UIApplication.shared.connectedScenes.first?.delegate as! SceneDelegate
let rootViewController = sceneDelegate.window?.rootViewController
rootViewController?.present(viewController3, animated: true, completion: nil)
}
}
- 딥링크가 로그인전에 시작되고, 유저가 로그인하면 바로 해당 화면이 present되게하고 싶거나, 해당 화면을 거쳐가는 화면들을 모두 보여지도록하는 deep link를 구현하고 싶은 경우 PostTaskManager 와 같은 객체를 만들어서 모든 화면에 주입해주고 각 화면에서는 viewDidAppear에서 task가 있는지 확인하고 deep link task가 있다면 다음 화면으로 이동되는, 연쇄적으로 동작하도록 구현
* 전체 소스 코드: https://github.com/JK0369/ExDeeplink
* 참고
- Universal Link: https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html