관리 메뉴

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

[iOS - swift] 3. DeepLink (딥 링크) - FCM(Firebase Cloud Messaging) remote 푸시 사용 방법 본문

iOS 응용 (swift)

[iOS - swift] 3. DeepLink (딥 링크) - FCM(Firebase Cloud Messaging) remote 푸시 사용 방법

jake-kim 2021. 10. 8. 23:20

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 처리 관련 메소드 총 정리 글은 이 포스팅 글 참고

 

* 딥링크 적용 사례

  • Push - 3번 방법 (해당 글)
    • FCM과 같은 Server Provider 솔루션을 사용하여, 사용자에게 푸시를 발송하고 푸시를 탭한 경우 푸시 안의 URL을 분석하여 딥링크 처리
  • Dynamic Link - 4번 방법
    • 앱에서 링크를 친구에게 공유하여 그 친구가 링크를 타고 들어가면 프로모션 혜택이 적용되거나 특정 화면 이동

FCM

Apple Developer에서 생성하는 .p8 형식의 키

  • .p8 없이 Provider Server가 푸시를 보내려면 푸시 전용 certificate 인증서를 따로 만들어야하는 점이 존재
  • .p8이 있다면 development버전과 ad-hoc 구분 없이 푸시를 받을 수 있는 편리함 존재
  • .p8이 없이 Push 설정하려면 Apple Developer 사이트에서 App Identifiers에 Certificate를 따로 등록해야 가능
    • 또 Certificates는 development와 Ad-hoc버전이 나누어져 있으므로 .p8키값 사용을 권장

FCM을 사용 준비

1) Apple Developer 사이트의 Apple 푸시 알림 인증 키 .p8 생성

  • Apple 푸시 알림 인증키가 필요한 이유: FCM에서는 이 값을 이용하여 APNs에 인증값으로 송신
  • Apple Developer > 계정 > Certificates, Identifiers & Profiles > Keys 탭

  • Create a Key 혹은 Keys 옆에 있는 `+` 버튼 탭하면 아래 화면 등장 > Key name과 ENABLE 체크 후 Continue

  • Register 

  • 아래 나와있는대로 다운로드 할 수 있는 파일이 있고 이 파일을 한번 다운받으면 다시 다운받지 못하므로, 잃어버리지 않게 보관 필요

  • 다운로드를 누르면 .p8 형식의 푸시 인증서 키 확인

2) Apple Developer에 App Identifiers 생성

  • 이미 App ID가 만들어져 있다면 이 단계는 패스
  • 새로운 App Id 생성

 

  • continue

  • continue

  • Description과 Bundle ID를 입력한 후에 스크롤하여 아래로 내려간 후 Push Notifications 체크 활성화 필요

  • Push Notification 체크 후 Continue

  • 생성된 것을 확인

3) Firebase에 프로젝트 등록

  • firebase console > 프로젝트 추가(이미 프로젝트가 있다면 그 안에다가 새로운 앱 등록 가능)
    • Firebase에서는 프로젝트 갯수에 제한이 있기 때문에 프로젝트 안에 여러 앱 등록 방법을 추천

  • 프로젝트 > + 클릭 > iOS 클릭

  • 앱 추가 > GoogleService-info.plist 다운로드 

  • Xcode에 GoogleService-info.plist 추가

  • Firebase를 Xcode에 연동
    • swift package manager에서 아래 검색 후 설치
https://github.com/firebase/firebase-ios-sdk.git
  • FirebaseMessaging 체크 후 Add Package

  • App Delegate에서 Firebase 초기화

4) Xcode에서 Push Notification 기능 활성화

Push Notification 활성화

5) device token 등록

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()
        registerRemoteNotification()

        return true
    }

    private func registerRemoteNotification() {
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        let options: UNAuthorizationOptions = [.alert, .sound, .badge]
        center.requestAuthorization(options: options) { granted, _ in
            // 1. APNs에 device token 등록 요청
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
  • device token을 APNs에서 받으면 Firebase에 device token 등록
    // 2. APNs에서 `device token 등록 요청`에 관한 응답이 온 경우, Provider Server인 Firebase에 등록
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }
  • 딥링크 url을 받을 델리게이트 구현
    • SceneDelegate파일이 있다면, SceneDelegate의 scene(_:openURLContexts:)에서 url 수신
    • SceneDelegate가 없다면, AppDelegate의 application(_:open:options:) -> Bool에서 url 수신
    • 단, Firebase dynamic link를 사용한다면 AppDelegate의 userNotification(_:didReceive:)에서만 수신되므로 이곳에서 구현하는 것을 지향
  • 예제에서는 SceneDelegate가 있다고하고 scene(_:openURLContexts:)에서 url수신
  • Provider Server (Firebase)에서 딥링크로 아래에서 설정할 key값은 url, value값은 아래처럼 설정할 것으로 기억

  • AppDelegate에 위 링크를 파싱하는 코드 추가
    // my-app://navigation?name=jake
    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("name") 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 name = dictionaryData["name"] else { return }

        print("네임 = \(name)")
    }

