FCM 알림설정

wkawhaRo·2025년 4월 3일
0

FCM 알림설정

✅ 프로젝트 환경

  • Frontend: React + Vite
  • Service Worker: vite-plugin-pwa + Workbox
  • Push 서비스: Firebase Cloud Messaging (FCM)
  • 실행 환경: 데스크톱 PWA (모바일 아님)

✅ 최종 목표

📥 포그라운드 및 백그라운드 모두에서 푸시 알림을 수신하고

🔔 알림 팝업(Notification)을 정상적으로 사용자에게 표시한다.

🔧 설정 순서 및 내용

1. Firebase 프로젝트 생성 및 FCM 설정

  • Firebase 콘솔에서 프로젝트 생성
  • "클라우드 메시징" 탭에서 Web Push 인증서 (VAPID 키) 발급

  • Authentication → 로그인 방법 → 새 제공업체 추가, 이메일/비밀번호 설정

2. 프로젝트 firebase 설정

  1. vite-plugin-pwa로 관리하는 src/sw.js 방식
  2. public/firebase-messaging-sw.js 방식

🔀 두 방식의 차이 요약

항목src/sw.js (vite-plugin-pwa)public/firebase-messaging-sw.js
관리 주체Vite / WorkboxFirebase 자체
파일 위치src/ → 빌드시 dist/sw.jspublic/ → 빌드시 그대로 복사
백그라운드 알림 처리onBackgroundMessage() 직접 추가Firebase가 자동 참조
확장성🟢 Workbox 사용 가능 (캐시 등)🔴 순수 백그라운드 알림만 가능
추천 용도✅ PWA + 알림 모두 커스텀할 때🔧 알림만 간단하게 쓸 때

나는 vite-plugin-pwa 방식으로 채택했다.

⚙️ 단계별 정리


① 설치

npm i vite-plugin-pwa

vite.config.ts 설정

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
import path from 'path';

export default defineConfig({
  plugins: [
    react(),
    VitePWA({
      strategies: 'injectManifest', // sw.js 직접 커스터마이징
      srcDir: 'src',
      filename: 'sw.js',
      includeAssets: ['pwa-192x192.png', 'pwa-512x512.png'],
      manifest: {
        name: 'My App',
        short_name: 'MyApp',
        start_url: '/',
        display: 'standalone',
        background_color: '#ffffff',
        theme_color: '#ffffff',
        icons: [
          {
            src: '/pwa-192x192.png',
            sizes: '192x192',
            type: 'image/png',
          },
          {
            src: '/pwa-512x512.png',
            sizes: '512x512',
            type: 'image/png',
          },
        ],
      },
      injectManifest: {
        globPatterns: ['**/*.{js,css,html,svg,png}'],
      },
      devOptions: {
        enabled: true,
        type: 'module',
        navigateFallback: 'index.html',
        navigateFallbackDenylist: [/^\/firebase-messaging-sw\.js$/],
        // firebase에서 기본적으로 firebase-messaging-sw.js 파일을 참고하려고 하기 때문에 이를 방지하려고 옵션을 추가. src/sw.js 사용해야함
      },
    }),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
});

src/sw.js 생성 (서비스워커 + 백그라운드 알림 포함)

/// <reference lib="webworker" />
import {
  cleanupOutdatedCaches,
  createHandlerBoundToURL,
  precacheAndRoute,
} from 'workbox-precaching';
import { clientsClaim } from 'workbox-core';
import { NavigationRoute, registerRoute } from 'workbox-routing';

precacheAndRoute(self.__WB_MANIFEST);
cleanupOutdatedCaches();
registerRoute(new NavigationRoute(createHandlerBoundToURL('index.html')));

self.skipWaiting();
clientsClaim();

// ✅ FCM 스크립트
importScripts('https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js');

firebase.initializeApp({
  apiKey: 'YOUR_API_KEY',
  authDomain: '...',
  projectId: '...',
  storageBucket: '...',
  messagingSenderId: '...',
  appId: '...',
});

const messaging = firebase.messaging();

messaging.onBackgroundMessage((payload) => {
  console.log('📦 백그라운드 메시지:', payload);
  const { title, body } = payload.notification || {};
  self.registration.showNotification(title || '알림', {
    body: body || '내용 없음',
    icon: '/pwa-192x192.png',
  });
});

④ Firebase 초기화 (src/firebase.js)

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

const app = initializeApp({
  apiKey: 'YOUR_API_KEY',
  authDomain: '...',
  projectId: '...',
  messagingSenderId: '...',
  appId: '...',
});

export const requestPermission = async () => {
  const permission = await Notification.requestPermission();
  if (permission === 'granted') {
    const registration = await navigator.serviceWorker.ready;
    const token = await getToken(getMessaging(app), {
      vapidKey: 'YOUR_VAPID_KEY',
      serviceWorkerRegistration: registration,
    });
    // 중요 여기 토큰 값이 메세지 테스트에 필요함
    console.log('🔥 FCM 토큰:', token);
    return token;
  }
};

export const listenForegroundMessage = () => {
  const messaging = getMessaging(app);
  onMessage(messaging, (payload) => {
    console.log('📥 포그라운드 메시지:', payload);
    const { title, body } = payload.notification || {};
    if (Notification.permission === 'granted') {
      new Notification(title ?? '알림', {
        body: body ?? '내용 없음',
        icon: '/pwa-192x192.png',
      });
    }
  });
};

⑤ FCM 토큰 발급 시 호출

useEffect(() => {
  requestPermission();
  listenForegroundMessage();
}, []);

⑥ 알림 테스트

  1. npm run build
  2. npm run preview
  3. Firebase 콘솔 → 클라우드 메시징 → 테스트 전송

아까 console에 찍었던 token 값을 저기 FCM 등록 토큰 추가 에 넣으면 된다


✅ 팁: 알림 안 뜰 때 체크리스트

문제해결 방법
알림 안 뜸윈도우/브라우저 알림 설정 켜기
icon 경로 오류/pwa-192x192.png 로 절대경로 사용
서비스워커 등록 안 됨vite.config.ts + src/sw.js 위치 확인
DevTools 열려 있음닫고 다시 테스트 (특히 백그라운드)

profile
1일 1백준을 목표로

0개의 댓글