๐Ÿšง

[FCM] Firebase Cloud Messaging ์œผ๋กœ ์›น์—์„œ ํ‘ธ์‹œ์•Œ๋ฆผ ๊ตฌํ˜„ํ•˜๊ธฐ (React ํด๋ผ์ด์–ธํŠธ)

purpplee 2021. 12. 1. 15:03

FCM์ด ๋ญ”์ง€๋Š” ์ผ๋‹จ ๋‚˜์ค‘์—...

 

์ž์„ธํ•œ ๊ฒƒ์€ ๐Ÿ‘‰  Firebase Cloud Messaging Documentation์„ ๋”ฐ๋ผํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ .

๋‹จ์ˆœํžˆ ์„œ๋ฒ„ ์‹คํ–‰ ์—†์ด http, js ํŒŒ์ผ๋กœ ์‹คํ–‰ํ–ˆ๋”๋‹ˆ ์•„๋ž˜์ฒ˜๋Ÿผ ๋œจ๋”๋ผ๊ณ ์š”... ์•„๋ž˜ ์˜ค๋ฅ˜๋Š” ์•Œ๋ฆผ ๊ถŒํ•œ ์š”์ฒญ์„ ์ฐจ๋‹จํ–ˆ๋‹ค๋Š” ๋ฉ”์‹œ์ง€์ธ๋ฐ, file:// ๋„๋ฉ”์ธ์œผ๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํฌ๋กฌ ์•Œ๋ฆผ ์„ค์ •์ด ์•„๋ฌด๋ฆฌํ•ด๋„ ํ—ˆ์šฉ์ด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

FirebaseError: Messaging: The notification permission was not granted and blocked instead. (messaging/permission-blocked).

๊ทธ๋ž˜์„œ ๋ฆฌ์•กํŠธ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ณ€๊ฒฝํ•ด์„œ ํ…Œ์ŠคํŠธํ•ด๋ณด๊ธฐ๋กœ...

 

 

๋™์ž‘ ์›๋ฆฌ

React ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์„ ๋Œ€๊ธฐํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ FCM ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋ฉด ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋„์›๋‹ˆ๋‹ค. ์ด๋•Œ ๋ธŒ๋ผ์šฐ์ €์˜ Service Worker ๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์—์„œ ๋Œ์•„๊ฐ€๋ฉฐ ์‚ฌ์ดํŠธ๋ฅผ ๊บผ๋„ ํ‘ธ์‹œ์•Œ๋ฆผ์„ ๋„์šธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ React ํด๋ผ์ด์–ธํŠธ๋Š” Service Worker ์— ๋Œ€ํ•œ ์„ค์ •๋„ ๊ฐ™์ด ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๊ตฌํ˜„

firebase ์„ค์น˜

firebase sdk ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด firebase ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

yarn install firebase

 

 

public/firebase-messaging-sw.js

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด fcm ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ service worker ๋ฅผ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ์ •์ ํŒŒ์ผ ๋ฃจํŠธ ๊ฒฝ๋กœ ์•„๋ž˜์— firebase-messaging-sw.js ๋ผ๋Š” ์ด๋ฆ„์˜ ํŒŒ์ผ๋กœ ์ €์žฅํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜ ์ •์ ํŒŒ์ผ์ด๋ผ ๊ทธ๋Ÿฐ์ง€...importScripts ๋กœ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค! ํ‘ธ์‹œ์•Œ๋ฆผ์ด ์ œ๋Œ€๋กœ ๋จนํžˆ์ง€ ์•Š๋Š”๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ importScripts ๋ฌธ์˜ ํ”„๋กœ์ ํŠธ ๋ฒ„์ „์„ ์ตœ์‹ ์œผ๋กœ ์ˆ˜์ •ํ•ด์ฃผ์„ธ์š”. config ๊ฐ’์€ ํ”„๋กœ์ ํŠธ ์„ค์ • > ์ผ๋ฐ˜ ํƒญ ๋งจ ํ•˜๋‹จ [๋‚ด ์•ฑ] ์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

