2023. 6. 4. 19:06ㆍ모바일어플개발/Flutter Tips
안녕하세요~ totally 개발자입니다.
이 포스팅은 제가 실제 플러터 앱 개발을 진행하며 파이어베이스 클라우드 메시징 (Firebase Cloud Messaging - 이하 FCM) 그리고 flutter_local_notification 패키지와의 연동 및 해당 기기에서의 알림 수신, 수신자가 알림을 탭 했을 때 특정 페이지로 이동하는 방법에 대해 Android, iOS 모두 그 방법에 대해 핵심적으로 요약하여 정리했습니다. 참고로 iOS의 APN 부분 등 기본 푸시 메시지 세팅 등은 여기에서 다루지 않고 FCM과 flutter_local_notification 부분만 다룹니다. 안드로이드를 위한 기본적인 내용은 여기에 정리해놓았으니 참고하시기 바랍니다.
https://totally-developer.tistory.com/144
먼저 FCM과 flutter_local_notification를 연동한 방법의 요약한 총 순서는 아래와 같습니다.
1) 파이어베이스 FCM 세팅 및 서버 키 발급
2) sendNotificationToDevice 메소드를 통해 FCM 전송
3) 수신자 측에서 FirebaseMessaging.onMessage.listen 또는 FirebaseMessaging.onBackgroundMessage 메소드를 통해 발신자의 FCM 수신 (이것만 하시면 실제 수신자 즉 사용자는 단순히 클라우드 메시지만 받은 것이기 때문에 알림이 있는지 모릅니다.)
4) flutter_local_notification 패키지를 사용하여 수신자의 디바이스 기기에 알림를 푸시(실제 수신자가 알림을 받는 부분)
5) 탭 했을 때 flutter_local_notification 패키지와 FIrebaseMessaging을 통해 액션을 만들어주면 됩니다. (아래에 상세 설명)
Step 1: 먼저 파이어베이스에서 FCM 세팅 작업을 해주셔야 합니다. 파이어베이스 콘솔에 진입하신 뒤에 Project Overview 오른쪽에 있는 설정 버튼을 누르시고 General 옆에 Cloud Messaging 탭을 선택해줍니다.
Step 2: 아래의 Add server key 작업을 통해 서버 키를 발급해주셔야 합니다. 그러면 아래처럼 Server key의 token이 발급된 것을 확인해볼 수 있습니다.
Step 3: 플러터로 가셔서 sendNotificationToDevice 메소드(이름 자유롭게 작명하시면 됩니다)를 만드시고 아래처럼 만들어줍니다. 참고로 이 코드는 플러터에서 구현하지 않고 php나 다른 백엔드 언어로 서버 단에서 구현하실 수도 있으니 아래처럼 사용할 수도 있는 것을 참고하시기 바랍니다. 서버 단에서 구현하는 경우는 지속적으로 디바이스의 토큰을 데이터베이스에서 가져와야 하기 때문에 플러터에서 구현하는 것보다 서버 단에서 구현하는 것이 좋을 수 있습니다. 이 부분은 개발 환경과 앱의 방향에 따라 다르게 적용하시면 됩니다.
Step 4: 테스트를 하실 분들은 아래 메소드를 통해 디바이스 토큰을 알아내실 수 있습니다. 실제 앱 개발하시는 분들은 이 Token들을 데이터베이스에 저장하셔서 따로 sendNotificationToDevice 메소드의 parameter로 디바이스 토큰을 전달해주셔야 합니다. 그리고 버튼을 누르면 sendNotificationToDevice 메소드를 작동시키면 됩니다. 저는 제 휴대폰의 기기의 토큰을 직접 입력했지만 실제로는 데이터베이스에서 가지고 와서 전달하는 방법을 고려해보셔야 합니다. 이 버튼을 누르면 발신자 측에서의 FCM이 전송됩니다.
Step 5: 이제 수신자 측에서 보겠습니다. 플러터가 크로스플랫폼 앱 개발이 주 목적이기 때문에 항상 안드로이드와 iOS 둘 다 생각을 해봐야 하고, 수신할 때의 앱 상태는 3가지가 있습니다. 앱이 실행된 경우(Foreground), 앱이 백그라운드에 있는 경우(Background), 앱이 완전히 닫힌 경우(Terminated) 이 3가지 경우를 1가지의 메소드로는 처리가 되지 않기 때문에 아래에서 소개하는 방법들을 적절하게 섞어 사용해야 합니다. 특히 알림을 탭해서 특정한 페이지로 이동하는 등 액션을 주어야 하는 경우에 그렇습니다.
1) Android & iOS Foreground (앱이 실행된 경우에 알림을 받는 경우)
FirebaseMessaging.onMessage.listen으로 FCM를 먼저 수신합니다.
여기에서 flutterLocalNotificationsPlugin의 show 메소드를 호출하여 알림을 줄 수 있도록 합니다. 그리고 initialize 부분에 onDidReceiveNotificationResponse 부분을 추가해서 액션 부분을 주면 됩니다. 만약 파라미터를 전달하고 받아야 하는 경우라면 listen((RemoteMessage message)를 활용하여 message.data에 접근한 뒤 message.data['test_parameter1'] 이런 방식으로 전달 받은 뒤에 show 메소드에 payload라는 파라미터를 String 데이터로 전달할 수 있습니다. 그것을 아래에 (details) 파라미터로 받는 것입니다. 그 후 details.payload로 데이터를 확인하시면 됩니다.
2) Android Background & Android Terminated & iOS Terminated (안드로이드 백그라운드, 앱 종료 상태 및 iOS 앱 종료 상태)
FirebaseMessaging.instance.getInitialMessage 메소드가 필요합니다. 예를 들어 아래처럼 사용하시면 됩니다.
또한 아래와 같이 onDidReceiveBackgroundNotificationResponse를 설정해주시면 됩니다.
3) iOS Background (iOS 앱 백그라운드 상태 -> 앱이 완전히 닫혀진 상태는 아니지만 백그라운드에서 작동중...)
탭했을 때 인식을 위해서 FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { }) 부분이 추가적으로 필요합니다. 즉 코드는 다음과 같이 구현하시면 됩니다.
if (Platform.isIOS) {
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
// 액션 추가 ... 파라미터를 전송하는 경우는 message.data['test_parameter1'] 이런 방식...
}
}
4) 백그라운드 상태에서의 FCM 수신을 위한 공통 사항
그리고 백그라운드 상태에서의 FCM 수신 준비를 위해 main 메소드에 FirebaseMessaging.onBackgroundMessage 부분이 필요하며 아래와 같이 구성하시면 됩니다.
먼저 main.dart 맨 윗부분에 다음을 추가합니다.
그 후, 96번째 줄처럼 await Firebase.initializeApp() 다음에 아래 줄을 추가하시면 됩니다.
여기까지 진행을 마무리하셨다면 세팅은 모두 마무리된 것이며 세부 액션(페이지 이동 등의 기능)만 앱 구현 상황에 따라 구현해주시면 됩니다. 보시다시피 안드로이드, iOS를 구현하는 것 뿐만 아니라 Foreground, Background, Terminated(종료)의 3가지 상황까지 즉 총 6가지 상황을 고려해야 하기 때문에 단순하지 않은 과정이며 먼저 이 원리를 파악하시고 어떤 경우에 어떤 메소드가 필요한지 이해하시는 것이 필요할 것으로 보입니다. 저는 위와 같은 과정으로 현재 개발 중인 앱에서 모두 테스트를 완료하여 수신자가 알림을 탭 했을 때 특정한 페이지로 이동하게끔 개발하였고 테스트 모두 성공하였습니다. 플러터 앱 개발에 도움이 되었기를 바랍니다. 감사합니다.
만약 안드로이드 백그라운드에서 푸시 알림이 제대로 오지 않는다면 아래 포스팅을 추가적으로 참고 및 진행하시기 바랍니다.
https://totally-developer.tistory.com/154
[전체 소스 코드]
[유튜브 강좌 영상]