유댕이의 개발공부일지
FCM ( with Serviceworker ) 본문
FCM이란
FCM은 Firebase Cloud Messaging의 약자로, 무료로 메시지를 안정적으로 전송할 수 있는 교차 플랫폼 메시징 솔루션이다. 모든 사용자에게 알림 메시지를 전송할 수도 있고, 그룹을 지어 메시지를 전송할 수도 있다.
FCM이 제공하는 주요 기능
FCM을 사용하여 구현할 수 있는 기능에는 총 3가지가 존재한다.
- 알림 메시지 전송 or 데이터 메시지 전송 기능또는 사용자에게 데이터 메시지를 전송하고 애플리케이션 코드에서 임의로 처리할 수 있다.
- 앱이나 웹, 게임 등을 이용하는 사용자에게 알림 메시지를 전송할 수 있다.
- 다양한 메시지를 전송받을 기기 타겟팅 기능
- 단일 기기, 그룹 기기, 특정 주제를 구독한 기기 등 3가지 타겟팅 방식으로 클라이언트 앱에 메시지를 배포할 수 있다.
- 클라이언트 앱에서 메시지 전송 기능
- 메시지를 전송 받은 클라이언트 기기에서 다시 서버로 확인 및 채팅 등의 메시지를 보낼 수 있다.
💡이 중 우리는 1번 알림 메시지 전송 기능을 사용해 푸시알람 기능을 구현했다.
FCM 사용 이유
FCM을 사용함으로써 얻는 장점(?),이유(?)는 간단하다. 서버 인프라를 고민할 필요가 없다는 점과 완전히 무료라는 점이다. Firebase는 Database, Storage, Auth, Analytics까지 제공해준다. 기본적으로 서비스를 구축하기 위한 서버 인프라 구축, 서버단의 세팅 등을 고민하지 않고 클라이언트단의 작업만 진행하여 서비스를 제작할 수 있기 때문에 우리의 프로젝트에 잘 맞는다고 볼 수 있다.
FCM 작동 원리 및 Flow
- Firebase Console GUI 에서 메시지를 전송
- 3rd-party-server 혹은 모바일 클라이언트에서 http 혹은 xmpp 프로토콜을 통해 메시지를 전송
- firebase 서버에서는 특정 기기로 메시지 전송 요청을 받으면 장치(ios, android, web)로 알림을 전송
- 클라이언트는 메시지 수신
[ How to Setting (In FinalMission)]
1. 프로젝트 생성
Firebase
Firebase는 고품질 앱을 빠르게 개발하고 비즈니스를 성장시키는 데 도움이 되는 Google의 모바일 플랫폼입니다.
firebase.google.com
FCM을 사용하기 위해서는 Firebase 등록이 필요하다.
2. FCM사용을 위해서 firebase 모듈을 설치
npm install firebase
3. FCM에 permission요청하고 token발급
→ Firebase에 허가를 요청하고 제작 중인 앱에 대한 token을 받는다.
import firebase from 'firebase';
firebase.initializeApp({
apiKey: 'secret!!',
authDomain: 'dog-blog-29d8f.firebaseapp.com',
databaseURL: '<https://dog-blog-29d8f-default-rtdb.firebaseio.com>',
projectId: 'dog-blog-29d8f',
storageBucket: 'dog-blog-29d8f.appspot.com',
messagingSenderId: '919821521993',
appId: '1:919821521993:web:ff0855fbea794365409b98',
measurementId: 'G-NY64PXGRL7'
});
const messaging = firebase.messaging();
// 허가 요청!!
Notification.requestPermission()
.then(function () {
return messaging.getToken();
})
.then(function (token) {
// 허가시 토큰 받기
console.log('get token', token);
})
.catch(function (err) {
alert(message.error);
console.error('fcm error : ', err);
});
Service Worker세팅
서비스워커는 자바스크립트로 실행되는 백그라운드 스크립트라고 보면 된다.
public/firebase-messaging-sw.js
// Firebase에서 필요한 모듈을 가져오기
importScripts('<https://www.gstatic.com/firebasejs/8.6.8/firebase-app.js>');
importScripts('<https://www.gstatic.com/firebasejs/8.6.8/firebase-messaging.js>');
firebase.initializeApp({
apiKey: 'secret!!',
authDomain: 'dog-blog-29d8f.firebaseapp.com',
databaseURL: '<https://dog-blog-29d8f-default-rtdb.firebaseio.com>',
projectId: 'dog-blog-29d8f',
storageBucket: 'dog-blog-29d8f.appspot.com',
messagingSenderId: '919821521993',
appId: '1:919821521993:web:ff0855fbea794365409b98',
measurementId: 'secret!!'
});
[ How to use ]
1. onMessage함수를 통해 알림 내용받기
/firebase/onMessageListener
export const onMessageListener = (messaging) =>
new Promise((resolve) => {
messaging.onMessage((payload) => {
resolve(payload);
});
});
사용하고 싶은 컴포넌트에서 Import해 사용
import firebase from 'firebase';
import onMessageListener from '/firebase/onMessageListener';
const [notification, setNotification] = useState({
title: '',
body: ''
});
const messaging = firebase.messaging();
onMessageListener(messaging)
.then((payload) => {
setNotification({
title: payload.notification.title,
body: payload.notification.body
});
})
.catch((err) => {
alert(message.error);
console.error('failed: ', err);
});
2. 백그라운드 노티스 알람
- 간단 노드 생성 Node.js(express)
- Firebase Admin SDK 세팅
server/index.js
var serviceAccount = require('./serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: '<https://dog-blog-29d8f-default-rtdb.firebaseio.com>'
});
- 알람 기능 간단 api 생성
server/index.js
server.post('/notice', (req, res) => {
const registrationToken = 'secret!!';
// 보내줄 notice 문구
const uploadMessages = [
{
notification: {
title: '업로드 완료',
body: '파일 업로드가 완료되었습니다.'
},
token: registrationToken
}
];
admin
.messaging()
.sendAll(uploadMessages)
.then((res) => {
console.log(res.successCount + ' messages were sent successfully');
})
.catch((error) => {
console.error('Error sending message:', error);
});
});
});
- 사용하고 싶은 컴포넌트에서 api post
component/Register/index.tsx
import axios from 'axios';
// 파일업로드 성공시 실행
const postNotice = () => {
console.log('노티스 Post 완료!');
axios.post('/notice');
};