서비스 워커를 사용하여 알림 관리

Kate Jeffreys
Kate Jeffreys

이 Codelab에서는 서비스 워커를 사용하여 알림을 관리합니다. 이 안내는 서비스 워커와 알림 권한 요청 및 알림 전송의 기본사항에 이미 익숙하다고 가정합니다. 알림에 관해 다시 알아보려면 Notifications API 시작하기 Codelab을 참고하세요. 서비스 워커에 대해 자세히 알아보려면 맷 가운트의 서비스 워커 소개를 참고하세요.

삽입된 Glitch 앱에서는 알림이 자동으로 차단되므로 이 페이지에서 앱을 미리 볼 수 없습니다. 대신 다음 단계를 따르세요.

  1. 리믹스하여 수정을 클릭하여 프로젝트를 수정할 수 있도록 합니다.
  2. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.

Glitch가 새 Chrome 탭에서 열립니다.

이 Codelab을 진행하면서 이 페이지에 삽입된 Glitch의 코드를 변경합니다. 실시간 앱이 있는 새 탭을 새로고침하여 변경사항을 확인합니다.

샘플 앱 및 시작 코드 숙지

먼저 새 Chrome 탭에서 실시간 앱을 살펴보세요.

  1. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  2. 콘솔 탭을 클릭합니다.

  3. 필터 상자 옆의 수준 드롭다운에서 정보 옵션이 선택되어 있는지 확인합니다.

  4. 실시간 앱의 DevTools 콘솔에 다음과 같은 콘솔 메시지가 표시됩니다.

    TODO: Implement getRegistration().

    이 메시지는 이 Codelab에서 구현할 함수 스텁의 메시지입니다.

이제 이 페이지에 삽입된 Glitch에서 샘플 앱의 코드를 살펴보겠습니다.

  1. 삽입된 Glitch에서 public/index.js를 살펴봅니다.

    • 구현할 함수의 스텁은 registerServiceWorker, getRegistration, unRegisterServiceWorker, sendNotification의 4가지가 있습니다.

    • requestPermission 함수는 알림을 전송할 사용자의 권한을 요청합니다. Notifications API 시작하기 Codelab을 진행했다면 여기에서 requestPermission 함수가 사용되는 것을 확인할 수 있습니다. 유일한 차이점은 이제 권한 요청을 해결한 후 사용자 인터페이스도 업데이트된다는 점입니다.

    • updateUI 함수는 앱의 모든 버튼과 메시지를 새로고침합니다.

    • initializePage 함수는 브라우저에서 서비스 워커 기능에 대한 기능 감지를 실행하고 앱 사용자 인터페이스를 업데이트합니다.

    • 스크립트는 페이지가 로드될 때까지 기다린 후 초기화합니다.

  2. 삽입된 Glitch에서 public/service-worker.js를 엽니다.

    이름에서 알 수 있듯이 이 파일을 서비스 워커로 등록하는 코드를 앱에 추가합니다.

    이 파일은 아직 앱에서 사용하지 않지만 서비스 워커가 활성화될 때 콘솔에 메시지를 출력하는 시작 코드가 포함되어 있습니다.

    서비스 워커가 알림을 수신할 때 이를 처리하도록 public/service-worker.js에 코드를 추가합니다.

서비스 워커 등록

이 단계에서는 사용자가 앱 UI에서 Register service worker를 클릭할 때 실행되는 코드를 작성합니다. 이 코드는 public/service-worker.js를 서비스 워커로 등록합니다.

  1. 삽입된 Glitch 편집기에서 public/index.js를 엽니다. registerServiceWorker 함수를 다음 코드로 바꿉니다.

    // Use the Service Worker API to register a service worker.
    async function registerServiceWorker() {
      await navigator.serviceWorker.register('./service-worker.js')
      updateUI();
    }
    

    registerServiceWorker는 약속 처리를 더 편리하게 하기 위해 async function 선언을 사용합니다. 이렇게 하면 Promise의 확인된 값을 await할 수 있습니다. 예를 들어 위 함수는 UI를 업데이트하기 전에 서비스 워커 등록 결과를 기다립니다. 자세한 내용은 MDN의 await를 참고하세요.

  2. 이제 사용자가 서비스 워커를 등록할 수 있으므로 서비스 워커 등록 객체의 참조를 가져올 수 있습니다. public/index.js에서 getRegistration 함수를 다음 코드로 바꿉니다.

    // Get the current service worker registration.
    function getRegistration() {
      return navigator.serviceWorker.getRegistration();
    }
    

    위 함수는 Service Worker API를 사용하여 현재 서비스 워커 등록(있는 경우)을 가져옵니다. 이렇게 하면 서비스 워커 등록 참조를 더 편리하게 가져올 수 있습니다.

  • 서비스 워커 등록 기능을 완료하려면 서비스 워커를 등록 취소하는 코드를 추가합니다. unRegisterServiceWorker 함수를 다음 코드로 바꿉니다.

    // Unregister a service worker, then update the UI.
    async function unRegisterServiceWorker() {
      // Get a reference to the service worker registration.
      let registration = await getRegistration();
      // Await the outcome of the unregistration attempt
      // so that the UI update is not superceded by a
      // returning Promise.
      await registration.unregister();
      updateUI();
    }
    