//ํ”„๋กœ์ ํŠธ ๋ฒ„์ „ ํ™•์ธ
importScripts("https://www.gstatic.com/firebasejs/9.5.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/9.5.0/firebase-messaging.js");

const config = {
  //ํ”„๋กœ์ ํŠธ ์„ค์ • > ์ผ๋ฐ˜ > ํ•˜๋‹จ์˜ ๋‚ด ์•ฑ ๋ถ€๋ถ„ ๋ณต์‚ฌ
};

// Initialize Firebase
firebase.initializeApp(config);

const messaging = firebase.messaging();

//๋ฐฑ๊ทธ๋ผ์šด๋“œ ์„œ๋น„์Šค์›Œ์ปค ์„ค์ •
messaging.onBackgroundMessage(messaging, (payload) => {
  console.log(
    "[firebase-messaging-sw.js] Received background message ",
    payload
  );
  
  // Customize notification here
  const notificationTitle = "Background Message Title";
  const notificationOptions = {
    body: payload,
    icon: "/firebase-logo.png",
  };
  
  self.registration.showNotification(notificationTitle, notificationOptions);
});

 

src/util/fcm.js

ํ† ํฐ์„ ์–ป๊ณ  ํฌ๊ทธ๋ผ์šด๋“œ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ ์„ ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์ด ํ† ํฐ์€ ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค. ํ† ํฐ์„ ์–ป๊ธฐ ์œ„ํ•ด์„œ๋Š” vapid๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ์ด ๊ฐ’์€ ํ”„๋กœ์ ํŠธ์„ค์ • > ํด๋ผ์šฐ๋“œ๋ฉ”์‹œ์ง• > ์›น ๊ตฌ์„ฑ์˜ ์›นํ‘ธ์‹œ์ธ์ฆ์„œ ๋ฐœ๊ธ‰ ์—์„œ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ดํ›„ ๋ฆฌ์•กํŠธ ์•ฑ์„ ์‹คํ–‰ํ•˜๋ฉด ์ฝ˜์†”์ฐฝ์— ํ† ํฐ๊ฐ’์ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์„œ๋น„์Šค์›Œ์ปค์™€๋Š” ๋ณ„๋„๋กœ ์ด์ชฝ์—์„œ๋„ initializeApp ์„ ํ•ด์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.(๊ฑฐ๊ธฐ์„œ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ์ค„ ์•Œ๊ณ  ์•ˆํ•ด์คฌ๋”๋‹ˆ uncaught firebaseerror: firebase: no firebase app '[default]' has been created - call firebase app.initializeapp() ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€...)

import { initializeApp } from "firebase/app";
import { getMessaging, getToken, onMessage } from "firebase/messaging";

const config = {
  //ํ”„๋กœ์ ํŠธ ์„ค์ • > ์ผ๋ฐ˜ > ํ•˜๋‹จ์˜ ๋‚ด์•ฑ์—์„œ ํ™•์ธ
};

const app = initializeApp(config);
const messaging = getMessaging();

//ํ† ํฐ๊ฐ’ ์–ป๊ธฐ
getToken(messaging, {
  vapidKey:
    "ํ”„๋กœ์ ํŠธ์„ค์ • > ํด๋ผ์šฐ๋“œ๋ฉ”์‹œ์ง• > ์›น ๊ตฌ์„ฑ์˜ ์›นํ‘ธ์‹œ์ธ์ฆ์„œ ๋ฐœ๊ธ‰",
})
  .then((currentToken) => {
    if (currentToken) {
      // Send the token to your server and update the UI if necessary
      // ...
      console.log(currentToken);
    } else {
      // Show permission request UI
      console.log(
        "No registration token available. Request permission to generate one."
      );
      // ...
    }
  })
  .catch((err) => {
    console.log("An error occurred while retrieving token. ", err);
    // ...
  });