6) Provider Server인 Firebase에 1)번 단계에서 발급한 .p8파일 업로드

  • 앱 설정 클릭 (프로젝트 설정)

  • 클라우드 메시징 클릭

  • 1)번에서 발급한 push 키 .p8 업로드, 키 ID와 팀 ID입력
    • 키 ID는 발급한 곳에 존재 (Certificates, Identifiers & Profiles > Keys > 아까 만든 key 클릭하면 확인 가능)
    • 팀 ID는 Apple Developer > 계정 > Membership에 존재

7) Provider Server인 Firebase에서 앱으로 푸시 전송

  • iOS에서 앱이 푸시를 받는 원리: Provider Server에서 푸시 전송 요청  > APNs에서 수신 > APNs에서 auth 인증, key 인증 후 Provider Server와 앱에 전송
  • Firebase 콘솔 > 설정 > 클라우드 메시징 탭 > Send Your first message 클릭

  • 푸시 메시지 내용 입력

  • Push에 딥링크 url정보 넣는 방법
    • 콘솔 > 추가 옵션 부분에서 맞춤 데이터에 key-value쌍으로 삽입하면 완료
    • 주의: 입력할 때 ""와 같은 큰따옴표를 입력하면 파싱할 때 어려움이 있으므로 문자열이라도 큰 따옴표 없이 하는것 주의

  • 항목에 대해서 입력해 나가고 `검토` 버튼을 누르면 캠페인이 자동으로 생성
    • 캠패인: 푸시 내용에 대해서 세팅했던 값이 저장

  • 푸시 확인
    • 주의: simulator에서는 APNs에 device token요청을 하면 등록이 되지 않기 때문에 실물 device에서 사용해야 테스트 가능

  • AppDelegate에서 딥링크 url 처리
    • 사용자가 푸시를 탭한 경우 호출되는 델리게이트 userNotificationCenter(_:didReceive:) 메소드에서 url 확인
extension AppDelegate: UNUserNotificationCenterDelegate {

    ...

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
        print(response.notification.request.content.userInfo)
    }
}
  • "url"부분을 파싱하여 딥링크 처리
// 결과

[AnyHashable("aps"): {
    alert =     {
        body = "\Uc54c\Ub9bc \Ud14d\Uc2a4\Ud2b8";
        title = "\Ud478\Uc2dc \Uba54\Uc2dc\Uc9c0 \Ud14c\Uc2a4\Ud2b8 \Uc81c\Ubaa9";
    };
    badge = 1;
    "mutable-content" = 1;
}, 
AnyHashable("google.c.fid"): eNqS247ay00TlrnaEbt0CG, 
AnyHashable("google.c.a.e"): 1, 
AnyHashable("url"): "my-app://navigation?name=jake", 
AnyHashable("google.c.a.c_id"): 8913753677916977018, 
AnyHashable("google.c.a.udt"): 0, 
AnyHashable("gcm.message_id"): 1633859324973797, 
AnyHashable("google.c.a.ts"): 1633859324, 
AnyHashable("gcm.n.e"): 1, 
AnyHashable("google.c.a.c_l"): 푸시 메시지 테스트 제목, 
AnyHashable("google.c.sender.id"): 1018046236453]

Cloud Messaging에서 `테스트 메시지 전송` 사용 방법

  • 테스트 메시지 전송 클릭

  • `FCM 등록 토큰 추가`화면에서 필요한 FCM 등록 토큰을 구하는게 필요

  • App Delegate에서 `Messageing.messaging().token {...}`을 추가한 다음에 token값을 출력 후 위에다 복붙하면 완료
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    FirebaseApp.configure()
    registerRemoteNotification()

    Messaging.messaging().token { token, error in
        print("토큰 = \(token)") <-- 여기
    }

    return true
}

* 전체 소스 코드: https://github.com/JK0369/ExDeeplink

 

* 참고

- Firebase: https://firebase.google.com/docs/cloud-messaging/ios/client?hl=ko 

- Firebase with Swift Package Manager: https://firebase.google.com/docs/ios/swift-package-manager

Comments