본문 바로가기
iOS

[iOS] Firebase 를 활용한 push 알림 (Remote Notification)

by Odin_1204 2022. 10. 14.
띵동~!! 택ㅂ...
잉?? 알림은 어떻게 보내지?!?

 

 

 

안녕하세요. 오딘(Odin)입니다.

 

저번 시간에는 Firebase를 Xcode에 넣고 사용하는 방법을 익혔는데요!!
https://odinios.tistory.com/11

 

이번에는 app을 사용하는 유저에게 필요한 알림을 제공하고 싶을 때

Firebase를 이용해서 push 알람을 보내보려고 합니다!!

 

Local 이냐 Remote 냐 에 따라 Noti 제공하는 방식이 다르니

같이 공부해보면서 만들어 볼까요??ㅎㅎ

 

 

 

 

 


 

 

Local Notificaion & Remote Notification 이란?

Local Notification : 지정된 시간에 보내주는 알림

- 앱 내에서 알림을 전달

- 정해진 시간 / 비슷한 컨텐츠

ex) 일기, 디데이 등

 

Remote Notification : 자유로운 시간대에 개발자가 자유롭게 보낼 수 있는 알림

- 서버에서 알림을 전달함

- 자유로운 시간 / 다양한 컨텐츠

ex) 카카오톡, 광고

 

 

저희가 이번에 하려고 하는 작업은 정해진 시간에만 Push 알림을 제공하는 것이 아닌

다양한 컨텐츠를 원하는 시간에 맞춤으로 Push알림을 제공해 주고자 하여
Remote Notification을 해보려고 합니다!!

 

Remote Notification은 위에도 나와 있듯이 서버에서 알림을 전달하는 방식이에요.

그런데 서버에서 알림을 전달하려면 apple sever에 있는 APNs 를 통해 알림이 보내진답니다.

그렇다면 APNs 란 무엇일까요??

 

 

APNs 란?

- Apple Push Notification service 의 약자로 알림 및 데이터를 OS X 및 iOS 기반 장치로 보내는 원격 알림 서비스입니다.

보안 연결을 통해 타사 알림을 보내는 데 사용됩니다. 이 서비스는 모든 타사 iOS 및 Mac OS 장치에 통합 된 API를 통해 제공됩니다.

 

간단하게 Push Notification에 대한 구조를 보자면

1. provider(서버) 에서 APNs에 noti 정보를 제공
2. APNs에서 device에 해당 noti를 전달

3. 전달 받은 정보를 clien App에 보여줌

 

다음과 같이 실행된다고 보시면 됩니다~

 

그러나 서버로 해당 작업을 하게 된다면 iOS만 적용이 가능한 Noti가 생성이 되고

android, web에는 따로 작업을 해주어야 하는 상황이 발생하게 됩니다..🥲

 

 

그래서 이러한 문제점을 해결해주기 위해 저희는 Firebase를 이용해서 해당 작업을 처리하고자 합니다!!

 

 

Firebase를 활용한 Push 알림

-> Firebase를 이용한 Push 알림 구조는 다음과 같습니다!!

 

 

1) apple severDivece Token에 대한 정보를 요청

2) Device Token 정보 받아옴

3) APNs 에서 받아온 Token에 대한 정보를 Message 대리자로 위임받은 Firebase에 제공

4) 업로드 해두었던 인증키 (p8)Device Token정보를 가지고 Noti Message 정보를 APNs에 전달

5) Device Token에 에 알맞는 Device에 push Noti 띄우기

 

휴우~~ 이제 전체적인 Push 알림에 대한 흐름은 정리가 되었으니

실제로 가능하도록 만들어볼까요?!?😆😆

 

 


잠깐!!

-> 만들기 전에 Push 알림을 사용하려면 무조건 지켜야 할 4가지가 있습니다.

 

⛔️ Remote Notification 주의 사항

1. 유료 개발자 계정

     ->앱을 출시 했는데 설마 개발자 계정이 아닐 경우가 있겠어...? 😬

 

