2026-02-01
서비스 워커(Service Worker)란?
웹 페이지와 별도로 브라우저 백그라운드에서 실행되는 JavaScript 스크립트로, 네트워크 요청을 가로채어 오프라인 경험과 백그라운드 동기화를 가능하게 하는 기술
기본 개념
- 웹 애플리케이션, 브라우저, 네트워크 사이에 위치한 프록시 서버 역할을 하는 스크립트
- DOM에 직접 접근할 수 없으며, 독립적인 워커 컨텍스트에서 실행
등장 배경
- 문제점: 기존 웹은 네트워크 연결이 끊기면 사용 불가능
- AppCache의 한계: 이전 오프라인 솔루션인 AppCache는 유연성 부족, 예측 불가능한 동작
- 네이티브 앱과의 격차: 푸시 알림, 백그라운드 동기화 등 네이티브 앱 기능 부재
- 해결: 개발자가 네트워크 요청을 완전히 제어할 수 있는 프로그래밍 가능한 프록시 제공
동작 원리
1단계: 등록
- 메인 스크립트에서
navigator.serviceWorker.register()호출 - 브라우저가 서비스 워커 파일 다운로드 시작
2단계: 설치
- 처음 등록되거나 새 버전이 발견될 때 발생
install이벤트에서 정적 자산 캐싱
3단계: 활성화
- 이전 버전 정리 작업 수행
- 오래된 캐시 삭제
4단계: 제어
- 페이지의 네트워크 요청 가로채기
- 캐시 우선, 네트워크 우선 등 전략 구현
관련 개념과 비교
Web Worker
- Web Worker: 복잡한 연산 처리용, 페이지와 생명주기 동일
- Service Worker: 네트워크 프록시, 페이지 종료 후에도 생존 가능
AppCache
- AppCache: 선언적, 제한적, deprecated
- Service Worker: 프로그래밍 방식, 완전한 제어 가능
코드 예시
서비스 워커 등록
// HTTPS 환경에서만 동작 (localhost 제외)if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker .register('/service-worker.js') .then((registration) => { console.log('SW 등록 성공:', registration.scope) }) .catch((error) => { console.log('SW 등록 실패:', error) }) })}서비스 워커 파일
const CACHE_NAME = 'my-app-v1'const urlsToCache = ['/', '/styles/main.css', '/scripts/app.js', '/images/logo.png']
// 설치 단계: 정적 자산 캐싱self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { console.log('캐시 열림') return cache.addAll(urlsToCache) }), ) // 즉시 활성화 (개발 시) self.skipWaiting()})
// 활성화 단계: 오래된 캐시 삭제self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { if (cacheName !== CACHE_NAME) { console.log('오래된 캐시 삭제:', cacheName) return caches.delete(cacheName) } }), ) }), ) // 모든 클라이언트 즉시 제어 self.clients.claim()})
// Fetch 단계: Cache First 전략self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((response) => { // 캐시에 있으면 반환, 없으면 네트워크 요청 return response || fetch(event.request) }), )})Network First 전략
// API 요청에 적합한 Network First 전략self.addEventListener('fetch', (event) => { if (event.request.url.includes('/api/')) { event.respondWith( fetch(event.request) .then((response) => { // 성공 시 캐시에 저장 const responseClone = response.clone() caches.open(CACHE_NAME).then((cache) => { cache.put(event.request, responseClone) }) return response }) .catch(() => { // 네트워크 실패 시 캐시 반환 (오프라인 대비) return caches.match(event.request) }), ) }})헷갈리기 쉬운 부분
Service Worker ≠ Web Worker
- Service Worker: 네트워크 프록시, 페이지와 독립적 생명주기
- Web Worker: 계산 작업용, 페이지 종료 시 함께 종료
개념 정리
서비스 워커는 웹 애플리케이션과 네트워크 사이에서 프록시 역할을 하는 백그라운드 스크립트입니다.
주요 특징으로 페이지와 별도로 백그라운드에서 실행되며 DOM에 직접 접근할 수 없습니다. 그리고 네트워크 요청을 가로채서 캐싱 전략을 구현할 수 있어 오프라인 경험을 제공할 수 있습니다.
생명주기는 등록, 설치, 활성화, 제어의 4단계로 진행됩니다. 등록 시 브라우저가 서비스 워커 파일을 다운로드하고, 설치 단계에서 정적 자산을 캐싱합니다. 활성화 단계에서는 이전 버전의 캐시를 정리하고 이후 fetch 이벤트를 통해 네트워크 요청을 제어합니다.
PWA를 구현할 때 핵심 기술로 사용됩니다. 특히 Cache First 전략으로 정적 자산을 빠르게 제공하고 Network First 전략으로 API 응답의 최신성을 보장하면서도 오프라인 대비책을 마련할 수 있습니다.
보안상 HTTPS 환경에서만 동작하며 개발 시에는 localhost가 예외로 허용됩니다.
핵심 문장
- 서비스 워커는 웹과 네트워크 사이의 프록시로 동작하는 백그라운드 스크립트
- 네트워크 요청을 가로채서 캐싱을 제어 가능
- 오프라인 경험과 빠른 로딩 속도를 제공
- PWA의 핵심 기술
- 등록-설치-활성화-제어의 생명주기
- HTTPS에서만 동작