본문 바로가기
Tech/flutter

Flutter - Node js - FCM으로 서버에서 푸시 보내보기

by 패드로 2021. 5. 10.

개인앱이나 회사 서비스를 만들다보면 채팅, 마케팅 메시지 목적으로 푸시 메시지를 보내야하는 경우가 있습니다.

 

[본 포스팅은 Flutter 프로젝트에 firebase 등록 및 설정이 완료되었다는 가정에서 작성되었습니다 :) ]

등록 안하신 분들은 등록을 먼저 진행해주세요

 

Flutter 앱에 Firebase 추가

Flutter 앱에 Firebase 추가plat_iosplat_android 이 가이드에 따라 Flutter 앱에 Firebase 제품을 추가하세요. 참고: Firebase는 Flutter와 같은 프레임워크를 최선의 노력으로 지원합니다. 이러한 제품 추가는 Fireba

firebase.google.com

아이폰은 추가로 Push Notification 쓸 수 있게 설정이 필요합니다.(까다로운 아이폰)

 

[Apple] Apple push notification service (APNs) 설정하기

Apple push notification service (APNs) key 설정하기 iOS 앱으로 푸시 알림을 보낼 수 있도록 APNs 인증서와 키를 발급해보자. APNs란? APNs는 Apple push notification service의 줄임말로, iOS에 표시되는 푸..

spiralmoon.tistory.com

위 링크에서 발급된 APN 키는 firebase의 아이폰 프로젝트 설정에서 APN 키를 업로드 해주어야 합니다.

 

FCM 이란?

앱 사용하면 푸시 많이 받아보시죠? 그걸 위한 기능입니다.

FCM이란 Firebase Cloud Messaging으로, 무료로 메시지를 안정적으로 전송할 수 있는 메시징 솔루션입니다.

Firebase 기능들이 프리티어 식으로 운영되다가 일정량 이상 사용하면 유료로 전환되는 것들이 많은데, FCM은 계속 무료입니다 :0

푸시 메시지를 보내는 솔루션은 FCM 이외에도 많이 있지만, 유료거나 각 플랫폼 환경별로 개발을 따로 해야되는 불편함이 있어서 FCM을 많이 쓰죠. Android, IOS, web까지 모두 커버가 가능합니다.

FCM 꼭 써야하나?

필수는 아니지만, 푸시 기능을 제공할거면 쓰는 것이 권장됩니다.

FCM과 같은 메시징 솔루션을 쓰지 않으려면 자체 서버에서 알람을 주는 방식을 사용할 수 있겠죠?

그러면 내 앱이 성공적으로 알람을 받으려면 앱이 백그라운드에서 계속 구동되고 있어야 하고 서버에 접속해있어야합니다.

즉, 지속적으로 배터리와 네트워크 사용이 발생합니다.

요즘 핸드폰은 어느 앱이 배터리 얼마나 썼는지, 데이터 얼마나 썼는지 다 알려주니깐 '악성앱이네!'하고 삭제해버릴 수도 있습니다.

보내는 방법

이러한 메시지는 개인에게 / 그룹에게 / 특정 주제를 구독한 사람에게 보낼 수 있는데요.

firebase 사용 등록이 되어있다면 앱, 웹, 어디에서든 fcm에 요청함으로써 푸시를 보낼 수 있습니다.

 

[푸시 발송 주체]

1. 앱에서 보내기 - 간단한 채팅의 경우, 채팅 방이 만들어지면 서로 토큰을 교환 한 후 메시지를 보낼 때 fcm에 푸시 요청을 보내는 식으로 구현이 가능합니다. 

2. 서버에서 보내기 - 앱 사용 독려나 마케팅 푸시를 보낼 때, 서버에서 fcm에 푸시 요청을 보내는 식으로 구현이 가능합니다.

3. 구현 없이 fcm에서 바로 보내기 - firebase console을 활용해서 보냅니다.

 

[타겟 정하기]

1. 개인에게 - 기기별 토큰을 담아서 푸시를 요청합니다.

2. 그룹에게 - 기기별 토큰을 모아서 한번에 푸시를 요청합니다.

3. 특정 주제를 구독한 사람에게 - 특정 주제에 구독을 추가 한 후에, 해당 주제를 topic으로 갖는 메시지 푸시를 요청합니다.

 

Flutter 설정

1. 내 기기 토큰 구하기

pubspec.yaml를 통해 firebase_messaging 이라는 패키지를 설치해줍니다.

  firebase_messaging: ^9.1.2

토큰을 아래 코드로 받아옵니다.

 String token = await FirebaseMessaging.instance.getToken();

받아온 토큰은 서버에 저장해두는 등의 방식으로 저장을 해둡니다.

 

2. 푸시 받을 리스너 설정해두기

