관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 5. DeepLink (딥 링크) - URL Scheme과 Dynamic Link를 이용한 딥 링크 처리 방법 본문

iOS 응용 (swift)

[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

Comments