Frontend/Javascript

PWA - 서비스 워커 웹 캐싱(service worker)

Developer Mobssie 2023. 4. 25. 16:39

* 서비스워커는 백그라운드에서 실행하는 스크립트

* 클라이언트에 설치되는 프록시 => Request를 가로채 Proxy Server와 비슷하게 동작

브라우저 백그라운드에서 네트워크를 가로채는 Thread

웹 캐싱은 CacheStorage를 사용.
Sqlite 같은 클라이언트 데이터베이스인데, Key:value 로 구성된 데이터베이스

ServiceWorker 적용 전 알아두어야할 점은 서비스워커는 보안상의 이유로 HTTPS에서만 실행

 

 

사용방법

public폴더(index.html이 있는)에 생성

메인 script파일에 다음과 같이 service-worker를 불러오는 구문을 추가

// navigator (브라우저)에 serviceWorker 기능이 있는지 확인
if ("serviceWorker" in navigator) {
  // 서비스워커 설치시 DOM 블로킹을 막아준다.
  window.addEventListener("load", function () {
    // 서비스워커를 register 하면 promise를 반환한다.
    navigator.serviceWorker
      .register("/sw.js")
      .then(() => {
        console.log("서비스 워커가 등록되었다.");
      })
      .catch((error) => {
        console.log(error);
      });
  });
}

 

 

 

 

 

// service-worker.js

var PRE_CACHE_NAME = "캐시-스토리지1";
// 캐시하고 싶은 리소스
var urlsToCache = [
  "/public/image/image1.png",
  "/public/css/font-awesome.min.css",
];

// 서비스워커가 설치될 때
self.addEventListener("install", (event) => {
  // 캐시 등록 이벤트가 끝날 때까지 기다려
  event.waitUntil(
    // '캐시-스토리지1'을 연다.
    // @return {Promise} 연결된 Cache Database를 반환한다.
    caches
      .open(PRE_CACHE_NAME)
      .then((cache) => {
        console.log("캐시 디비와 연결됨");
        // addAll 메소드로 내가 캐싱할 리소스를 다 넣어주자.
        return cache.addAll(urlsToCache);
      })
      .then(() => {
        // 설치 후에 바로 활성화 단계로 들어갈 수 있게 해준다.
        return self.skipWaiting();
      })
  );
});

 

 

오래된 캐시 삭제

// 서비스 워커가 활성화 될 때
self.addEventListener("activate", (event) => {
  // 영구적으로 가져갈 캐시 스트리지 화이트리스트
  var cacheWhiteList = [PRE_CACHE_NAME, DYNAMIC_CACHE_NAME];

  event.waitUntil(
    // 캐시 스토리지의 모든 스토리지명을 가져온다.
    caches.keys().then((cacheNames) => {
      // 캐시를 삭제하는 건 Promise를 반환하므로 Promise.all을 사용해 끝날 시점을 잡아야한다.
      return Promise.all(
        // 이 결과는 [Promise, Promise...] 형태가 되시겠다.
        cacheNames.map((cacheName) => {
          // 각각의 캐시 스토리지명이 화이트 리스트와 같지 않을 경우
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            // 캐시를 삭제하는 Promise를 배열에 추가한다.
            return caches.delete(cacheName);
          }
        })
      );
    })
  );

  // activate 시에는 clients claim 메소드를 호출해서
  // 브라우저에 대한 제어권을 가져와야한다.
  return self.clients.claim();
});

 

 

결과적으로 DYNAMIC_CACHE_NAME이 아닌 캐시 스토리지는 삭제된다.