최신 웹 애플리케이션 내에서 백그라운드 스크립트로 작동하는 서비스 워커는 강력한 캐싱 기능과 지속적인 실행을 통해 다양한 추가 이점을 제공합니다.

이러한 속성의 통합은 웹 브라우저의 범위 내에서 네이티브 애플리케이션의 특징인 원활하고 직관적인 인터페이스를 용이하게 합니다.

서비스 워커의 활용은 프로그레시브 웹 애플리케이션(PWA) 개발에서 중요한 측면입니다.

서비스 워커의 이해

서비스 워커는 기본 자바스크립트 스레드와 독립적으로 실행되도록 설계된 특수 자바스크립트 실행 컨텍스트로, 사용자 인터페이스를 방해하거나 애플리케이션과의 상호작용을 방해하지 않으면서 비동기적이고 눈에 거슬리지 않는 작업을 수행할 수 있도록 해줍니다.

서비스 워커는 웹 애플리케이션과 네트워크 사이의 중개자 역할을 수행하여 요청과 응답을 가로채는 동시에 리소스를 캐싱하고 오프라인 지원을 제공할 수 있습니다. 이를 통해 웹 애플리케이션의 온라인 사용과 오프라인 사용 간의 원활한 전환을 보장하여 전반적인 사용자 경험을 향상시키는 데 기여합니다.

서비스 워커를 위한 주요 애플리케이션

서비스 워커는 다양한 애플리케이션을 포괄하는 여러 기능을 가지고 있습니다. 여기에는 다음이 포함될 수 있습니다:

프로그레시브 웹 애플리케이션(PWA)은 서비스 워커가 사용자 지정 네트워크 요청, 푸시 알림 전달, 오프라인 기능 제공, 인터넷에 연결되지 않은 상태에서도 빠른 렌더링 등 다양한 작업을 처리할 수 있는 기능을 제공합니다.

캐싱은 이미지, 자바스크립트 코드, CSS 파일과 같은 애플리케이션의 자산을 브라우저의 캐시 메모리에 저장하는 것을 포함합니다. 이렇게 하면 네트워크를 통해 원격 서버에서 이러한 콘텐츠를 검색하는 대신 브라우저가 캐시된 버전을 사용하므로 인터넷 연결 속도가 느리거나 안정적이지 않은 사용자에게 특히 유용한 로딩 시간을 단축할 수 있습니다.

서비스 작업자는 적극적인 사용자 상호 작용이나 브라우저 창을 열지 않고도 데이터의 백그라운드 동기화를 수행하고 추가 작업을 실행할 수 있습니다. 이 기능을 사용하면 애플리케이션이 백그라운드에서 계속 작동하고 기능을 향상시킬 수 있습니다.

Next.js 애플리케이션에 서비스 워커 통합

등록 및 활성화.

초기 단계에서 브라우저는 등록을 통해 서비스 워커와 관계를 설정합니다. 기본적인 그림은 다음과 같습니다:

 const registerServiceWorker = async () => {
  if ("serviceWorker" in navigator) {
    registration = await navigator.serviceWorker.register("/sw.js");
  }
};

registerServiceWorker();

최신 웹 브라우저에서 보편적으로 사용되는 서비스 워커와의 호환성을 감지하면 코드는 지정된 파일 경로 내에 있는 서비스 워커를 등록하기 위해 진행합니다.

이 글도 확인해 보세요:  웹 개발을 위한 가장 인기 있는 8가지 백엔드 프레임워크

시작 단계에서는 ‘설치’ 및 ‘활성화’ 발생을 감지하고 이에 대응하기 위해 자바스크립트 이벤트 핸들러를 활용하여 서비스 워커를 고용하고 활성화해야 합니다. 이 프로세스를 효과적으로 실행하려면 다음 단계를 따르세요:

 registration.addEventListener("install", () => {
    console.log("Service worker installed");
});

registration.addEventListener("activate", () => {
    console.log("Service worker activated");
});

서비스 작업자 등록 프로세스가 성공적으로 완료되면 그 이후에 바로 앞서 언급한 코드를 통합할 수 있습니다.

이 프로젝트의 소스 코드는 전용 GitHub 리포지토리에서 확인할 수 있습니다.

Next.js 프로젝트 만들기

프로세스를 시작하려면 로컬 환경에서 다음 명령을 실행하여 “스캐폴드” 기능을 사용하여 Next.js 프로젝트를 생성하세요:

 npx create-next-app next-project 

서비스 워커를 Next.js 애플리케이션에 통합하려면 다음을 포함한 여러 절차 단계를 실행해야 합니다:

글로벌 범위에 서비스 워커를 등록하면 출처나 컨텍스트에 관계없이 웹사이트에 액세스하는 모든 클라이언트에 대한 요청과 응답을 효율적으로 처리할 수 있습니다. 이를 통해 리소스 및 네트워크 요청을 중앙 집중식으로 관리할 수 있으므로 성능이 향상되고 서버 리소스에 대한 부하가 줄어듭니다.