2. 실제 iOS 기기

     -> 별도 설정을 하면 Xcode 11.4 이상 부터는 Simulator에서 푸시 수신 가능,  but - local 알람은 always 가능

 

3. 푸시 인증 key (p8)

     -> 인증서 종류로 p12 이후 등장, 재다운로드가 불가능 하므로 인증키 관리가 필요!! (최대 2개만 생성 가능!!)

 

4. XCode push/ Background 처리

     -> push 알림 설정과 background 상태에서도 noti를 받을 수 있도록 처리!

 

 

--> 1, 2번은 당연히 준비가 되었다는 가정하에 3, 4번을 진행해보겠습니다!!

      (하나라도 놓치면 실행이 안되니 주의하셔야 합니다~!!)

 


 

 

푸시 인증 Key (p8)

인증키 생성

푸시 알람을 보내기 위해서는 인증 key가 필요합니다.

그래서 Key를 한번 만들러 가볼게요~!!

 

apple Developder ->https://developer.apple.com/account/ 

해당 사이트로 들어가서 '인증서'를 누르고 '+' 버튼을 눌러 키를 만들어주세요!!

 

 

 

 

우리는 push 알림을 추가할 것이기 때문에 'Apple Push Notifications service(APNs)' 을 체크해주세요!!

 

 

 

 


 

~~~ 주의 사항!!! ~~~

1. 재다운로드가 불가능

그러니 미리미리 잘 정리해 두어야 겠죠??

 

2. Key는 최대 두 개만 만들 수 있음

재사용이 가능하니 걱정마세요~!!

 


 

 

다운로드 받으셨다면 인증키 만들기는 끝이 났습니다!!

인증키를 만드셨으니 해당 키를 Firebase에 등록 해주어야겠죠??

 

 

Firebase에 인증키 등록

Firebase 사이트로 가서 원하는 프로젝트로 들어가주세요.

 

 

프로젝트 개요 -> 프로젝트 설정에 들어가서 FireBase에 APN인증 키를 업로드 해볼게요!!

 

 

다음과 같이 3개를 입력하라고 나오는데요!!

같이 한 번 차근차근 넣어볼게요~!!

 

APN 인증키: 위에 만들어 두었던 인증키(p8)를 넣어주시면 됩니다!!

키 ID: 인증키를 등록하면 다음과 같이 등록된 파일이 나타나는데 여기서 빨간 박스 부분이 키ID 입니다.

팀 ID: apple Developer 사이트 -> Account -> 인증서 로 넘어가면 우측 상단에 빨간 박스에 해당하는 부분 입니다!!

왼쪽부터 키 ID, 팀ID

 

 

이제 인증키 생성 및 등록은 끝이 났습니다!!!

그러면 project에서 push 알림을 받을 수 있도록 처리하러 가볼까요~?!

 

 

 

XCode Push/ Background 처리

앱 화면이 push알림을 보내기 위한 push Notification을 추가해 주시고

Background 상태에 있어도 noti 알림이 올 수 있도록 Remote notification에 체크해주세요!!

 

 

이렇게 하면 기본 Setting은 끝이 났습니다!!

이제 Message 데리자 설정, Foreground noti, Background noti  등 에 대한 처리를 해야곘죠??

해당 처리 작업은  project 내부에서 해야 하므로 XCode로 가볼게요~!!

 

 

Project 내부에 Firebase Message 설정

Firebase에서 제공하는 순서에 맞게 진행했습니다.

Firebase-> https://firebase.google.com/docs/cloud-messaging/ios/client?authuser=0 

 

 

Firebase 연결 및 대리자 설정

didFinishLaunchingWithOptions
-> 함수 내부에서 앱이 시작 될 때 Firebase push 알림을 등록하고 Message에 대한 대리자를 위임합니다.

import FirebaseCore
import FirebaseMessaging


class AppDelegate: UIResponder {
	func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
		
        // firebase에 연결
    	 FirebaseApp.configure() 
        
        // 원격 알림 시스템에 앱을 등록
        if #available(iOS 10.0, *) {
          // For iOS 10 display notification (sent via APNS)
          UNUserNotificationCenter.current().delegate = self

