Feat: Firebase FCM 구현 완료, 테스트 중
This commit is contained in:
parent
628503dd27
commit
de723381b3
@ -15,6 +15,10 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="/serviceWorkerRegistration.js"
|
||||||
|
></script>
|
||||||
<script
|
<script
|
||||||
type="module"
|
type="module"
|
||||||
src="/src/main.tsx"
|
src="/src/main.tsx"
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
// import { initializeApp } from 'firebase/app';
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
// import { getMessaging } from 'firebase/messaging';
|
/* eslint-disable no-undef */
|
||||||
|
importScripts('https://www.gstatic.com/firebasejs/8.7.1/firebase-app.js');
|
||||||
|
importScripts('https://www.gstatic.com/firebasejs/8.7.1/firebase-messaging.js');
|
||||||
|
|
||||||
// const firebaseConfig = {
|
self.addEventListener('install', (_) => {
|
||||||
// apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
self.skipWaiting();
|
||||||
// authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
});
|
||||||
// projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
||||||
// storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
||||||
// messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
||||||
// appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
||||||
// measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// export const app = initializeApp(firebaseConfig);
|
self.addEventListener('activate', (_) => {
|
||||||
// export const messaging = getMessaging(app);
|
console.log('FCM service worker가 실행되었습니다.');
|
||||||
|
});
|
||||||
|
|
||||||
|
const firebaseConfig = {};
|
||||||
|
|
||||||
|
firebase.initializeApp(firebaseConfig);
|
||||||
|
const messaging = firebase.messaging();
|
||||||
|
|
||||||
|
messaging.onBackgroundMessage((payload) => {
|
||||||
|
const notificationTitle = payload.data.title;
|
||||||
|
const notificationOptions = {
|
||||||
|
body: payload.data.body,
|
||||||
|
icon: payload.data.image,
|
||||||
|
data: {
|
||||||
|
url: payload.data.url, // 알림 클릭시 이동할 URL
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.registration.showNotification(notificationTitle, notificationOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 알림 클릭 이벤트 처리
|
||||||
|
self.addEventListener('notificationclick', (event) => {
|
||||||
|
event.notification.close(); // 알림 닫기
|
||||||
|
|
||||||
|
// 알림에서 설정한 URL로 이동
|
||||||
|
const clickActionUrl = event.notification.data.url;
|
||||||
|
|
||||||
|
if (clickActionUrl) {
|
||||||
|
event.waitUntil(clients.openWindow(clickActionUrl));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
56
frontend/public/serviceWorkerRegistration.js
Normal file
56
frontend/public/serviceWorkerRegistration.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { initializeApp } from 'https://www.gstatic.com/firebasejs/9.1.3/firebase-app.js';
|
||||||
|
import { getMessaging, getToken } from 'https://www.gstatic.com/firebasejs/9.1.3/firebase-messaging.js';
|
||||||
|
|
||||||
|
const firebaseConfig = {};
|
||||||
|
|
||||||
|
const firebaseApp = initializeApp(firebaseConfig);
|
||||||
|
const messaging = getMessaging(firebaseApp);
|
||||||
|
|
||||||
|
const registerServiceWorker = async () => {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
try {
|
||||||
|
console.log('Service Worker 등록 중...');
|
||||||
|
const firebaseRegistration = await navigator.serviceWorker.register('/firebase-messaging-sw.js');
|
||||||
|
console.log('Service Worker 등록 성공');
|
||||||
|
|
||||||
|
console.log('Service Worker 활성화 중...');
|
||||||
|
const serviceWorker = await navigator.serviceWorker.ready;
|
||||||
|
console.log('Service Worker 활성화 성공');
|
||||||
|
|
||||||
|
if (serviceWorker && !sessionStorage.getItem('fcmToken')) {
|
||||||
|
const permission = await Notification.requestPermission();
|
||||||
|
|
||||||
|
if (permission === 'granted') {
|
||||||
|
console.log('알림 권한이 허용되었습니다.');
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('FCM 토큰 발급 중...');
|
||||||
|
const currentToken = await getToken(messaging, {
|
||||||
|
vapidKey: 'BApIruZrx83suCd09dnDCkFSP_Ts08q38trrIL6GHpChtbjQHTHk_38_JRyTiKLqciHxLQ8iXtie3lvgyb4Iphg',
|
||||||
|
serviceWorkerRegistration: firebaseRegistration,
|
||||||
|
});
|
||||||
|
console.log('FCM 토큰 발급 성공');
|
||||||
|
|
||||||
|
if (currentToken) {
|
||||||
|
sessionStorage.setItem('fcmToken', currentToken);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('FCM 토큰을 가져올 수 없습니다.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('알림 권한이 거부되었습니다.');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Service Worker 등록에 실패했습니다. : ', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('현재 브라우저에서 Service Worker를 지원하지 않습니다.');
|
||||||
|
};
|
||||||
|
|
||||||
|
registerServiceWorker();
|
@ -17,6 +17,6 @@ export async function saveFcmToken(token: string) {
|
|||||||
return api.post('/auth/fcm', { token }).then(({ data }) => data);
|
return api.post('/auth/fcm', { token }).then(({ data }) => data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createTestNotification() {
|
export async function createFcmNotification() {
|
||||||
return api.post('/auth/test').then(({ data }) => data);
|
return api.post('/auth/test').then(({ data }) => data);
|
||||||
}
|
}
|
||||||
|
60
frontend/src/api/firebaseConfig.ts
Normal file
60
frontend/src/api/firebaseConfig.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
import { getMessaging, getToken, onMessage } from 'firebase/messaging';
|
||||||
|
|
||||||
|
const firebaseConfig = {
|
||||||
|
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
||||||
|
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
||||||
|
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
||||||
|
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
||||||
|
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
||||||
|
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
||||||
|
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
const firebaseApp = initializeApp(firebaseConfig);
|
||||||
|
const messaging = getMessaging(firebaseApp);
|
||||||
|
|
||||||
|
const getFcmToken = async () => {
|
||||||
|
const existingToken = sessionStorage.getItem('fcmToken');
|
||||||
|
|
||||||
|
if (existingToken) {
|
||||||
|
return existingToken; // 이미 토큰이 있는 경우, 해당 토큰을 반환한다.
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const permission = await Notification.requestPermission();
|
||||||
|
|
||||||
|
if (permission === 'granted') {
|
||||||
|
const currentToken = await getToken(messaging, {
|
||||||
|
vapidKey: 'BGVbiPhLWWxijrc2jfn9lTyDs-kcSfSinb2bUmEoDXSc8ljx6sWtur9k82vmjBLND06SSeb10oq-rw7zmzrpoPY',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentToken) {
|
||||||
|
sessionStorage.setItem('fcmToken', currentToken);
|
||||||
|
return currentToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn('FCM 토큰을 가져올 수 없습니다.');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('알림 권한이 거부되었습니다.');
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('FCM 토큰을 가져오는 중 오류가 발생했습니다 : ', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleForegroundMessages = () => {
|
||||||
|
onMessage(messaging, (payload) => {
|
||||||
|
console.log('onMessage');
|
||||||
|
console.log(payload);
|
||||||
|
|
||||||
|
if (!payload.data) return;
|
||||||
|
|
||||||
|
console.log(payload.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getFcmToken, handleForegroundMessages, messaging };
|
@ -1,13 +0,0 @@
|
|||||||
import { initializeApp } from 'firebase/app';
|
|
||||||
|
|
||||||
const firebaseConfig = {
|
|
||||||
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
|
|
||||||
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
|
|
||||||
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
|
|
||||||
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
|
|
||||||
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
|
|
||||||
appId: import.meta.env.VITE_FIREBASE_APP_ID,
|
|
||||||
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const firebaseApp = initializeApp(firebaseConfig);
|
|
@ -1,98 +1,49 @@
|
|||||||
import { createTestNotification, saveFcmToken } from '@/api/authApi';
|
import { createFcmNotification, saveFcmToken } from '@/api/authApi';
|
||||||
|
import { getFcmToken, handleForegroundMessages } from '@/api/firebaseConfig';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { firebaseApp } from '@/firebase';
|
|
||||||
import { getMessaging, getToken, onMessage } from 'firebase/messaging';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
export default function FirebaseTest() {
|
export default function FirebaseTest() {
|
||||||
useEffect(() => {
|
const handleSaveFcmToken = async () => {
|
||||||
const messaging = getMessaging(firebaseApp);
|
const fcmToken = await getFcmToken();
|
||||||
|
|
||||||
onMessage(messaging, (payload) => {
|
|
||||||
console.log('Message recieved. ', payload);
|
|
||||||
|
|
||||||
if (!payload || !payload.notification) return;
|
|
||||||
|
|
||||||
const { title, body } = payload.notification;
|
|
||||||
|
|
||||||
if (!title || !body) return;
|
|
||||||
|
|
||||||
new Notification(title, { body });
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getFcmToken = async () => {
|
|
||||||
const existingToken = sessionStorage.getItem('fcmToken');
|
|
||||||
|
|
||||||
if (existingToken) {
|
|
||||||
console.log(existingToken);
|
|
||||||
return existingToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const permission = await Notification.requestPermission();
|
|
||||||
|
|
||||||
if (permission === 'granted') {
|
|
||||||
const messaging = getMessaging(firebaseApp);
|
|
||||||
const currentToken = await getToken(messaging, {
|
|
||||||
vapidKey: 'BApIruZrx83suCd09dnDCkFSP_Ts08q38trrIL6GHpChtbjQHTHk_38_JRyTiKLqciHxLQ8iXtie3lvgyb4Iphg',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (currentToken) {
|
|
||||||
console.log(currentToken);
|
|
||||||
sessionStorage.setItem('fcmToken', currentToken);
|
|
||||||
return currentToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.warn('FCM 토큰을 가져올 수 없습니다. 권한이 없거나 문제가 발생했습니다.');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('알림 권한이 거부되었습니다.');
|
|
||||||
return null;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('FCM 토큰을 가져오는 중 오류가 발생했습니다.');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveToken = () => {
|
|
||||||
const fcmToken = sessionStorage.getItem('fcmToken');
|
|
||||||
console.log(fcmToken);
|
|
||||||
|
|
||||||
if (fcmToken) {
|
if (fcmToken) {
|
||||||
saveFcmToken(fcmToken);
|
await saveFcmToken(fcmToken);
|
||||||
|
console.log(fcmToken);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('저장된 FCM token이 없습니다.');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTestNotification = () => {
|
const handleTestNotification = async () => {
|
||||||
createTestNotification();
|
await createFcmNotification()
|
||||||
console.log('ok');
|
.then(() => {
|
||||||
|
console.log('테스트 알림에 성공했습니다.');
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log('테스트 알림에 실패했습니다.');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleForegroundMessages();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1 className="heading p-2">hello, firebase!</h1>
|
<h1 className="heading p-2">hello, firebase!</h1>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<Button
|
<Button
|
||||||
onClick={getFcmToken}
|
onClick={handleSaveFcmToken}
|
||||||
variant="outlinePrimary"
|
variant="outlinePrimary"
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
>
|
>
|
||||||
getFcmToken
|
FCM 토큰 불러와서 redis에 저장
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={handleSaveToken}
|
|
||||||
variant="outlinePrimary"
|
|
||||||
className="mr-2"
|
|
||||||
>
|
|
||||||
handleSaveToken
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleTestNotification}
|
onClick={handleTestNotification}
|
||||||
variant="outlinePrimary"
|
variant="outlinePrimary"
|
||||||
|
className="mr-2"
|
||||||
>
|
>
|
||||||
handleTestNotification
|
FCM 알림 테스트
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user