Service Worker 생명주기 — install, activate, fetch의 순서

PWA의 핵심, 오프라인 캐시가 동작하는 메커니즘

// sw.js
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('v1').then(cache => cache.addAll(['/index.html', '/app.js', '/style.css']))
  );
});

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request))
  );
});

생명주기

1. register — 메인 페이지에서 navigator.serviceWorker.register('/sw.js'). SW 파일을 다운로드.

2. install — SW가 처음 설치될 때 1회 실행. 여기서 Cache API로 정적 자원을 미리 캐시(pre-cache)한다.

3. waiting — 이전 버전의 SW가 아직 활성화되어 있으면 새 SW가 대기. skipWaiting()으로 즉시 활성화 가능.

4. activate — 이전 SW가 해제되면 활성화. 여기서 오래된 캐시를 정리한다.

5. fetch — 이제부터 모든 네트워크 요청을 가로챈다. 캐시에서 응답하거나, 네트워크에서 가져오거나, 둘을 조합.

캐시 전략

  • Cache First — 캐시에 있으면 캐시, 없으면 네트워크. 정적 자원에 적합.

  • Network First — 네트워크 시도, 실패하면 캐시. API 응답에 적합.

  • Stale While Revalidate — 캐시를 즉시 반환하면서 백그라운드에서 네트워크 갱신. 속도+최신성 균형.

주의점

SW는 HTTPS에서만 동작한다 (localhost 예외). 업데이트가 즉시 반영 안 되는 건 waiting 단계 때문. clients.claim()으로 즉시 제어 가능.

SW가 한 번 등록되면 삭제하지 않는 한 브라우저에 영구 상주한다. 버그가 있는 SW를 배포하면 사용자가 캐시를 직접 지우기 전까지 계속 버그가 발생한다 — 이래서 SW 업데이트 전략이 중요하다.

핵심 포인트

1

register → install(정적 자원 pre-cache) → activate(오래된 캐시 정리) → fetch(요청 가로채기)

2

fetch 이벤트에서 캐시/네트워크 전략 선택 (Cache First, Network First 등)

3

HTTPS 필수 (localhost 예외). skipWaiting() + clients.claim()으로 즉시 활성화

4

SW 업데이트 전략이 중요 — 버그 있는 SW가 영구 상주할 수 있다

사용 사례

PWA — 오프라인에서도 작동하는 웹앱 정적 사이트 캐싱 — 블로그/문서 사이트의 즉시 로딩