본문 바로가기
Swift 개발 이야기

iOS Push Notification / Silent Push 에 대해 Araboza

by 방화동한량 2021. 2. 18.
728x90

굿데이 여러분 2021 잘 보내구 계신가여 올해 첫글을 2월에 쓰게 되다니 반성합니다

 

오늘은 Push Notification 에 대해서 알아보게씀니다

 

iOS 10 이상 기준으로 진행할건데여 카카오톡도 12.0 이상 부터 지원하는 현 시대에 그 이하는 쳐다도 안보는 것이 좋다구 생각함니다

 

먼저 UNUserNotificationCenter 의 델리게이트를 AppDelegate 내에서 설정해줍니다 바로 didFinishLaunchingWithOptions 에서 해주면 되겠쥬? 저는 fcm 을 통해서 테스트할것이기 때문에, 이부분도 같이 셋팅해주겠읍니다 

 

사실 여기서 확인하셔도 됩니다 (https://firebase.google.com/docs/cloud-messaging/ios/client?authuser=2

 

참고참고

 

class AppDelegate {


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

	UNUserNotificationCenter.current().delegate = self
    Messaging.messaging().delegate = self


	let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
	UNUserNotificationCenter.current().requestAuthorization(
    options: authOptions,
    completionHandler: {_, _ in })
    
    application.registerForRemoteNotifications()
 
 	return true
    
 	}

}

 

이렇게 델리게이트를 설정하면 UNUserNotificationCenterDelegate 의 두가지 함수를 이용해서 푸시를 구현할 수 있읍니다

 

extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        let userInfo = notification.request.content.userInfo
        
        print(userInfo)
        
        completionHandler([.alert, .sound])
    }
    
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
       let userInfo = response.notification.request.content.userInfo
       
       print(userInfo)
        
        completionHandler()
        
    }

}

 

willPresent 는 앱이 foreground에 있을 때 사용되는 함수구여

 

didReceive 의 경우는 앱이 background 에 가있을때나 종료되어 있을 때 호출되는 함수입니당

 

자 그럼 먼저 앱이 켜져있을때 어떻게 처리해야할지 보게씀니다

 

관련된 정보는 바로 notification 에 담겨서 오는데여

 

저희가 보고 싶은 정보는 바로 notification.request.content.userInfo 안에 담겨있습니다 겁나 꽁꽁 숨겨있쥬?

 

이제 뭐 사람마다 다르겠지만 저는 개인 테스트할때는 간단하게 노드와 익스프레스를 이용해서 개별기기로 푸시를 보낼수있게 만들어놓는데여 

 

아주 간단한 코드이구 firebase 튜토리얼에도 나와있으니 참고하시면 됨니다 드디어 제 블로그에도 서위퍼터 말고 다른 언어가 추가되네여

 

app.get('/sendPush', (req, res) => {

    var message = {
        apns: {
          payload: {
            aps: {
              badge: 1,
              sound: "default",
                title: "Title",
                body:"Push Test",
            },
          },
        },
        token: "fcmToken",

      };

admin.messaging().send(message)
  .then((response) => {
    res.send(response);
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    res.send(error);
    console.log('Error sending message:', error);
  });
})

 

정말 간단하져? 이렇게 푸시를 보내게 되면~ userInfo 에 관련된 정보가 담겨서 온다~이말입니다.

 

그런데 이 userInfo 는 [AnyHashable: Any] 타입을 준수하는 딕셔너리이기 때문에, 이 데이터를 활용하려면 필요한 정보를 파싱해서 쓰시면 되게씁니다 참 쉽죠?

 

그러면 마지막에 CompletionHandler 뒤에 붙어있는 .alert 과 .sound 는 무엇인가 하니 푸시가 도착한 이후에 어떤 행동을 할것인가에 대해서 지정을 해주는 겁니다. sound 는 말그대로 소리로 알려주구여, .alert 까지 지정해주면  백그라운드에 있을때처럼 상단에 수신된 푸시메시지가 확인됩니다 두개 다 해주는게 좋겠져? 다른 옵션으로는 .badge 가 있읍니다 이건 그 홈에서 확인하는 빨간 1 올라가는겁니다 실행중일때는 바로 푸시가 확인되니까 안해주는게 좋다구 생각해여

 

iOS 14 이상부터 지원하는 .list 와 .banner 가 있는데, 이건 일단 패쓰할게여 사용이 안됨,,,

 

자 이 다음은 didReceive 일때 체크해볼까여?

 

사실 별차이 없읍니당

 

여기는 notification 이 response 에 또 한번 감싸져서 오기 때문에, 이부분만 추가해서 진행해주시면 댑니다

 

백그라운드에서 작업되기 때문에 핸들러에서 추가적으로 해줘야할 건 없읍니당

 

아 그런데 만약 payload 안에서 badge 와 sound 의 value 를 넣어주지 않으면 ㅇ무리 해도 진동조차 안오니 이부분은 서버쪽과 꼭 확인해보십셔!!

 

SILENT PUSH NOTIFICATION

 

자 이렇게 기본적인 푸시 구현은 끝냈는데, Silent Push 는 또 무엇일까여? 말그대로 푸쉬를 보내지만 유저는 그걸 알수가 없어여 물밑작업을 한다고 하쥬? 백그라운드에서 앱 데이터를 갱신한다던가 할때 사용한다구 하는데, 사실 저는 실무에서 써본적은 없어여...실사용예를 보고 싶은 이밤

 

여튼 알아보게씁니다

 

애플이 친절하게 공식문서를 써놨군여

 

https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app

 

Apple Developer Documentation

 

developer.apple.com

하지만 뭐 저희가 공식문서만 보고 살순 없잖아여? 영어니까

 

그리구 fcm 과 연결해서 하려면 좀 더 작업이 필요해서...사실 이거 정리하려고 쓴글입니다..

 

자 바로 가보시져 먼저 기존 푸시와는 다르게 프로젝트에서 추가해야할게 있읍니다

 

요 프로젝트 안에 Signing&Capabilities 의 백그라운드 모드에서 Remote notifications 를 활성화시켜주세여 자 준비끝

 

 

이 부분은 기존 푸시 수신할때 사용하는 두 함수와는 다른 친구를 써야하ㅣㅂ니당 

    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print(userInfo)
        completionHandler(.newData)
    }

 

에잉 이게 끝인가여 하실 분들이 계신데 네 맞습니다 맞고요

 

하지만! 중요한건! 서버쪽에서 메시지를 보내줄때입니다 이거 찾느라 아주 혼쭐이남

 

iOS 13 이전부터는 payload 부분에 content-available: 1 만 추가해주면 끝났는데 이젠 그게 아니래여 그럼 우째야 하나?

 

그냥 바로 알려드립니다 ;; 헤더에 이 두 값을 넣어주세여 apns-priority / apns-push-type 위치가 중요합니다!!

    var message = {
        apns: {
              headers: {
               "apns-priority":"5",
               "apns-push-type":"background"
           },
          payload: {
            aps: {
             'content-available':1,
              badge: 1,
              sound: "default",
                title: "Title",
                body:"Push Test",
            },
          },
        },
        token: "fcmToken",

      };

 

자 이렇게 해서 메시지를 발송하고 앱 내에서 테스트를 해보면 아주 깔쌈하게 badge 와 sound 가 설정되어있어도 조용하게 푸시가 수신되는것을 확인할 수 있습니다

 

그럼 다음시간에 또 만나유 안녕~~~~