실시간 앱을 보고 있는 탭에서 페이지를 새로고침합니다. 이제 서비스 워커 등록서비스 워커 등록 취소 버튼이 작동합니다.

서비스 워커에 알림 전송

이 단계에서는 사용자가 앱 UI에서 알림 보내기를 클릭할 때 실행되는 코드를 작성합니다. 이 코드는 알림을 만들고 서비스 워커가 등록되었는지 확인한 다음 postMessage 메서드를 사용하여 알림을 서비스 워커로 전송합니다.

삽입된 Glitch 편집기에서 public/index.js를 열고 sendNotification 함수를 다음 코드로 바꿉니다.

// Create and send a test notification to the service worker.
async function sendNotification() {
  // Use a random number as part of the notification data
  // (so you can tell the notifications apart during testing!)
  let randy = Math.floor(Math.random() * 100);
  let notification = {
    title: 'Test ' + randy,
    options: { body: 'Test body ' + randy }
  };
  // Get a reference to the service worker registration.
  let registration = await getRegistration();
  // Check that the service worker registration exists.
  if (registration) {
    // Check that a service worker controller exists before
    // trying to access the postMessage method.
    if (navigator.serviceWorker.controller) {
      navigator.serviceWorker.controller.postMessage(notification);
    } else {
      console.log('No service worker controller found. Try a soft reload.');
    }
  }
}

이 코드의 역할은 다음과 같습니다.

  • sendNotification는 비동기 함수이므로 await를 사용하여 서비스 워커 등록에 대한 참조를 가져올 수 있습니다.

  • 서비스 워커의 postMessage 메서드는 앱에서 서비스 워커로 데이터를 전송합니다. 자세한 내용은 postMessage에 관한 MDN 문서를 참고하세요.

  • 코드는 postMessage 함수에 액세스하기 전에 navigator.serviceWorker.controller 속성이 있는지 확인합니다. 활성 상태의 서비스 워커가 없거나 페이지가 강제로 새로고침된 경우 (Shift+새로고침) navigator.serviceWorker.controllernull입니다. 자세한 내용은 MDN의 ServiceWorker 컨트롤러 문서를 참고하세요.

서비스 워커에서 알림 처리

이 단계에서는 서비스 워커에 게시된 메시지를 처리하고 사용자에게 알림을 표시하는 코드를 작성합니다.

삽입된 Glitch 편집기에서 public/service-worker.js를 엽니다. 파일 끝에 아래 코드를 추가합니다.

// Show notification when received
self.addEventListener('message', (event) => {
  let notification = event.data;
  self.registration.showNotification(
    notification.title,
    notification.options
  ).catch((error) => {
    console.log(error);
  });
});

다음은 간단한 설명입니다.

  • self는 서비스 워커 자체를 참조합니다.

  • 이제 서비스 워커가 알림 표시를 처리하지만 기본 앱 UI는 여전히 사용자로부터 알림 권한을 가져와야 합니다. 권한이 부여되지 않으면 showNotification에서 반환된 프로미스가 거부됩니다. 위 코드는 catch 블록을 사용하여 포착되지 않은 Promise 거부 오류를 방지하고 이 오류를 좀 더 원활하게 처리합니다.

문제가 발생하면 glitch.com/edit/#!/codelab-notifications-service-worker-completed에서 완성된 코드를 확인하세요.

이 시리즈의 다음 Codelab인 푸시 알림 서버 빌드로 이동합니다.