웹 푸시 구현 예제
npm install @nativify/notifications firebase
// composables/useNotification.js
import { ref, onMounted, onUnmounted } from 'vue';
import { getNotificationService } from '@nativify/notifications';
export function useNotification() {
// 반응형 상태
const service = ref(null); // 알림 서비스
const notifications = ref([]); // 알림 목록
const token = ref(null); // FCM 토큰
const permission = ref('default'); // 권한 상태
// Firebase 설정
const initFirebase = () => {
window.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,
vapidKey: import.meta.env.VITE_FIREBASE_VAPID_KEY
};
};
// 서비스 초기화
const initialize = async () => {
try {
initFirebase();
service.value = getNotificationService();
await service.value.initialize();
// 메시지 수신 리스너
service.value.onMessageReceived(handleMessage);
} catch (error) {
console.error('초기화 실패:', error);
}
};
// 권한 요청
const requestPermission = async () => {
try {
permission.value = await service.value.requestPermission();
if (permission.value === 'granted') {
token.value = await service.value.getToken();
console.log('FCM Token:', token.value);
// 서버에 토큰 등록
await registerToken();
}
} catch (error) {
console.error('권한 요청 실패:', error);
}
};
// 토큰 서버 등록
const registerToken = async () => {
const appId = 'delivery_app_001'; // Console 앱 ID
const appUserId = 'user123'; // 실제 앱 사용자 ID
try {
await service.value.registerUserToken(
appId,
appUserId,
'https://your-server.com/api/notifications'
);
} catch (error) {
console.error('토큰 등록 실패:', error);
}
};
// 메시지 수신 처리
const handleMessage = (message) => {
notifications.value.unshift({
id: Date.now(),
title: message.notification?.title || '알림',
body: message.notification?.body || '',
timestamp: new Date()
});
};
// 컴포넌트 마운트 시 초기화
onMounted(async () => {
await initialize();
});
// 컴포넌트 언마운트 시 정리
onUnmounted(() => {
if (service.value) {
service.value.onMessageReceived(null);
}
});
return {
notifications,
token,
permission,
requestPermission
};
}
<script setup>
import { useNotification } from './composables/useNotification';
// Composable 사용
const { notifications, token, permission, requestPermission } = useNotification();
</script>
<template>
<div class="app">
<h1>웹 푸시 알림 데모</h1>
<!-- 권한 요청 버튼 -->
<button
@click="requestPermission"
v-if="permission !== 'granted'"
class="btn-primary"
>
알림 권한 요청
</button>
<!-- FCM 토큰 표시 -->
<div v-if="token" class="token-display">
<strong>FCM Token:</strong>
<code>{{ token }}</code>
</div>
<!-- 알림 목록 -->
<div class="notifications">
<h2>받은 알림</h2>
<div
v-for="notif in notifications"
:key="notif.id"
class="notification-item"
>
<h3>{{ notif.title }}</h3>
<p>{{ notif.body }}</p>
<small>{{ notif.timestamp.toLocaleString() }}</small>
</div>
<p v-if="notifications.length === 0" class="empty">
받은 알림이 없습니다.
</p>
</div>
</div>
</template>
<style scoped>
.notification-item {
background: #f7fafc;
border-left: 4px solid #42b883;
padding: 15px;
margin: 10px 0;
border-radius: 8px;
}
.token-display {
background: #ebf8ff;
padding: 15px;
border-radius: 8px;
margin: 20px 0;
}
.btn-primary {
background: #42b883;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
}
.btn-primary:hover {
background: #35495e;
}
</style>
public/firebase-messaging-sw.js 생성:
importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: "YOUR_API_KEY",
projectId: "YOUR_PROJECT_ID",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
});
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon || '/icon.png'
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
.env 파일 생성:
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
VITE_FIREBASE_VAPID_KEY=your_vapid_key
.env 파일에 Firebase 설정 입력firebase-messaging-sw.js 파일을 public/ 폴더에 배치npm install - 패키지 설치npm run dev - 개발 서버 실행