pwa - push 이벤트 구현하기
PWA - Push Notification?
Javascript
로 를 통해 웹과 모바일에 푸쉬 메세지를 발송하는 PWA 기능입니다. 즉 브라우저에서 네이티브와 마찬가지로 사용자에게 알림 메세지를 보낼 수 있습니다. 아직 사파리 계열은 제대로 지원되고 있지 않지만 크롬, 안드로이드 에서는 네이티브와 같은 알림 메세지를 받아보실 수 있습니다. 이제 PWA의 푸쉬 메세지 기능을 추가해 보도록 하겠습니다.
FCM 키 발급.
우선 웹에서 푸쉬메세지를 받으려면 서버와 클라이언트(웹브라우저) 사이의 메세지가 필요한데 이를 위해 FCM을 사용합니다.
FCM 이란??
구글에서 제공하는 Server 와 Client app 간에 푸쉬 메시지를 보낼 수 있는 서비스로 웹, IOS, ANDROID 모두 지원 합니다.
1. FCM 프로젝트 생성
FCM을 사용하기 위해 https://console.firebase.google.com 로 접속하겠습니다.
해당 영역에서 푸쉬서비스를 위한 프로젝트 생성을 위해 프로젝트 추가
를 클릭해주도록 하겠습니다.
프로젝트에 대한 이름을 설정후 GA설정은 원한다면 선택후 프로젝트를 생성하게 되면 간단하게 프로젝트가 생성되게 됩니다.
2. FCM 서버 키 발급
생성된 프로젝트의 설정 메뉴 에서 클라우드 메세지
탭으로 이동합니다.
위의 메뉴에서 서버 키
를 사용하기 위해 해당 키를 복사해 두도록 하겠습니다. :)
service-worker 알림설정
서비스워커에 알림 허용 설정.
이제 service-worker
에서 알림 설정 세팅을 위해 코드를 작성해 보도록 하겠습니다.
export const PUSH_APPLICATION_SERVER_KEY = 'FCM 서버키를 넣어주세요.'; // 해시 처리 const urlB64ToUint8Array = (base64String: string) => { const padding = '='.repeat((4 - base64String.length % 4) % 4); const base64 = (base64String + padding) .replace(/\-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; }; // 구독하기 export const subscribeUser = (swRegistration) => { const applicationServerKey = urlB64ToUint8Array(PUSH_APPLICATION_SERVER_KEY); const ACCESS_PUSH_TOKEN = 'ACCESS_PUSH_TOKEN'; swRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: applicationServerKey, // 서버 키 등록 }).then((subscription) => { const pwaSubscription = JSON.parse(JSON.stringify(subscription)); localStorage.setItem(ACCESS_PUSH_TOKEN, pwaSubscription.keys.auth); // 추후 코드 제거를 위해 저장합니다. pushSubscription(pwaSubscription); }).catch(e => console.log(`subscribe error`, e)); }; export const pushSubscription = (subscription) => { // 서버로 구독 정보 전송 };
서비스 워커의 pushManager
를 통해 위에서 설정한 FCM 키를 통해 푸쉬메세지 구독에 대한 함수를 요청하였습니다. 이때 pushSubscription
을 통해 서버로 전송해 DB에 해당 값을 저장해 두도록 하겠습니다.
위에서의 pushManager
의 파라미터를 그대로 저장하게 되면 위의 구조처럼 정보가 저장됩니다.
위의 코드를 서비스 워커가 로드될때 불러주도록 설정하겠습니다.
if ('serviceWorker' in navigator && 'PushManager' in window) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then(reg => subscribeUser(reg)) .catch(e => console.log(e)); }); }
여기까지 설정후 프로젝트를 실행하면 알림 허용여부에 대한 창이 나오게 됩니다.
Push 메세지 처리
이제 서버에서 메세지가 내려올 경우의 처리를 하도록 하겠습니다.
브라우저에서는 서버에서 푸쉬가 오면 이를 service-worker에서 감지하는 함수가 존재합니다. 각 함수의 역할은 다음과 같습니다.
|함수명|역활| |---|---| |push|서버에서 알림 메세지가 오는것을 감지합니다.| |notificationclick| 알림창을 클릭했을때의 이벤트를 감지합니다.|
클라이언트
// 서버에서 푸쉬가 왔을때 감지하는 이벤트. self.addEventListener('push', function (event) { console.log(`Push had this data: "${event.data.text()}"`); const pushInfo = JSON.parse(event.data.text()); const options = { // 푸쉬 알림창에 대한 각종 설정 body: pushInfo.content, // 푸쉬 매세지에 대한 설정. icon: 'static/main-icon192x192.png', // 알림 아이콘 사이즈 data: {// 푸쉬메세지에 필요한 커스텀값들을 obj 형태로 전달 가능. url: pushInfo.url // 알림 클릭시 필요한 url 세팅. 커스텀 데이터 } }; //showNotification 에 첫 파라미터는 제목, 두번째는 위의 옵션 데이터를 넣어줍니다. event.waitUntil(self.registration.showNotification(pushInfo.title, options)); }); // 알림 메세지를 클릭했을때의 이벤트. self.addEventListener('notificationclick', function (event) { event.notification.close(); // 푸쉬 종료 처리 event.waitUntil( // `push` 에서 받은 url로 새창으로 열어 이동 clients.openWindow(event.notification.data.url) ); });
알림 서비스의 옵션은 진동 등 좀더 여러가지가 존재합니다. 이는 pwa-push-noti-guide 에서 좀더 자세히 보실 수 있습니다.
이제 서버에서 푸쉬메세지를 보내게 되면 다음과 같이 알림 설정이 오는것을 확인하실 수 있습니다.
알림 취소 작업
사용자는 웹어플리케이션 내부 혹은 브라우저 에서 알림을 취소 할 수 있습니다. 지금부터는 해당 기능을 추가해 보도록 하겠습니다.
push 알림 상태
pwa 의 push 에는 다음과 같은 3가지의 상태가 존재합니다. 해당 상태는 Notification
객체를 을 통해 알 수 있습니다.
|함수명|역활| |---|---| |default|알림 허용, 알림 거부 그 어떤것도 안한 기본 상태| |granted| 알림 허용 상태| |denied| 알림 거부 상태|
서비스 워커 등록 수정
서비스워커에서 알림 기본상태일때만 구독함수를 실행하고 허용상태가 아닐 경우 존재하는 알람 설정을 삭제하는 작업을 하도록 하겠습니다.
if ('serviceWorker' in navigator && 'PushManager' in window) { window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then(reg => initSubscribe(reg)) // 바로 subscribeUser 를 호출하지 않고 권한을 통해 판단. .catch(e => console.log(e)); }); } export const initSubscribe = (swRegistration) => { // 사용자가 브라우저에서 강제로 알람 차단 할 경우 남아있는 키 제거 if (Notification.permission !== 'granted') { removeAccessPushToken(); } // 알림 기본 설정일 경우 구독 시켜주기. if (Notification.permission === 'default') { subscribeUser(swRegistration); } };
위의 설정을 작성시 권한 설정을 안한 경우에만 subscribeUser 를 호출하고 권한 허용상태가 아닌 경우 토큰을 삭제 하도록 처리하도록 합니다. 이젠 발급된 키를 삭제하는 removeAccessPushToken
를 작성하도록 하겠습니다.
removeAccessPushToken 작성
const removeAccessPushToken = () => { const pwaSubscriptionKey = localStorage.getItem(ACCESS_PUSH_TOKEN); // subscribeUser 에서 저장한 키 가져오기 if (!pwaSubscriptionKey) { return; } pushUnsubscription(pwaSubscriptionKey); localStorage.removeItem(ACCESS_PUSH_TOKEN); }; cosnt pushUnsubscription = pwaSubscriptionKey => '서버로 해당 키 제거 요청'
위의 코드는 이전 subscribeUser
를 통해 구독이 완료되면 브라우저에 저장한 'auth' 정보를 가져와서 해당 정보가 존재하면 서버로 해당 키를 삭제하도록 처리하는 코드입니다. 위와같이 작성할 경우 사용자가 직접 구현한 기능으로 알림 취소를 하는것이 아닌 브라우저에서 알림 거부 를 설정해도 정상적으로 알림설정을 처리할 수 있는 장점이 있습니다.