서비스 워커는 웹 애플리케이션에 캐싱 및 다양한 기능들을 제공하기 위해 백그라운드에서 작동하는 스크립트입니다.
이러한 기능들은 웹 브라우저에서 애플리케이션이 원활하고 사용자 친화적으로 동작하도록 돕습니다.
서비스 워커는 PWA(Progressive Web Apps)를 구축하는 데 필수적인 요소입니다.
서비스 워커 이해
서비스 워커는 메인 JavaScript 스레드와 독립적으로 백그라운드에서 실행되는 JavaScript 웹 워커의 한 종류입니다. 이는 애플리케이션의 사용자 인터페이스나 사용자 상호 작용이 지연되거나 중단되지 않음을 의미합니다.
서비스 워커는 웹 애플리케이션과 네트워크 사이에서 프록시 서버처럼 작동합니다. 요청과 응답을 가로채 리소스를 캐시하고 오프라인 상태에서도 작동할 수 있도록 지원합니다. 이러한 기능은 사용자가 인터넷에 연결되지 않은 상황에서도 웹 앱의 사용성을 높여줍니다.
서비스 워커의 주요 활용
서비스 워커는 여러 분야에서 활용될 수 있습니다. 주요 사용 사례는 다음과 같습니다.
- PWA: 서비스 워커는 Progressive Web App에 다양한 기능을 제공합니다. 사용자 정의 네트워크 요청, 푸시 알림, 오프라인 지원, 빠른 로딩 등을 가능하게 합니다.
- 캐싱: 서비스 워커는 애플리케이션의 자원(이미지, JavaScript 코드, CSS 파일 등)을 브라우저의 캐시 저장소에 저장할 수 있습니다. 이렇게 하면 브라우저가 원격 서버에서 직접 가져오는 대신 캐시에서 자원을 가져와 더 빠른 콘텐츠 로딩이 가능합니다. 특히 네트워크 연결이 불안정하거나 느린 환경에서 유용합니다.
- 백그라운드 동기화: 서비스 워커는 사용자가 앱을 사용하지 않거나 브라우저에서 앱이 열려있지 않아도 데이터를 동기화하고 백그라운드 작업을 수행할 수 있습니다.
Next.js 애플리케이션에 서비스 워커 통합
코드 구현에 앞서 서비스 워커의 작동 방식을 이해하는 것이 중요합니다. 서비스 워커는 등록과 활성화라는 두 가지 주요 단계를 거칩니다.
등록 단계에서 브라우저는 서비스 워커를 등록합니다. 다음은 간단한 예시 코드입니다.
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
registration = await navigator.serviceWorker.register("/sw.js");
}
};registerServiceWorker();
위 코드는 먼저 현재 브라우저가 서비스 워커를 지원하는지 확인합니다. 서비스 워커를 지원한다면 지정된 파일 경로에 위치한 서비스 워커를 등록합니다.
활성화 단계에서는 JavaScript 이벤트 리스너를 사용하여 서비스 워커를 설치하고 활성화합니다. 서비스 워커는 ‘install’ 및 ‘activate’ 이벤트를 수신합니다. 아래 코드를 참고하세요.
registration.addEventListener("install", () => {
console.log("Service worker installed");
});registration.addEventListener("activate", () => {
console.log("Service worker activated");
});
이 코드는 서비스 워커 등록 프로세스 직후에 실행되어야 합니다. 서비스 워커 등록이 완료되면 ‘install’ 및 ‘activate’ 이벤트가 발생합니다.
이 프로젝트의 전체 코드는 GitHub 저장소에서 확인할 수 있습니다.
Next.js 프로젝트 생성
먼저 다음 명령어를 사용하여 로컬 환경에 Next.js 프로젝트를 생성합니다.
npx create-next-app next-project
Next.js 애플리케이션에 서비스 워커를 추가하는 단계는 다음과 같습니다.
서비스 워커 추가
먼저 서비스 워커를 등록해야 합니다. `src/pages/_app.js` 파일을 아래와 같이 수정합니다. 이렇게 하면 애플리케이션이 로드될 때 서비스 워커가 등록되고 애플리케이션의 모든 자원에 접근할 수 있게 됩니다.
import { useEffect } from 'react';export default function App({ Component, pageProps }) {
useEffect(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('/service-worker.js', { scope: "https://www.makeuseof.com/" })
.then((registration) => {
console.log(
'Service worker registered successfully. Scope:',
registration.scope
);
})
.catch((error) => {
console.error('Service worker registration failed:', error);
});
}
}, []);return <Component {...pageProps} />;
}
`useEffect` 훅은 컴포넌트가 마운트될 때 실행됩니다. 코드에서는 먼저 브라우저가 서비스 워커를 지원하는지 확인합니다.
만약 서비스 워커를 지원하는 브라우저라면 지정된 경로의 서비스 워커 스크립트를 등록하고 범위를 “/”로 지정합니다. 이는 서비스 워커가 애플리케이션의 모든 리소스를 제어할 수 있다는 것을 의미합니다. 필요한 경우 범위를 “/products”와 같이 세분화할 수도 있습니다.
등록이 성공하면 콘솔에 성공 메시지와 함께 서비스 워커의 범위가 출력됩니다. 등록 과정에서 오류가 발생하면 오류를 캐치하여 콘솔에 오류 메시지를 출력합니다.
서비스 워커 설치 및 활성화
`public/service-worker.js` 파일을 생성하고 다음 코드를 추가합니다.
const installEvent = () => {
self.addEventListener('install', () => {
console.log('service worker installed!!!!');
});
};installEvent();
const activateEvent = () => {
self.addEventListener('activate', () => {
console.log('service worker activated!!!');
});
};activateEvent();
서비스 워커가 성공적으로 등록, 설치 및 활성화되었는지 확인하기 위해 개발 서버를 실행하고 브라우저에서 애플리케이션을 열어봅니다.
npm run dev
Chrome 개발자 도구 (또는 해당 브라우저의 개발자 도구)를 열고 ‘애플리케이션’ 탭으로 이동합니다. ‘서비스 워커’ 섹션에서 등록된 서비스 워커를 확인할 수 있습니다.
서비스 워커가 정상적으로 등록, 설치 및 활성화되었다면 캐싱, 백그라운드 동기화, 푸시 알림 전송과 같은 다양한 기능을 구현할 수 있습니다.
서비스 워커를 이용한 리소스 캐싱
사용자의 장치에 애플리케이션 자산을 캐싱하면 특히 인터넷 연결이 불안정한 환경에서 더 빠른 접근이 가능하여 성능을 향상시킬 수 있습니다.
애플리케이션 자원을 캐시하려면 `service-worker.js` 파일에 다음 코드를 추가합니다.
const cacheName="test-cache";self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
return cachedResponse || fetch(event.request).then((response) => {
return caches.open(cacheName).then((cache) => {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
사용자가 처음으로 홈페이지에 접근하면 위 코드는 캐시에 해당 요청에 대한 캐시된 응답이 있는지 확인합니다. 만약 캐시된 응답이 있다면 서비스 워커는 해당 응답을 클라이언트에 반환합니다.
캐시된 응답이 없는 경우 서비스 워커는 네트워크를 통해 서버에서 리소스를 가져옵니다. 이 과정에서 클라이언트에 응답을 전달하고 추후 요청에 대비하여 캐시에 저장합니다.
캐시된 자원을 확인하려면 개발자 도구에서 ‘애플리케이션’ 탭을 열어봅니다. ‘캐시 저장소’ 섹션에서 캐시된 자원 목록을 확인할 수 있습니다. 또한 ‘서비스 워커’ 섹션에서 ‘오프라인’ 옵션을 선택하고 페이지를 새로 고침하여 오프라인 환경을 시뮬레이션할 수도 있습니다.
이제 홈페이지에 방문하면 브라우저는 데이터를 가져오기 위해 네트워크 요청을 시도하는 대신 캐시 저장소에 저장된 리소스를 제공합니다.
서비스 워커를 활용한 성능 향상
서비스 워커는 Next.js 애플리케이션의 성능을 향상시키는 데 유용한 도구입니다. 리소스 캐싱, 요청 가로채기, 오프라인 지원 등을 통해 사용자 경험을 개선할 수 있습니다.
하지만 서비스 워커는 구현 및 관리가 복잡할 수 있다는 점을 고려해야 합니다. 서비스 워커를 사용하기 전에 잠재적인 이점과 단점을 신중하게 평가하는 것이 중요합니다.