이 부분은 패키지 예시를 확인해주세요(버전별로 조금씩 바뀌는게 있어서 최신 버전을 참고하시는게 좋습니다)

간단히 설명하면 firebase_messaging 패키지의 리스너를 통해 메시지를 전달 받고, flutter_local_notification을 통해서 메시지를 출력해주는 방식입니다.

 

firebase_messaging | Flutter Package

Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS.

pub.dev

 

Node.js 설정

firebase에서 프로젝트 설정 - 서비스 계정에 가서 새 비공개 키 생성을 눌러줍니다.

그럼 ~~~~.json 파일이 생기는데, 이걸 node.js 프로젝트에 넣어주고 세팅을 시작해주면 됩니다.

Java나 Python, Go로 서버를 설정할 경우에도 예시가 다 있고 작동 방식은 동일합니다.

 

yarn 이나 npm을 통해 firebase-admin 이라는 패키지를 설치해주시고 아래와 같이 설정해줍니다.

const admin = require("firebase-admin");

let serAccount = require("../~키 넣어놓은 경로 밑에 내 키 이름.json");
admin.initializeApp({
  credential: admin.credential.cert(serAccount),
});

설정이 끝나면 바로 메시지를 보낼 수 있습니다.

[토큰으로 개인한테 보내기]

router.get('/push_send', function (req, res, next) {
  let target_token =
    ''
	//flutter에서 getToken 한 다음 print찍어서 복사해보아요.

  let message = {
    data: {
      title: '테스트 데이터',
      body: '내용내용',
    },
    token: target_token,
  }

  admin
    .messaging()
    .send(message)
    .then(function (response) {
      console.log('Successfully sent message: : ', response)
    })
    .catch(function (err) {
      console.log('Error Sending message!!! : ', err)
    })
})

[토픽으로 여러명한테 보내기]

주제 구독은 주제 당 1000명까지 등록됩니다.

*신뢰성보다 처리량에 우선을 둔 부분이라 꼭 전달되어야되는 경우 구독 외 다른 방법 사용이 필요합니다.

router.get("/admin/push_send_all", async function (req, res, next) {
  let tokens = [];
  tokens.push(''); //마찬가지로 당신의 토큰(들)
  admin
    .messaging()
    .subscribeToTopic(tokens, "public")
    .then(function (response) {
      console.log("Successfully subscribed to topic:", response);
    })
    .catch(function (error) {
      console.log("Error subscribing to topic:", error);
    });
    //public이라는 주제를 구독한다는 의미입니다.
  var message = {
    notification: {
      title: "테스트 데이터",
      body: "잘가유",
    },
    topic:"public"
  };
	//아까 token과는 별개로 topic이라는 속성에 구독 주제 이름을 작성해줍니다.
  admin
    .messaging()
    .send(message)
    .then((response) => {
      console.log("Successfully sent message:", response);
      res.status(200).json({ success: true });
    })
    .catch((error) => {
      console.log("Error sending message:", error);
      res.status(400).json({ success: false });
    });
    //마찬가지로 전송

[+ 추가적으로 여러 조건을 한꺼번에 적용 가능한 condition이라는 것도 있습니다]

var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

var message = {
  notification: {
    title: 'a',
    body: 'b'
  },
  condition: condition
};

 

Q. 전체 푸시를 보내려면?

firebase-admin에는 전체 푸시 기능은 없는 것으로 보입니다.(제가 못찾은거면 제발 알려주세요ㅠ)

사용자 수가 적을 경우에는 특정 주제를 다 같이 구독하는 식으로 푸시를 보낼 수 있을 것 같고, 필요한 경우 firebase 콘솔에 직접 접근해서 보낼 수 있습니다. 대상 사용자에 android / ios로 분리해서 두번 보내게 되면 모든 이용자에게 푸시를 보낼 수 있습니다.

Q. 메시지 보낼 때 data 와 notification 중 뭘 써야하는건가요?

메시지에 담을 수 있는 속성들

둘 다 써도 되고 notification만 써도 됩니다. 푸시의 알림 기능을 쓰려면 notification만 쓰면 되고, 그 푸시를 터치해서 추가적인 액션을 해주기 위한 데이터가 필요한 경우 data에도 필요한 데이터를 담아서 보내주면 됩니다.

각 데이터에 따라 처리되는 부분은 아래와 같습니다.

 

백그라운드 상태인 경우

- (Notification) 알림 페이로드가 앱의 알림 목록에 수신됨

- (Data) 사용자가 알림을 탭(오픈)한 경우에만, 앱이 데이터 페이로드를 처리

 

포그라운드 상태인 경우

- 앱에서 페이로드가 둘 다 제공되는 메시지 개체를 수신




 

댓글