          let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
          UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { _, _ in }
          )
        } else {
          let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
          application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()

        // 메시지 대리자 설정 (MessagingDelegate 상속 필요)
        Messaging.messaging().delegate = self
        	return true
    }
}

extension AppDelegate: UNUserNotificationCenterDelegate {

    // token 정보를 확인하고 싶다면 해당 Func을 실행하시면 됩니다~! (FCM registration token)
    func checkToken() {
    	Messaging.messaging().token { token, error in
          if let error = error {
            print("Error fetching FCM registration token: \(error)")
          } else if let token = token {
            print("FCM registration token: \(token)")
            self.fcmRegTokenMessage.text  = "Remote FCM registration token: \(token)"
          }
        }
    }

}

 

 

 

Firebase 에 DeviceToken 전달

didRegisterForRemoteNotificationsWithDeviceToken

-> 앱을 APN에 성공적으로 등록되면 해당 Method가 실행 되는데 이 때 Device Token에 대한 정보를 Firebase에 넣어줌 

 

UNNotification

-> Foreground 상태에서도 Noti를 받을 수 있도록 처리

 

UNNotificationResponse

-> Noti를 눌렀을 때 담겨있는 데이터를 뽑아 낼 수 있음 (UserInfo를 통해)

extension AppDelegate: UIApplicationDelegate {
	// UIKit은 앱을 APN에 성공적으로 등록한 후 이 메서드를 호출
    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    	// Firebase 에서 대리자로 APNs 토큰을 설정해주는 곳
  		Messaging.messaging().apnsToken = deviceToken
    }
    
    //포그라운드 알림 수신: 로컬 / 푸시 동일
    //카카오톡: 도이님과 채팅방, 푸시마다 설정, 화면마다 설정 가능
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        guard let viewController = (UIApplication.shared.connectedScenes.first?.delegate as?
                                    SceneDelegate)?.window?.rootViewController?.topVIewController else { return }

        //.banner, .list : iOS 14+
        completionHandler([.badge, .sound, .banner, .list])
    }
    
    //푸시 클릭: 카카오톡 푸시 클릭 -> 카카오톡 푸시 온 채팅방으로 바로 이동
    //유저가 푸시를 클릭했을 때만 수신 확인 가능
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print("사용자가 푸시를 클릭했습니다.")
        print(response.notification.request.content.body)
        print(response.notification.request.content.userInfo)
        
        let userInfo = response.notification.request.content.userInfo
        if userInfo[AnyHashable("sesac")] as? String == "project" {
            print("SeSAC Project")
        } else {
            print("NOTHING")
        }
    }
}

 

토큰 갱신 모니터링

didReceiveRegistrationToken

-> 토큰이 갱신 될 때 불리는 Func으로 새로운 토큰에 대해서 전달

extension AppDelegate: MessagingDelegate {
    //토큰 갱신 모니터링 : 토큰 정보가 언제 바뀔까?
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
      print("Firebase registration token: \(String(describing: fcmToken))")

      let dataDict: [String: String] = ["token": fcmToken ?? ""]
      NotificationCenter.default.post(
        name: Notification.Name("FCMToken"),
        object: nil,
        userInfo: dataDict
      )
      // TODO: If necessary send token to application server.
      // Note: This callback is fired at each app startup and whenever a new token is generated.
    }
}

 

 

 

 

Push 알림 보내기

자!! 이제 모든 준비는 끝이 났습니다~!!

push 알림을 보내볼까요?!

 

 

참여 -> Messaging 부분에 들어가서 캠패인을 만들어 볼게요~

 

 

 

 

저희는 앱이 Background에 있어도 Noti를 보내는게 만드는게 목표이니

Firebase 알림 메시지를 선택해주세요~!

 

 

 

 

 

 

이렇게 해주면~~

 

 

 

 

 

 

짜잔!!! 🎉🎉

다음 처럼 노티가 왔어요~!!ㅎㅎ

 

조금 복잡하고 하나라도 놓치면 안되지만 

차근차근 하시면 하실 수 있으실거에요~!!