PWA는 Progressive Web Application으로, 웹이 웹의 장점과 네이티브 앱의 장점을 모두 가질수 있도록 다양한 기술들과 표준 패턴을 사용해 개발된 웹 앱을 말합니다.
PWA 는 여러 가지의 기술의 집합체이며, 대표적인 기술에는 오프라인에서 동작, 설치, 동기화, 푸시 알림 등이 있습니다.
PWA을 개발하기 위해서는 Service Worker
와 Web App Manifest
를 알아야 합니다.
서비스워커는 자바스크립트 파일로 브라우저가 백그라운드에서 실행시키는 스크립트입니다. 브라우저가 focus 되어있지 않는 백그라운드 상태에서도 서비스워커 스크립트는 실행되고 있어서 네트워크에서 Push 방식으로 전달된 메시지를 받을 수 있습니다. 즉, 서비스워커가 백그라운드에서 실행되기 때문에 PWA의 주된 기술 중 하나인 "푸시 알림" 을 웹에 직접 접속해 있지 않아도 받을 수 있습니다.
Manifest
는 JSON 파일로, 앱에 대한 옵션들을 명시할 수 있습니다. 앱의 이름, 아이콘, 색상값 등이 포함됩니다. Manifest
파일에 정의된 값들은 앱이 설치 되었을때 보여줄 앱의 아이콘이나 이름등을 나타내게 됩니다.
따라서 웹 푸시 서비스는 서버가 보낸 푸시 알림을 받아서 브라우저에게 전달하는 역할을 합니다. 그리고 웹 푸시 서비스는 앞에서 설명한 서비스워커를 통해서 구현할 수 있습니다. 즉, 서비스워커 스크립트에 서버에서 보낸 알림을 받아서 브라우저에게 전달하는 코드를 작성하면 됩니다.
먼저 리액트를 create-react-app 으로 설치합니다.
npx create-react-app <project name>
FCM 을 사용하기 위해서는 파이어베이스를 설치해주어야 합니다.
npm install firebase
웹 푸시를 구현하기 위해서는 서비스 워커를 설정해야 합니다.
서비스워커 스크립트 파일은 public
폴더에 firebase-message-sw.js
라는 이름으로 따로 생성해주어야 합니다. 파일명이 반드시 firebase-message-sw.js
이어야 FCM 서비스를 이용할 수 있습니다.
!https://velog.velcdn.com/images/heelieben/post/26df9474-73ca-45fa-ab2e-405ac446f1b5/image.png
깃허브에서 서비스워커 코드 전문을 참고하세요.
서비스워커 스크립트가 설치되고 활성화 되었는지 "install" 과 "activat" 이벤트로 확인할 수 있습니다.
self
는 WorkerGlobalScope
인터페이스의 읽기 전용 프로퍼티로, WorkerGlobalScope
자체의 참조값 반환합니다.
self.addEventListener("install", function (e) {
console.log("fcm sw install..");
self.skipWaiting();
});
self.addEventListener("activate", function (e) {
console.log("fcm sw activate..");
});
서비스워커 스크립트에 백그라운드일 때에도 알림을 받을 수 있도록 이벤트를 등록할 수 있습니다.
Web push 알림을 "push" 이벤트로 확인할 수 있습니다.
e
이벤트 객체의 data
프로퍼티에는 웹 푸시 알림에 대한 옵션들을 확인할 수 있습니다.
self.registration.showNotification(title, options)
메서드를 사용해서 직접 웹 푸시에 대한 알림을 노출할 수 있습니다. 서비스워커는 백그라운드 환경에서도 동작하므로 브라우저가 focus 되어 있는 상태가 아니더라도 알림이 노출됩니다.
만약 웹 푸시 알림에 이미지가 삽입되었으면 한다면, options
값에 icon
프로퍼티를 추가해야 합니다.
self.addEventListener("push", function (e) {
if (!e.data.json()) return;
const resultData = e.data.json().notification;
const notificationTitle = resultData.title;
const notificationOptions = {
body: resultData.body,
icon: resultData.image, // 웹 푸시 이미지는 icon
tag: resultData.tag,
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
만약 웹 푸시 알림을 클릭했을 때 어떤 URL 을 열어주는 등과 같은 추가적인 기능을 구현하고 싶다면 "notificationclick" 이벤트를 사용하면 됩니다.
self.addEventListener("notificationclick", function (event) {
console.log("notification click");
const url = "/";
event.notification.close();
event.waitUntil(clients.openWindow(url));
});
PWA를 만족시키기 위해서는 Web App Manifest 수정할 필요가 있습니다.
해당 프로젝트를 npm start로 로컬에서 실행 시킨 후 개발자 도구에서 Lighthouse에서 pwa 적용여부를 확인할 수 있습니다.
초기 설정 후 analyze page load로 바로 확인해 보면 pwa 오류 하나가 나는 것을 확인할 수 있습니다.
Manifest doesn't have a maskable icon
이때 manifest.json 내의 아이콘 중 하나에 아래 값을 추가해 주면 정상적으로 pwa 설정이 완료되게 됩니다.
"purpose": "maskable"