/** * Service Worker for Video Caching * * 배경 영상 파일을 브라우저 Cache API에 저장하여 * 페이지 새로고침 시에도 네트워크 요청 없이 캐시에서 로드 */ const CACHE_NAME = 'evcp-video-cache-v1'; const VIDEO_URLS = [ '/background-videos/1.yard.mp4', '/background-videos/2.SN2635_LNGC_CARDIFF.mp4', '/background-videos/3.SN2628_CONT_WAN HAI.mp4', '/background-videos/4.SN2612_LNGC_KGL.mp4', '/background-videos/5.SN2596_LNGC_JP MORGAN.mp4', '/background-videos/6.2235_FLNG_ENI_CORAL.mp4', '/background-videos/7.2126_FLNG_PETRONAS.mp4', ]; // Service Worker 설치 시 영상 파일 프리캐시 self.addEventListener('install', (event) => { console.log('[Service Worker] Installing...'); event.waitUntil( caches.open(CACHE_NAME).then((cache) => { console.log('[Service Worker] Caching video files...'); // 각 비디오를 개별적으로 캐시 (하나 실패해도 다른 것은 계속) return Promise.allSettled( VIDEO_URLS.map((url) => cache.add(url).catch((err) => { console.warn(`[Service Worker] Failed to cache ${url}:`, err); return null; }) ) ); }).then(() => { console.log('[Service Worker] Video files cached successfully'); // 즉시 활성화 return self.skipWaiting(); }) ); }); // Service Worker 활성화 self.addEventListener('activate', (event) => { console.log('[Service Worker] Activating...'); event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { // 이전 버전 캐시 삭제 if (cacheName !== CACHE_NAME) { console.log('[Service Worker] Deleting old cache:', cacheName); return caches.delete(cacheName); } }) ); }).then(() => { // 모든 클라이언트에 즉시 적용 return self.clients.claim(); }) ); }); // 네트워크 요청 가로채기 self.addEventListener('fetch', (event) => { const url = new URL(event.request.url); // 배경 영상 파일 요청인 경우 if (url.pathname.startsWith('/background-videos/')) { event.respondWith( caches.match(event.request).then((cachedResponse) => { if (cachedResponse) { console.log('[Service Worker] Serving from cache:', url.pathname); return cachedResponse; } // 캐시에 없으면 네트워크에서 가져오고 캐시에 저장 console.log('[Service Worker] Fetching and caching:', url.pathname); return fetch(event.request).then((response) => { // 응답이 유효한 경우에만 캐시 if (response && response.status === 200) { const responseToCache = response.clone(); caches.open(CACHE_NAME).then((cache) => { cache.put(event.request, responseToCache); }); } return response; }); }) ); } // 다른 요청은 그대로 통과 }); // 메시지 리스너 (캐시 상태 확인용) self.addEventListener('message', (event) => { if (event.data && event.data.type === 'GET_CACHE_STATUS') { caches.open(CACHE_NAME).then((cache) => { Promise.all( VIDEO_URLS.map((url) => cache.match(url).then((response) => !!response)) ).then((results) => { const cachedCount = results.filter(Boolean).length; event.ports[0].postMessage({ total: VIDEO_URLS.length, cached: cachedCount, urls: VIDEO_URLS.map((url, i) => ({ url, cached: results[i], })), }); }); }); } if (event.data && event.data.type === 'CLEAR_CACHE') { caches.delete(CACHE_NAME).then(() => { event.ports[0].postMessage({ success: true }); }); } });