개요
Firebase FCM - 클라이언트(JavaScript) 설정에서 웹앱(PWA)에 Firebase에서 요구하는 특별한 서비스워커인 firebase-messaging-sw.js
를 추가하였습니다. 그 후, 파이어베이스 알림 작성기를 이용해 푸시 메시지를 발송하여 웹앱(PWA)을 실행한 기기에서 해당 푸시 메시지가 도착하는 것을 PC 및 스마트폰에서 확인하였습니다.
웹앱(PWA)이 백그라운드 상태일 때 알림 유형의 푸시 메시지는 firebase-messaging-sw.js
에서 초기화한 Firebase SDK에서 수신 및 표시를 자동으로 해주기 때문에 그저 SDK 만 초기화하는 코드로 충분히 기능이 동작했습니다.
이번 포스트는 알림 유형의 푸시 메시지 이외에 FCM에서 지원하는 다른 종류의 푸시 메시지도 함께 살펴보고 이것을 모두 수신할 수 있도록 웹앱(PWA)에 기능을 추가할 것입니다.
푸시 메시지 종류
FCM이 제공하는 푸시 메시지는 푸시메시지에 포함된 key에 따라 3가지 유형이 있습니다.
- 알림(notification) 메시지
- 데이터(data) 메시지
- 알림 + 데이터 메시지
알림 메시지(notification)
알림 메시지에는 사용자에게 표시되는 키 모음이 사전 정의되어 있습니다. 따라서 우리는 정의되어 있는 키에 해당하는 값을 채워서 푸시 메시지를 발송하면 됩니다. 이전 포스트에서 우리가 파이어 베이스 알림 작성기를 이용해 발송한 메시지가 바로 이 알림 메시지입니다.
알림 메시지는 notification
키가 설정됩니다. 이 키의 내부 키-값의 쌍은 사전에 정의되어 있으므로 이들 중 수신기기에 표시할 것의 값을 포함시키면 됩니다.
예시
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}
전송방법
알림 메시지의 전송은 두 가지 방법이 있습니다. 앞선 포스트에서 보았던 것처럼 파이어베이스 알림 작성기를 이용하여 전송하는 방법과 서버 측에서 API를 사용하여 FCM 서비스에 푸시 메시지 전송을 요청할 수 있습니다.
수신처리
알림 메시지의 경우, 수신 처리는 앱의 상태에 따라 달라집니다. 앱이 활성화되어 있다면 onMessage
에서 처리합니다. 반면 앱이 비활성화되어 있다면 SDK에서 푸시 메시지를 자동으로 처리하여 알림 탭에 적절히 표시합니다.
앞서 파이어베이스 알림 작성기를 이용해 메시지를 발송한 후, 앱을 닫은 것은 SDK에서 푸시메시지를 수신하여 알림 탭에 표시하도록 하기 위해서입니다.
데이터 메시지
(반면 아직 다루지는 않았으나) 데이터 메시지는 우리가 자체적으로 정의한 커스텀 키와 값 쌍만 포함됩니다.
데이터 메시지는 data
키를 푸시 메시지에 추가합니다. 이 data
키의 내부에 키-값은 사전에 정의된 것이 아니므로 수신하는 앱(클라이언트)에서 처리해야 합니다.
예시
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
전송방법
데이터 메시지는 파이어베이스 알림 작성기를 이용하여 전송할 수 없습니다. 따라서 서버 측에서 API를 사용하여 FCM 서비스에 푸시 메시지 전송을 요청해야 합니다.
수신처리
알림 메시지와 달리 Data
키에 포함되는 키와 값의 쌍은 제약이 없습니다. 따라서 SDK에서 메시지를 처리할 수 없습니다. 때문에 data
가 포함된 메시지를 수신할 경우 SDK를 우회하여 앱에 작성된 onMessage
핸들러 또는 서비스 워커에 작성된 setBackgroundMessageHandler
에서 바로 메시지(message
) 객체를 수신합니다.
이런 유형의 메시지는 Firebase SDK에서 자동으로 알림 탭에 표시를 해주지 않기 때문에 웹앱에 해당 메시지를 처리하는 기능을 작성하지 않으면 사용자는 메시지의 수신 여부도 확인할 수 없습니다.
알림 + 데이터 메시지
마지막으로 알림과 데이터가 하나의 푸시 메시지에 포함되어 있는 유형인 알림 + 데이터 메시지가 있습니다. 이 유형의 메시지에는 notification
과 data
페이로드가 모두 포함되어 있습니다.
예시
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
}
전송방법
알림 메시지와 동일하게 파이어베이스 알림 작성기 또는 API를 이용하여 전송할 수 있습니다.
수신처리
notification
및 data
가 둘 다 포함된 메시지를 수신할 경우 앱의 동작은 앱이 백그라운드 상태인지 아니면 포그라운드 상태인지에 따라 달라집니다.
- 백그라운드 상태인 경우
notification
페이로드의 내용이 SDK에 의해 앱의 알림 목록에 표시됩니다. 사용자가 알림을 탭한 경우 앱이data
페이로드를 처리합니다. - 포그라운드 상태인 경우 앱의
onMessage()
에서 메시지(message
) 객체를 수신합니다.
푸시 메시지 수신
푸시 메시지를 웹앱(PWA)에서 수신하기 위해 구현해야 하는 내용을 정리하면 다음과 같습니다.
예를 들어 알림메시지(notification
)만 사용할 예정이라면 앱이 백그라운드 상태일 경우 Firebase SDK 가 알림 상태에 내용을 표시해주므로 포그라운드 상태에서 메시지를 처리하도록 앱에 onMessage
만 messaging
객체에 추가하면 됩니다.
앱 상태 | 메시지 종류 | ||
"notification" | "data" | "notification" + "data" | |
포그라운드 | onMessage | onMessage | onMessage |
백그라운드(서비스워커) | SDK가 표시하는 알림 | setBackgroundMessageHandler | SDK가 표시하는 알림 |
알림메시지 수신처리
알림메시지를 포그라운드에서 수신하려면 massaging
객체에 onMessage
를 추가하고 내용을 작성합니다.
※ 앞서 진행한 FCM - 클라이언트설정 포스트에서 사용한 프로젝트를 사용합니다.
index.html
의 <body>
태그안에 있는 document.addEventListener('DOMContentLoaded', function () {
부분을 찾아 다음과 같이 onMessage()
를 추가합니다.
<body>
... 중략 ...
<script>
document.addEventListener('DOMContentLoaded', function () {
// Firebase Messaging 객체 획득
const messaging = firebase.messaging();
// Add the public key generated from the console here.
messaging.usePublicVapidKey("BBO_8w ... Mlfrw8eo");
messaging.onMessage(payload => {
console.log("Message received. ", payload);
});
... 중략 ...
</script>
</body>
▲ index.html
이제 웹앱(PWA)이 백그라운드 상태일 때뿐만 아니라 활성화된 상태에서도 알림 메시지를 수신할 수 있습니다.
동작 확인을 위하여 firebase serve
명령으로 웹앱(PWA)을 실행합니다. 포어그라운드(앱이 활성화)된 상태에서 메시지를 수신하는 것을 확인하기 위해 창은 닫지 않습니다.
알림 유형의 푸시 메시지는 파이어베이스 알림 작성기를 이용하여 송신할 수 있습니다. 하지만 데이터 유형의 푸시 메시지는 알림 작성기를 사용할 수 없으므로 postman서비스를 사용하여 시험용 푸시 메시지를 송신하겠습니다.
postman을 이용한 푸시메시지 전송에 대한 상세한 설명은 링크로 대체합니다.
메시지의 구성은 시험 메시지 보내기를 참조하였습니다.
postman 서비스로 알림 메시지 전송
전송방식은 POST
를 선택합니다. URL 값은 https://fcm.googleapis.com/fcm/send
을 입력합니다.
Header는 다음 그림과 같이 Authorization
과 Content-Type
을 입력합니다. Authorization
키의 값은 FCM의 서버키 값을 사용합니다.
Body는 다음과 같이 입력하였습니다. to
키에는 에는 등록 Token값을 넣습니다.
[Send] 버튼을 누른 후, 웹앱(PWA)이 실행 중인 크롬의 개발자 도구의 콘솔탭을 살펴봅니다. 출력된 로그를 통해 푸시메시지가 도착하면 onMessage()
로 전달되는 것을 확인할 수 있습니다. (그림의 Messag received.
부분이 송신한 메시지의 내용입니다.)
제가 작성하고자 하는 앱의 경우 알림 메시지를 받으면 푸시 알림 창에 메시지의 내용을 표시하고 싶기 때문에 다음과 같이 onMessage
메서드를 조금 수정하였습니다.
<body>
... 중략 ...
<script>
document.addEventListener('DOMContentLoaded', function () {
// Firebase Messaging 객체 획득
const messaging = firebase.messaging();
// Add the public key generated from the console here.
messaging.usePublicVapidKey("BBO_8w ... Mlfrw8eo");
messaging.onMessage(payload => {
console.log("Message received. ", payload);
const { title, ...options } = payload.notification;
//Show the notification :)
return navigator.serviceWorker.getRegistration('/firebase-cloud-messaging-push-scope').then(registration => {
registration.showNotification(
title,
options
)
});
});
... 중략 ...
</script>
</body>
▲ index.html
이번에는 앞서 와 마찬가지로 개발자 콘솔에 메시지를 출력한 후, 푸시 알림까지 표시하는 것을 확인할 수 있습니다.
※ 스마트폰에서 알림 메시지 수신 동작 확인은 생략하도록 하겠습니다.
데이터 메시지 수신처리
데이터 메시지의 경우 백그라운드 상태에서 메시지를 수신하도록 처리하기 위해 setBackgroundMessageHandler
를 추가합니다. 이때 앞서 와 달리 firebase-messaging-sw.js
에 다음과 같이 코드를 작성하였습니다.
const messaging = firebase.messaging();
// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START background_handler]
messaging.setBackgroundMessageHandler(payload => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
const { title, ...options } = payload.data;
return self.registration.showNotification(
title,
options
);
});
▲ firebase-messaging-sw.js
데이터 메시지를 활성화 상태에서도 수신하도록 앞서 작성하였던 onMessage()
코드도 약간 수정하였습니다.
... 중략 ...
const { title, ...options } = payload.notification || payload.data;
... 중략 ...
▲ index.html
postman 서비스로 데이터 메시지 전송
시험을 위한 메시지의 전송은 body의 notification
키를 data
로 수정합니다.
개발자 도구에 출력되는 로그를 통해 데이터 메시지도 포어그라운드 및 백그라운드 모두에서 정상 수신하는 것을 확인할 수 있습니다. (포어그라운드 : Message received.
, 백그라운드: [firebase-messaging-sw.js]
)
알림 + 데이터 메시지의 수신 처리
앞서 정리한 내용과 같이 notification
과 data
가 모두 포함된 메시지는 포어그라운드일 경우 onMessage()
로 notificatoin
과 data
가 모두 포함된 메시지가 전달됩니다.
반면 웹앱(PWA)이 백그라운드 상태인 경우, notification
페이로드는 SDK에 의해 자동 처리가 되지만 data
페이로드는 SDK가 onMessage()
로 전달하지 않습니다. 문서에 따르면 앱으로 전달된다는 내용이 있어 구글의 Web Push Notification 문서를 참고하면 Push Event로 해당 데이터를 수신할 수 있습니다.
따라서 서비스워커 코드에 다음과 같이 Push 이벤트 핸들러를 추가합니다.
self.addEventListener('push', (event) => {
if (event.data) {
let jsonData = JSON.parse(event.data.text());
console.log(`${jsonData.data.title} : ${jsonData.data.body}`);
} else {
console.log('This push event has no data.');
}
});
▲ firebase-messaging-sw.js
※ 참고 : 20.8.13 Firebase JavaScript SDK가 7.18.0으로 버전업 되면서 이 오류가 수정되었습니다. (링크)
postman 서비스로 알림 + 데이터 메시지 전송
간단히 메시지를 notification
과 data
의 내용을 다음과 같이 수정하여 메시지의 수신 시 전달되는 경로를 확인하였습니다.
정리
- FCM이 지원하는 푸시 메시지는 알림, 데이터, 알림+데이터 메시지가 있습니다.
- 앱의 상태에 따라 메시지가 전달되는 경로가 다릅니다.
onMessage()
,setBackgroundMessageHandler
,push
이벤트 핸들러를 구현해야 합니다.
참고
'모듈, 프레임웍 > Firebase' 카테고리의 다른 글
[Firebase] Cloud Firestore Collection에 포함된 Doc 갯수 세기 (0) | 2021.01.06 |
---|---|
Firebase JavaScript SDK 7.18.0 - Cloud Messaging (0) | 2020.08.17 |
Firebase Cloud Messaging - 클라이언트(JavaScript) 설정 (0) | 2020.07.28 |
Firebase 호스팅 사용하기 - Custom Domain 연결 (0) | 2020.07.21 |
파이어베이스(Firebase) 앱 등록 (=키 발급) (0) | 2020.07.02 |