-
Notifications
You must be signed in to change notification settings - Fork 0
Firebase FCM Guide 2
앱 최상단에 작성 해주셔야 합니다 간혹 타 사이트에 작성 된 설명을 보면 class 내부에 작성 해둔 부분들이 많이 보입니다 . 그래서 사실 검증을 위해 공식 문서에 FCM 관련된 설명을 찾아보니 이렇게 작성되어 있습니다 .
https://firebase.google.com/docs/cloud-messaging/flutter/receive?hl=ko&authuser=0
final GlobalKey navigatorKey = GlobalKey();
위 부분은 사용자가 내 메세지를 수신하고 클릭시 내가 원하는 화면으로 이동시키기 위해 사용하였습니다.
현재 프로젝트는 go router을 사용중이기 때문에 gorouter 내부에도 추가해주시면 됩니다.
PushNotification 이라는 class를 만들고 앱 시작 단계에서 실행하기 위한 함수를 하나 선언 했습니다 . 이때 requestPermission부분은 내가 필요한 부분에 대한 권한을 요청하기 위해서 추가했습니다. 따로 PermissionHandler이라는 패키지를 사용하셔도 되지만 이부분이 더 간단하기때문에 FirebaseMessaging내부에 있는 로직을 활용했습니다.
FCM토큰을 디바이스에서 추출하고 디바이스 내부 저장소에 저장하는 로직을 추가하였습니다. 그냥 유저에게 그때그때 계속 호출해도 되지만 더 호출속도를 최대한 단축시켜서 검증할수 있고 앱을 실행할때 시간을 최대한 단축 시키기 위해 사용했습니다.
메세지 수신 후 어디로 보낼지 우선 임의로 설정하기 위해서 gorouter를 활용해서 MyPage로 이동 시켜보기 위해서 임의로 작성했습니다 원하시는 경로에 추가하시면 됩니다.
앱이 foreground상태일때도 알림을 수신 하기 위해 추가하였습니다. 이때 alert와 sound를 false로 처리한 이유는 localNotification을 활용해서 그부분을 만들어 줄거라서 제외 했습니다. 만약 True하고 local까지 활성화 하시면 foreground상태일때는 알람이 2번 전송되게 됩니다.
FirebaseMessaging.onMessageOpenedApp.listen(handleMessage);
이부분은 message를 tap했을때 내가 요청한 페이지로 진입시키기 위해서 적용했습니다. 그냥 onMessage를 하게되면 클릭 하셔도 페이지로 진입하지 못하고 알람만 수신 됩니다.
이제 LocalNotification을 구현 해보겠습니다.
이부분은 Android 8.0 이상부터 모든 알림에 채널이 할당 되어야 합니다. 그래서 추가하였습니다. importance: Importance.max는 이 채널의 알림이 최고 중요도를 가짐을 의미합니다. 이는 알림음, 진동, 헤드업 알림 등의 동작에 영향을 줍니다. 이부분은 원하시는부분에 맞게 설정하시면 됩니다. 우선 임의테스트를 하기위해 max를 사용했습니다.
로컬 알림을 위한 셋팅을 전부 했습니다. refresh를 하는 이유는 유저가 앱을 삭제 하거나, 디바이스가 변경되면 토큰값이 변경됩니다. 이때 변경된 수정하기 위한 작업입니다.
이제 추가했던 부분에 대한 함수도 main함수가 실행될때 같이 실행 할수 있게 추가해주시면 됩니다.
main 함수에 initNotification을 추가하였고 아까 하지 않았던 background message를 처리하는 로직을 추가하였습니다.
여기까지만 하셔도 기본 FCM 구성은 끝입니다.
이제 앱을 실행 하시면 로그로 토큰을 얻으실 수 있습니다 .
여기서 나온 토큰을 복사 하신 후에 firebase로 이동 후
이부분에 진입 하셔서 차례대로 선택해주시면 됩니다.
여기에 토큰 복사하신 토큰 키를 입력해주시면 메세지를 확인해볼수 있습니다. foreground, background 모두 수신이 되며, 화면전환까지 잘 되는 부분을 확인하실수 있습니다.
이 이후부터는 자신이 현재 구현하는 상태에 맞게 설정 해주시면 됩니다.
몇가지 방법들을 미리 설명 하겠습니다.
- fcmToken을 firebaseStorage에 저장하는 방식
단계 순서 // 토큰 발급 > 유저 Preference 저장 > 로그인 or 회원 가입시 firebase db에 저장 > user DTO에 fcmToken 컬렉션 추가 > 로그아웃시 null 처리 이방식의 장점은 매우 간결하고 쉽게 토큰을 관리 할 수 있습니다. 단점은 채팅방 / 어떠한 포스팅에 댓글, 대댓글, 좋아요, 친구신청, 이런기능들에 즉각대응이 어렵습니다. 반드시 firestorage를 읽어야 하기 때문에 느립니다. 그리고 데이터가 쌓이면 index를 읽어야하는 양도 늘어나기때문에 규모가 커질수록 관리가 어려워집니다. 로그아웃 시 null 처리는 어떤 회원가입 생태계를 보유하고 있냐에 따라서 갈라집니다. 예를들어서 한명이 한개의 계정만 소유할수 있는 시스템의 경우엔 상관없습니다. 하지만 그게 아니라 한명이 다계정을 소유할수 있는 시스템일때 로그아웃시 token을 보관한다면 A아이디를 쓰다가 B아이디로 로그인한 상태인데 A아이디에 가야할 알림까지 구독됩니다. 그래서 null처리를 해줘야 합니다.
- RealTimeDataBase 활용하기
단계순서 // 토큰 발급 > 유저 Preference 저장 > 로그인 or 회원가입시 rtdb에 맞는 필드에 저장 > 로그아웃 시 null 처리 rtdb는 즉각적으로 필요한 필드만 읽어올수 있습니다. 그리고 프론트 to 프론트 상의 알림이 필요한 부분에 적합합니다. serverless 상태의 체계로 구현할때는 이 방식이 선호도가 가장 높습니다. 데이터가 불안정한 상태일때도 알림 처리가 문제가 없습니다.
- server구축하기 사실 이 시스템이 가장 권장되는 방식입니다. 하지만 현재 시스템상 서버를 가지고 있지 않고 시도 할수 없다고 생각하고 규모가 커지기 전엔 고려해볼 생각이 없기때문에 패스 하겠습니다.
현재 rtdb가 채팅방이 완벽히 구현되기 전입니다. 그래서 우선은 임의로 사용하기 위해서 서버에 저장하고 보내는 1번 방식을 사용해 보겠습니다. 차주 내로 rtdb시스템을 적용하여 2번 사항도 위키에 업데이트 예정입니다.
기존 코드에 서버에 저장해두는 함수 추가
우선은 컬렉션을 활용하지 않고 임의 단계 테스트기때문에 userField에 추가했습니다 .
구독형 매핑 추가 이부분을 추가하는 이유는 firebase가 fcm을 네이밍과 함께 자동 매핑해서 보관합니다 . 그래서 functions로직을 만들어서 전체 메세지 (업데이트, 이벤트) 이런 전체알림을 보내야 하는 상황일때 사용할수 있습니다.