JavaScript와 같은 스크립팅 언어를 사용하여 프로젝트의 “공개” 디렉터리 내에 서비스 워커 파일을 개발하세요.

서비스 워커 추가하기

시작하려면 서비스 워커를 등록해야 합니다. 이에 따라 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: '/' })
        .then((registration) => {
          console.log(
            'Service worker registered successfully. Scope:',
            registration.scope
          );
        })
        .catch((error) => {
          console.error('Service worker registration failed:', error);
        });
    }
  }, []);

  return <Component {...pageProps} />;
}

컴포넌트 렌더링 시 `useEffect` 훅의 활용이 시작됩니다. 앞서 언급한 인스턴스와 유사하게, 구현은 처음에 사용자의 브라우저가 서비스 워커의 기능을 지원하는지 여부를 확인합니다.

이 글도 확인해 보세요:  React Native에서 Flexbox를 사용하는 방법

서비스 워커 스크립트의 등록은 해당 위치를 제공하고 애플리케이션 내의 모든 리소스를 포괄하는 관련 범위를 지정함으로써 용이하게 이루어집니다. 그러나 원하는 경우 서비스 작업자가 행사하는 제어 범위를 제한하기 위해 ““/제품”과 같은 개별 섹션 또는 카테고리와 같이 보다 구체적인 범위를 제공할 수 있습니다.

등록 프로세스가 성공적으로 완료되면 시스템은 지정된 범위와 함께 확인 메시지를 기록합니다. 등록 절차 중에 오류가 발생하면 프로그램은 오류를 캡처하고 검토를 위해 적절한 오류 메시지를 기록합니다.

서비스 워커 설치 및 활성화

“public/service-worker.js”라는 새 파일에 다음 코드 스니펫을 추가하세요: ”’자바스크립트 importScripts(‘https://www.example.com/sw.js’); 내보내기 함수 register() { self.addEventListener(‘fetch’, event => { const url = new URL(event.request); if (url.pathname === ‘/static/path/to/your/page’) { event.respondWith(fetch(url)); } else { // 다른 경우는 여기서 처리… } }); }

 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 

Google 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;
        });
      });
    })
  );
});

사용자가 홈페이지에 처음 접속하면 이 스크립트는 요청된 데이터에 해당하는 저장된 응답이 캐시 내에 존재하는지 여부를 확인합니다. 보존된 응답이 발견되면 시스템은 해당 응답을 검색하여 클라이언트에 다시 전달합니다.

이 글도 확인해 보세요:  Reqwest로 Rust에서 HTTP 요청 만들기

캐시된 응답이 없는 경우 서비스 작업자는 인터넷 연결을 통해 원격 서버에서 요청된 데이터를 검색합니다. 그런 다음 작업자는 이 데이터를 사용자 에이전트에게 전달하고 향후 잠재적 사용을 위해 캐시에 저장합니다.

캐시된 리소스에 액세스하려면 개발자 도구 내의 애플리케이션 탭으로 이동하세요. 이 탭에서 캐시 스토리지 영역을 찾으면 저장된 에셋 카탈로그를 찾을 수 있습니다. 또한 웹페이지 재로드 시 온라인/오프라인 막간을 시뮬레이션할 수 있는 서비스 워커 섹션을 살펴봄으로써 오프라인 기능을 확인할 수 있습니다.

웹사이트 홈페이지에 액세스하면 브라우저는 데이터 검색을 위한 추가 네트워크 요청을 시작하는 대신 캐시된 리소스 저장소를 사용합니다.

서비스 워커를 사용하여 성능 향상

서비스 워커를 활용하는 것은 캐싱 기능, 요청 차단, 오프라인 운영 지원을 제공하여 Next.js 애플리케이션의 기능을 강화하는 효과적인 수단으로, 사용자 만족도 향상에 기여합니다.

실제로 서비스 워커는 웹사이트의 성능 향상과 사용자 경험 개선 측면에서 많은 이점을 제공하지만, 구현 및 관리에는 때때로 특정 문제가 발생할 수 있습니다. 따라서 서비스 워커를 웹사이트 디자인에 통합하기 전에 장단점을 면밀히 검토하는 것이 중요합니다.

By 최은지

윈도우(Windows)와 웹 서비스에 대한 전문 지식을 갖춘 노련한 UX 디자이너인 최은지님은 효율적이고 매력적인 디지털 경험을 개발하는 데 탁월한 능력을 발휘합니다. 사용자의 입장에서 생각하며 누구나 쉽게 접근하고 즐길 수 있는 콘텐츠를 개발하는 데 주력하고 있습니다. 사용자 경험을 향상시키기 위해 연구를 거듭하는 은지님은 All Things N 팀의 핵심 구성원으로 활약하고 있습니다.