전체 목록
브라우저Medium#107

Service Worker와 PWA의 동작 원리를 설명해주세요.

#브라우저#ServiceWorker#PWA#캐싱

답변 포인트

브라우저와 네트워크 사이에서 요청을 가로채는 백그라운드 스크립트를 떠올려보세요.

정답 및 해설

빠른 요약

Service Worker는 브라우저와 네트워크 사이에서 동작하는 백그라운드 스크립트입니다. fetch 이벤트를 가로채 캐시 응답을 반환하거나 네트워크 요청을 제어할 수 있습니다.

Service Worker는 브라우저와 네트워크 사이에서 동작하는 백그라운드 스크립트입니다. 이를 활용하면 오프라인 캐싱, 푸시 알림, 백그라운드 동기화 같은 PWA(Progressive Web App) 기능을 구현할 수 있습니다.

Service Worker의 특징

  • 웹 페이지와 별도의 스레드에서 실행됩니다.
  • DOM에 직접 접근할 수 없습니다.
  • HTTPS 환경 또는 localhost에서만 동작합니다.
  • 네트워크 요청을 가로채 캐시 응답을 반환할 수 있습니다.
  • 생명주기가 일반 페이지와 다릅니다.

등록

TypeScript
if ("serviceWorker" in navigator) {
  navigator.serviceWorker.register("/service-worker.js");
}

생명주기

Service Worker의 주요 단계는 다음과 같습니다.

  1. install: 최초 설치, 정적 자산 사전 캐싱
  2. activate: 이전 캐시 정리, 새 worker 활성화
  3. fetch: 네트워크 요청 가로채기
JavaScript
self.addEventListener("install", (event) => {
  event.waitUntil(
    caches.open("app-v1").then((cache) => {
      return cache.addAll(["/", "/styles.css", "/app.js"]);
    })
  );
});

self.addEventListener("activate", (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(keys.filter((key) => key !== "app-v1").map((key) => caches.delete(key)))
    )
  );
});

fetch 이벤트와 캐싱 전략

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

대표 전략:

전략설명적합한 대상
Cache First캐시를 먼저 사용, 없으면 네트워크해시가 붙은 정적 파일
Network First네트워크 우선, 실패 시 캐시최신성이 중요한 API
Stale While Revalidate캐시를 즉시 보여주고 백그라운드 갱신뉴스 피드, 목록
Cache Only캐시만 사용앱 셸
Network Only항상 네트워크 사용결제, 민감한 요청

PWA 구성 요소

PWA가 되려면 Service Worker 외에도 웹 앱 매니페스트가 필요합니다.

JSON
{
  "name": "DevRoutine",
  "short_name": "DevRoutine",
  "start_url": "/",
  "display": "standalone",
  "icons": [
    { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }
  ]
}

매니페스트는 홈 화면 설치, 앱 이름, 아이콘, 시작 URL, 표시 방식 등을 정의합니다.

주의사항

Service Worker는 한 번 설치되면 캐시와 함께 오래 남을 수 있습니다. 배포 후 오래된 파일이 계속 제공되지 않도록 캐시 버전 관리와 업데이트 전략을 명확히 해야 합니다.

JavaScript
const CACHE_NAME = "app-v2";

또한 인증이 필요한 API나 사용자별 데이터를 공유 캐시에 저장하면 보안 문제가 될 수 있습니다.

정리

Service Worker는 네트워크 요청을 제어하는 브라우저의 프록시 계층이고, PWA는 이를 매니페스트와 함께 활용해 설치 가능하고 오프라인에 강한 웹 앱을 만드는 접근입니다. 강력한 만큼 캐시 무효화와 보안 설계가 중요합니다.

Service Worker 동작 흐름

Service Worker는 브라우저와 네트워크 사이에 놓이는 프록시 같은 스크립트입니다. 페이지와 별도 생명주기를 가지며, 설치 후 fetch 요청을 가로채 캐시 응답, 오프라인 페이지, 백그라운드 동기화 등을 구현할 수 있습니다.

JavaScript
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open('static-v1').then((cache) => cache.addAll(['/', '/offline.html']))
  );
});

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

PWA 구성 요소

  • Web App Manifest: 앱 이름, 아이콘, 시작 URL, display 모드 정의
  • Service Worker: 캐싱, 오프라인, push 처리
  • HTTPS: 보안 컨텍스트에서만 대부분 기능 동작
  • 반응형 UI: 설치형 앱처럼 사용할 수 있는 화면 구성

업데이트에서 자주 생기는 문제

Service Worker는 즉시 교체되지 않고 기존 탭이 닫힐 때까지 대기할 수 있습니다. 새 버전 배포 후 “코드는 바뀌었는데 사용자는 옛 캐시를 보는” 문제가 생길 수 있으므로 버전 캐시 이름, skipWaiting, 사용자 새로고침 안내를 함께 설계합니다.

JavaScript
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then(keys => Promise.all(keys.filter(k => k !== 'static-v2').map(k => caches.delete(k))))
  );
});

관련 질문

같은 카테고리/태그 기준