Skip to content

Commit 29fe45b

Browse files
authored
Merge pull request #114 from projects200/feature/fcm-link
(#109) fcm 연동
2 parents ec223f9 + 42b20b9 commit 29fe45b

7 files changed

Lines changed: 128 additions & 33 deletions

File tree

next.config.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import withPWAInit from '@ducanh2912/next-pwa'
22

33
const pwaConfig = {
44
dest: 'public',
5-
disable: process.env.NODE_ENV === 'development',
5+
swSrc: 'src/firebase-messaging-sw.js',
6+
// disable: process.env.NODE_ENV === 'development',
67
register: true,
78
skipWaiting: true,
89
}

src/app/auth/login/page.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,29 @@ import Logo from '@/assets/logo.svg'
1010

1111
import styles from './login.module.css'
1212

13+
// 임시 알람 요청 테스트코드
14+
import { requestFcmToken } from '@/lib/firebase/config'
15+
1316
export default function Login() {
17+
// 임시 알람 요청 테스트코드
18+
const handleTestClick = async () => {
19+
const token = await requestFcmToken()
20+
if (token) {
21+
console.log('발급 토큰 : ', token)
22+
alert('토큰 발급 성공')
23+
} else {
24+
alert('토큰 발급 실패')
25+
}
26+
}
1427
return (
1528
<section className={styles['container']}>
16-
<Logo className={styles['logo']} width={150} height={150} />
29+
{/* 임시로 테스트를 위해 로고 클릭시 fcm토큰 요청하도록 구현했습니다. */}
30+
<Logo
31+
className={styles['logo']}
32+
width={150}
33+
height={150}
34+
onClick={handleTestClick}
35+
/>
1736
<Typography
1837
className={styles['title']}
1938
as="div"

src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Metadata } from 'next'
22
import { NuqsAdapter } from 'nuqs/adapters/next/app'
3-
import { Analytics } from '@/lib/firebase'
3+
import Analytics from '@/lib/firebase/analytics'
44

55
import { ClientProviders } from './_components/clientProviders'
66
import './reset.css'

src/firebase-messaging-sw.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
importScripts(
2+
'https://www.gstatic.com/firebasejs/9.22.1/firebase-app-compat.js',
3+
)
4+
importScripts(
5+
'https://www.gstatic.com/firebasejs/9.22.1/firebase-messaging-compat.js',
6+
)
7+
8+
const firebaseConfig = {
9+
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
10+
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
11+
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
12+
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
13+
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
14+
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
15+
}
16+
17+
firebase.initializeApp(firebaseConfig)
18+
19+
const messaging = firebase.messaging()
20+
21+
messaging.onBackgroundMessage(function (payload) {
22+
const notificationTitle = payload.notification.title
23+
const notificationOptions = {
24+
body: payload.notification.body,
25+
icon: '/icons/logo192.png',
26+
}
27+
28+
self.registration.showNotification(notificationTitle, notificationOptions)
29+
})

src/lib/firebase.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

src/lib/firebase/analytics.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use client'
2+
3+
import { useEffect } from 'react'
4+
import { getAnalytics, isSupported, logEvent } from 'firebase/analytics'
5+
import { firebaseApp } from './config'
6+
7+
function Analytics() {
8+
useEffect(() => {
9+
isSupported().then((supported) => {
10+
if (supported) {
11+
const analytics = getAnalytics(firebaseApp)
12+
logEvent(analytics, 'page_view', {
13+
page_path: window.location.pathname,
14+
})
15+
}
16+
})
17+
}, [])
18+
return null
19+
}
20+
21+
export default Analytics

src/lib/firebase/config.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { initializeApp, getApps, getApp, FirebaseApp } from 'firebase/app'
2+
import { getMessaging, getToken, Messaging } from 'firebase/messaging'
3+
4+
const firebaseConfig = {
5+
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
6+
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
7+
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
8+
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
9+
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
10+
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
11+
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
12+
}
13+
14+
const firebaseApp: FirebaseApp = !getApps().length
15+
? initializeApp(firebaseConfig)
16+
: getApp()
17+
18+
let messaging: Messaging | null = null
19+
20+
const initializeMessaging = () => {
21+
if (typeof window !== 'undefined') {
22+
if (!messaging) {
23+
messaging = getMessaging(firebaseApp)
24+
}
25+
}
26+
return messaging
27+
}
28+
29+
const requestFcmToken = async (): Promise<string | null> => {
30+
const messagingInstance = initializeMessaging()
31+
32+
if (!messagingInstance) return null
33+
34+
try {
35+
const serviceWorkerRegistration =
36+
await navigator.serviceWorker.register('/sw.js')
37+
38+
const permission = await Notification.requestPermission()
39+
if (permission !== 'granted') {
40+
return null
41+
}
42+
43+
const currentToken = await getToken(messagingInstance, {
44+
vapidKey: process.env.NEXT_PUBLIC_FIREBASE_VAPID_KEY,
45+
serviceWorkerRegistration: serviceWorkerRegistration,
46+
})
47+
48+
return currentToken
49+
} catch (err) {
50+
console.error('An error occurred while retrieving token. ', err)
51+
return null
52+
}
53+
}
54+
55+
export { firebaseApp, messaging, requestFcmToken }

0 commit comments

Comments
 (0)