//ํฌ๊ทธ๋ผ์šด๋“œ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ 
onMessage(messaging, (payload) => {
  console.log("Message received. ", payload);
  // ...
});

 

src/App.js

fcm ์Šคํฌ๋ฆฝํŠธ๋ฅผ app.js ์— ํฌํ•จ์‹œ์ผœ์ค๋‹ˆ๋‹ค.

import "./util/fcm";

...

 

๋ฉ”์‹œ์ง€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ

firebase ์—์„œ ํ…Œ์ŠคํŠธํ•  ์ˆ˜๋„ ์žˆ๊ณ  api ํ…Œ์ŠคํŠธ ํˆด๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

firebase ์—์„œ ํ…Œ์ŠคํŠธ

์ฐธ์—ฌ > Cloud Messaging > Send your first message ๋ฅผ ์„ ํƒํ•œ ํ›„ ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ์ „์†ก์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.

 

๋ฆฌ์•กํŠธ ์•ฑ ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅ๋œ ํ† ํฐ๊ฐ’์„ ์•„๋ž˜์— ์ถ”๊ฐ€ํ•˜๊ณ  ํ…Œ์ŠคํŠธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํฌ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์—์„œ๋Š” ์ฝ˜์†”์ฐฝ์— ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๊ณ , ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ(์‚ฌ์ดํŠธ๋ฅผ ์ข…๋ฃŒํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํƒญ์œผ๋กœ ์ „ํ™˜)์—์„œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ํ‘ธ์‹œ ์•Œ๋ฆผ์ด ์˜ต๋‹ˆ๋‹ค.

 

api ํˆด๋กœ ํ…Œ์ŠคํŠธ

POST ์š”์ฒญ์œผ๋กœ https://fcm.googleapis.com/fcm/send  ์—”๋“œํฌ์ธํŠธ์— ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค. header ์—๋Š” Authorization ์— bearer ์ธ์ฆ ํ† ํฐ๊ฐ’์„ ๊ฐ™์ด ๋ณด๋‚ด์ค˜์•ผ ํ•˜๋Š”๋ฐ, ์ด๊ฒƒ์€ ํ”„๋กœ์ ํŠธ ์„ค์ • > ํด๋ผ์šฐ๋“œ ๋ฉ”์‹œ์ง• > ํ”„๋กœ์ ํŠธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด์˜ ์„œ๋ฒ„ํ‚ค ํ† ํฐ์„ ๋ณต์‚ฌํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค. bearer์™€ ๊ทธ ๋’ค ๋„์–ด์“ฐ๊ธฐ ๊ผญ ์•ž์— ๋ถ™์—ฌ์ฃผ์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. key= ๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

 

send ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ์˜ค๊ณ , ํ‘ธ์‹œ์•Œ๋ฆผ์ด ๋œน๋‹ˆ๋‹ค.

 

api ํˆด์ด ์—†๋‹ค๋ฉด vscode ์—์„œ restclient ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•˜๊ณ  test.http ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด ์•„๋ž˜์ฒ˜๋Ÿผ ํ…Œ์ŠคํŠธํ•ด์ค๋‹ˆ๋‹ค.

curl --location --request POST 'https://fcm.googleapis.com/fcm/send' \
--header 'Authorization: bearer server-key' \
--header 'Content-Type: application/json' \
--data-raw '{
    "notification": {
        "title": "TEST",
        "body": "์•Œ๋ฆผํ…Œ์ŠคํŠธ"
        
    },
    "to": "token"
}'

 

 

ํ˜น์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค๋ฉด ๋ฆฌ์•กํŠธ ์„œ๋ฒ„๋ฅผ ์•„์˜ˆ ๊ป๋‹ค๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰ํ•ด๋ณด์„ธ์š”. ์ •์  ํŒŒ์ผ ์ˆ˜์ •์€ ์„œ๋ฒ„ ์ข…๋ฃŒํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰ํ•ด์•ผ ์—…๋ฐ์ดํŠธ ๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•