- public/service-worker.js 파일 내에 위치하였고, index.html 파일 실행 시 해당 스크립트 파일을 실행시킵니다. - 실행이 되면, ‘1. 서비스 워커 설치 (최초 1회 실행)가 실행’되어서 서비스 워커가 실행이 됩니다. 그리고 활성화되었을 때, 활성화 이벤트를 추가하였습니다.
/**
* 1. 서비스 워커 설치 (최초 1회 실행)
*/
self.addEventListener("install", (event) => {
console.log("서비스 워커가 설치되었습니다!");
// 대기 중인 서비스 워커를 즉시 활성화
self.skipWaiting();
});
/**
* 2. 서비스 워커 활성화
*/
self.addEventListener("activate", (event) => {
console.log("서비스 워커가 활성화되었습니다!");
});
/**
* 3. 네트워크 요청 가로채기 (PWA 오프라인 작동의 핵심)
*/
self.addEventListener("fetch", (event) => {
// 현재는 통과시키지만, 나중에 캐싱 로직을 여기에 넣습니다.
});
3. index.html
💡 index.html
- 최초 실행되는 페이지 내에 서비스 워커 지원여부에 따라, 이전에 생성한 파일을 기반으로 서비스 워커 등록을 수행하도록 처리합니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>prototype-react-csr</title>
</head>
<body>
<div id="root"></div>
<script>
// 브라우저가 서비스 워커를 지원하는지 확인 후 등록
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(() => console.log("서비스 워커 등록 완료!"))
.catch((err) => console.log("등록 실패:", err));
}
</script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
4. Chrome 결과 확인
💡 Chrome 결과 확인
- 관리자모드 (F12)로 실행하여 애플리케이션(Application) > Service workers로 이동하여서 확인을 하면 정상적으로 실행이 됨을 확인하였습니다.
5. 앱으로 실행하기
💡 앱으로 실행하기
- Chrome 가장 오른쪽 점 3개 아이콘(⋮)을 누르고 > 전송, 저장, 공유 > 페이지를 앱으로 설치를 선택합니다.
💡 설치 버튼을 누릅니다.
💡 아래와 같이 실행이 되었습니다.
4) PWA 푸시 메시지 테스트
💡 PWA 푸시메시지 테스트
1. 푸시 메시지 권한 요청
💡 푸시 메시지 권한 요청
- 아래와 같이 화면 실행 시 권한을 체크하는 부분을 추가하였습니다. - 상태를 체크하고, 권한이 없는 경우 Notification.requestPermission()를 통해서 권한 요청을 수행합니다.
useEffect(() => {
requestNotificationPermission();
}, []);
const requestNotificationPermission = async () => {
// 브라우저가 알림을 지원하는지 확인
if (!('Notification' in window)) {
console.log('이 브라우저는 알림을 지원하지 않습니다.');
return false;
}
// 이미 권한이 있는 경우
if (Notification.permission === 'granted') {
console.log('알림 권한이 이미 허용되어 있습니다.');
return true;
}
// 권한 거부된 경우
if (Notification.permission === 'denied') {
console.log('알림 권한이 거부되었습니다.');
return false;
}
// 권한 요청
const permission = await Notification.requestPermission();
if (permission === 'granted') {
console.log('알림 권한이 허용되었습니다.');
return true;
} else {
console.log('알림 권한이 거부되었습니다.');
return false;
}
}
2. 푸시 메시지 전송
💡 푸시 메시지 전송
- 아래의 함수에서 푸시메시지 전송 테스트를 수행합니다. - 권한 체크를 한번 더 수행한 이후에 navigator.serviceWorker.getRegistration() 함수로 서비스 워커 등록 상태를 확인합니다. - 서비스 워커 등록이 완료된 경우, registration.showNotification()를 통해서 전송하려는 메시지를 구성합니다.
const sendTestPush = async () => {
if (permission !== "granted") {
alert("알림 권한이 허용되지 않았습니다.");
return;
}
try {
const registration = await navigator.serviceWorker.getRegistration();
if (registration) {
await registration.showNotification("로컬 테스트 알림", {
body: "Service Worker를 통한 직접 알림입니다!",
icon: "/icon-192.png",
badge: "/icon-192.png",
requireInteraction: true, // 자동으로 안 사라지게
data: { url: "/" }
});
console.log("✅ 알림 전송 완료!");
}
} catch (error) {
console.error("❌ 알림 전송 실패:", error);
}
};
3. 전송 테스트
💡 전송 테스트
- 구성한 버튼을 클릭하거나 Service Worker 메뉴에서 선택하여서 푸시 메시지를 전송합니다.
💡 아래와 같이 버튼을 눌렀을때, 푸시 메시지가 정상적으로 출력이 됨을 확인하였습니다.
💡 아래와 같이 Service Worker 메뉴에서 푸시 메시지가 정상적으로 출력이 됨을 확인하였습니다.
[더 알아보기]
💡 PWA를 구성한 상태에서 알람을 다른 다른 사람에게 보내려면 어떻게 해야 할까?
- 사용자 A의 PWA를 백엔드 서버를 통해서 사용자 B의 PWA로 전송하는 ‘web-push’를 사용합니다.
5) PWA 미디어 쿼리
💡 PWA 미디어 쿼리
- 미디어 쿼리는 반응형 디자인의 핵심으로, CSS @media를 사용하여 화면 크기(모바일/데스크톱)에 맞춰 레이아웃을 조정하고 설치형 앱 모드(display-mode)에 따라 스타일을 차별화합니다. - display-mode: standalone 등을 통해 브라우저 UI 없이 네이티브 앱처럼 보이도록 사용자 환경을 최적화할 수 있습니다.
1. 코드 확인
💡 아래와 같은 미디어 쿼리를 적용하였습니다.
- @media (min-width: 768px)와 @media (min-width: 1200px)에 맞게 각각 적용하여서 반응형 디자인이 적용되었습니다.