Service Worker와 PWA의 동작 원리를 설명해주세요.
답변 포인트
브라우저와 네트워크 사이에서 요청을 가로채는 백그라운드 스크립트를 떠올려보세요.
정답 및 해설
빠른 요약
Service Worker는 브라우저와 네트워크 사이에서 동작하는 백그라운드 스크립트입니다. fetch 이벤트를 가로채 캐시 응답을 반환하거나 네트워크 요청을 제어할 수 있습니다.
Service Worker는 브라우저와 네트워크 사이에서 동작하는 백그라운드 스크립트입니다. 이를 활용하면 오프라인 캐싱, 푸시 알림, 백그라운드 동기화 같은 PWA(Progressive Web App) 기능을 구현할 수 있습니다.
Service Worker의 특징
- 웹 페이지와 별도의 스레드에서 실행됩니다.
- DOM에 직접 접근할 수 없습니다.
- HTTPS 환경 또는 localhost에서만 동작합니다.
- 네트워크 요청을 가로채 캐시 응답을 반환할 수 있습니다.
- 생명주기가 일반 페이지와 다릅니다.
등록
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/service-worker.js");
}생명주기
Service Worker의 주요 단계는 다음과 같습니다.
- install: 최초 설치, 정적 자산 사전 캐싱
- activate: 이전 캐시 정리, 새 worker 활성화
- fetch: 네트워크 요청 가로채기
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 이벤트와 캐싱 전략
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 외에도 웹 앱 매니페스트가 필요합니다.
{
"name": "DevRoutine",
"short_name": "DevRoutine",
"start_url": "/",
"display": "standalone",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" }
]
}매니페스트는 홈 화면 설치, 앱 이름, 아이콘, 시작 URL, 표시 방식 등을 정의합니다.
주의사항
Service Worker는 한 번 설치되면 캐시와 함께 오래 남을 수 있습니다. 배포 후 오래된 파일이 계속 제공되지 않도록 캐시 버전 관리와 업데이트 전략을 명확히 해야 합니다.
const CACHE_NAME = "app-v2";또한 인증이 필요한 API나 사용자별 데이터를 공유 캐시에 저장하면 보안 문제가 될 수 있습니다.
정리
Service Worker는 네트워크 요청을 제어하는 브라우저의 프록시 계층이고, PWA는 이를 매니페스트와 함께 활용해 설치 가능하고 오프라인에 강한 웹 앱을 만드는 접근입니다. 강력한 만큼 캐시 무효화와 보안 설계가 중요합니다.
Service Worker 동작 흐름
Service Worker는 브라우저와 네트워크 사이에 놓이는 프록시 같은 스크립트입니다. 페이지와 별도 생명주기를 가지며, 설치 후 fetch 요청을 가로채 캐시 응답, 오프라인 페이지, 백그라운드 동기화 등을 구현할 수 있습니다.
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, 사용자 새로고침 안내를 함께 설계합니다.
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then(keys => Promise.all(keys.filter(k => k !== 'static-v2').map(k => caches.delete(k))))
);
});