[ETC] Browser Service Worker
2022. 11. 22. 10:15ㆍETC
서비스워커란?
서비스워커는 브라우저가 백그라운드에서 실행하는 스크립트로, 웹페이지와는 별개로 작동하며 웹페이지 또는 사용자의 인터랙션이 필요하지 않은 기능만 제공하고 있습니다.
서비스워커의 수명 주기는 웹페이지와는 완전히 별개입니다. 웹 서비스와 브라우저 및 네트워크 사이에서 프록시 서버의 역할을 하며, 오프라인에서도 서비스를 사용할 수 있도록 합니다.
주의
ServiceWorker 적용 전 알아두어야할 점은 서비스워커는 보안상의 이유로 HTTPS에서만 실행이 됩니다.
서비스워커 사용
서비스워커를 사용하기 위해서는 먼저 등록하는 단계가 필요합니다.
async function registerServiceWorker() {
const swRegistration = await navigator.serviceWorker.register(
"https://test.io/service_worker.js"
);
return swRegistration;
}
이후 앞단에서 서비스워커 허가를 요청, 지원 여부를 판단하는 함수
function checkSupport() {
if (!("serviceWorker" in navigator)) {
alert("Service worker needed for sending push is not supported by your browser");
throw new Error("No Service Worker support!");
} else {
console.log("Service worker supported✅");
}
if (!("PushManager" in window)) {
alert("Push API needed for sending push is not supported by your browser");
throw new Error("No Push API Support!");
} else {
console.log("Push API supported✅");
}
}
async function requestNotificationPermission() {
const permission = await window.Notification.requestPermission();
//'granted', 'default', or 'denied'
if (permission !== "granted") {
console.error("Permission not granted for Notification");
}
}
등록, 설치 과정까지 마쳤다면, 활성화 단계로 넘어갑니다.
활성화는 activate 이벤트를 핸들링하여 조작할 수 있습니다.
self.addEventListener("activate", async () => {
// This will be called only once the service worker is activated
console.log("activating service worker");
try {
const applicationServerKey = urlB64ToUint8Array(
// key generated for the app (VAPID)
"KEY..."
);
const options = { applicationServerKey, userVisibleOnly: true };
const subscription = await self.registration.pushManager.subscribe(options);
const response = await saveSubscription(subscription.toJSON());
} catch (e) {
console.log("Error", e);
}
console.log("service worker activated");
});
활성화 후 이제 본 서비스워커는 기능적인 이벤트를 처리할 수 있습니다. ( push, fetch 등... )
서비스 워커 활성화 후 해당 구독 정보를 서버단으로 보내 값을 저장하고 처리할 수 있습니다.
const saveSubscription = async (subscription) => {
//backend endpoint
const saveSubEndpoint = "https://test.io/save-subscription";
const response = await fetch(saveSubEndpoint, {
method: "post",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-origin": "*",
"Access-Control-Allow-Credentials": "true"
},
body: JSON.stringify(subscription),
});
console.log(response);
return response;
};
서버단에서는 넘겨받은 구독정보를 통해 푸시 이벤트를 발생 시켜 보겠습니다.
const express = require('express');
const webpush = require('web-push');
const bodyParser = require('body-parser');
const path = require('path');
let Mysql = require("./mysqldb/database");
let timez = require("moment-timezone");
require("dotenv").config();
const app = express();
const PUBLIC_KEY = process.env.PUBLIC_KEY;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const port = 5000;
app.use(express.static(path.join(__dirname, "client")));
app.use(bodyParser.json());
webpush.setVapidDetails('mailto:random@email.com', PUBLIC_KEY, PRIVATE_KEY);
app.post('/save-subscription', async (req, res) => {
const subscription = req.body;
const nData = await Mysql.Noti_Get_Data();
const cData = await Mysql.Crawling_Get_Data();
Mysql.Sub_Insert_Data(req.body);
if (cData[0].length !== 0) {
const payload = JSON.stringify({
title: cData[0][0].market,
url: nData[0][0].not_url,
message: nData[0][0].not_message,
});
// pass Object into sendNotification
webpush.sendNotification(subscription, payload).catch((err) => console.log(err));
}
else return console.log('push no exists...');
});
app.listen(port, () => console.log(`server started on port ${port}`));
해당 코드는, 5000 포트로 열려있으며 /save-subscription 라우트로 요청이 올 경우 알림 전송을 하고 있습니다.
이렇게 푸시 된 이벤트를 앞단에서 형식에 맞게 푸시 알림을 구현하면 끝입니다.
self.addEventListener("push", function (event) {
if (event.data) {
console.log("Push event!! ", event.data.text());
showLocalNotification("Message from backend", event.data.text(), self.registration);
} else {
console.log("Push event but no data");
}
});
const showLocalNotification = (title, body, swRegistration) => {
const options = {
body,
};
swRegistration.showNotification(title, options);
};
'ETC' 카테고리의 다른 글
[ETC] Debounce 와 Throttle 차이점 (0) | 2022.12.06 |
---|---|
[Homestead] 디렉토리 추가 (0) | 2022.12.02 |
[ETC] Chrome CORS 이슈 회피 (0) | 2022.11.22 |
[ETC] 개발 Tools (0) | 2022.09.06 |
[ETC] 개발 용어 정리 (0) | 2022.08.31 |