Codelab: 푸시 알림 클라이언트 빌드

케이트 제프리스
케이트 제프리스
케이스 바스크
케이스 바스크

이 Codelab에서는 푸시 알림 클라이언트를 빌드하는 방법을 단계별로 보여줍니다. Codelab을 마치면 다음과 같은 클라이언트가 생성됩니다.

  • 사용자의 푸시 알림을 수신합니다.
  • 푸시 메시지를 수신하여 알림으로 표시합니다.
  • 사용자의 푸시 알림 수신 거부

이 Codelab에서는 실습을 통해 학습하는 데 중점을 두고 있으며 개념에 관해서는 다루지 않습니다. 푸시 알림 개념에 대해 알아보려면 푸시 알림의 작동 원리를 확인하세요.

이 Codelab의 서버 코드는 이미 완성되어 있습니다. 이 Codelab에서는 클라이언트만 구현합니다. 푸시 알림 서버를 구현하는 방법은 Codelab: 푸시 알림 서버 빌드를 참고하세요.

전체 코드는 push-notifications-client-codelab-complete(소스)를 참고하세요.

브라우저 호환성

이 Codelab은 다음과 같은 운영체제 및 브라우저 조합에서 작동하는 것으로 알려져 있습니다.

  • Windows: Chrome, Edge
  • macOS: Chrome, Firefox
  • Android: Chrome, Firefox

이 Codelab은 다음 운영체제(또는 운영체제와 브라우저 조합)에서는 작동하지 않는 것으로 알려져 있습니다.

  • macOS: Brave, Edge, Safari
  • iOS

설정

수정 가능한 코드 사본 받기

이 안내의 오른쪽에 표시되는 코드 편집기는 이 Codelab 전체에서 Glitch UI라고 합니다.

  1. 리믹스하여 수정을 클릭하여 프로젝트를 수정할 수 있도록 합니다.

인증 설정

푸시 알림이 작동하도록 하려면 먼저 인증 키로 서버와 클라이언트를 설정해야 합니다. 이유는 웹 푸시 프로토콜 요청 서명을 참조하세요.

  1. Glitch UI에서 도구를 클릭한 다음 터미널을 클릭하여 Glitch 터미널을 엽니다.
  2. Glitch 터미널에서 npx web-push generate-vapid-keys를 실행합니다. 비공개 키와 공개 키 값을 복사합니다.
  3. Glitch UI에서 .env를 열고 VAPID_PUBLIC_KEYVAPID_PRIVATE_KEY를 업데이트합니다. VAPID_SUBJECTmailto:test@test.test로 설정합니다. 이러한 값은 모두 큰따옴표로 묶어야 합니다. 업데이트 후에는 .env 파일이 다음과 같이 표시됩니다.
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
  1. Glitch 터미널을 닫습니다.
  1. public/index.js를 엽니다.
  2. VAPID_PUBLIC_KEY_VALUE_HERE를 공개 키 값으로 바꿉니다.

서비스 워커 등록

클라이언트는 최종적으로 알림을 수신하고 표시하려면 서비스 워커가 필요합니다. 서비스 워커는 가능한 한 빨리 등록하는 것이 가장 좋습니다. 자세한 내용은 푸시된 메시지를 알림으로 수신하여 표시를 참조하세요.

  1. // TODO add startup logic here 주석을 다음 코드로 바꿉니다.
// TODO add startup logic here
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.register('./service-worker.js').then(serviceWorkerRegistration => {
    console.info('Service worker was registered.');
    console.info({serviceWorkerRegistration});
  }).catch(error => {
    console.error('An error occurred while registering the service worker.');
    console.error(error);
  });
  subscribeButton.disabled = false;
} else {
  console.error('Browser does not support service workers or push messages.');
}

subscribeButton.addEventListener('click', subscribeButtonHandler);
unsubscribeButton.addEventListener('click', unsubscribeButtonHandler);
  1. 사이트를 미리 보려면 View App을 누른 다음 Fullscreen 전체 화면을 누릅니다.
  1. `Control+Shift+J` (Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  2. 콘솔 탭을 클릭합니다. Console에 로깅된 Service worker was registered. 메시지가 표시됩니다.

푸시 알림 권한 요청

페이지 로드 시 푸시 알림을 보낼 수 있는 권한을 요청해서는 안 됩니다. 대신 UI는 사용자에게 푸시 알림을 받고 싶은지 물어봐야 합니다. 사용자가 버튼을 클릭하여 명시적으로 확인하면 (예: 버튼 클릭) 브라우저에서 푸시 알림 권한을 얻기 위한 공식 프로세스를 시작할 수 있습니다.

  1. Glitch UI에서 View Source를 클릭하여 코드로 돌아갑니다.
  2. public/index.js에서 subscribeButtonHandler()// TODO 주석을 다음 코드로 바꿉니다.
// TODO
// Prevent the user from clicking the subscribe button multiple times.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
  1. 앱 탭으로 돌아가서 푸시하려면 구독을 클릭합니다. 브라우저나 운영체제에서 웹사이트에서 푸시 알림을 보낼 수 있는지 묻는 메시지가 표시될 수 있습니다. 허용 (또는 브라우저/OS에서 사용하는 동등한 문구)을 클릭합니다. 콘솔에 요청이 수락되었는지 또는 거부되었는지 여부를 나타내는 메시지가 표시됩니다.

푸시 알림 구독

구독 프로세스에는 브라우저 공급업체가 제어하는 푸시 서비스라고 하는 웹 서비스와의 상호작용이 포함됩니다. 푸시 알림 구독 정보를 받으면 서버로 전송하여 서버에서 장기적으로 데이터베이스에 저장해야 합니다. 구독 프로세스에 관한 자세한 내용은 클라이언트의 푸시 알림 구독을 참고하세요.

  1. 다음 강조표시된 코드를 subscribeButtonHandler()에 추가합니다.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
  console.error('The user explicitly denied the permission request.');
  return;
}
if (result === 'granted') {
  console.info('The user accepted the permission request.');
}
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
  console.info('User is already subscribed.');
  notifyMeButton.disabled = false;
  unsubscribeButton.disabled = false;
  return;
}
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY)
});
notifyMeButton.disabled = false;
fetch('/add-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(subscription)
});

userVisibleOnly 옵션은 true여야 합니다. 사용자에게 표시되는 알림을 표시하지 않고(자동 푸시) 메시지를 푸시하는 것도 언젠가 가능할 수 있지만, 현재 브라우저에서는 개인 정보 보호 문제로 인해 이 기능을 허용하지 않습니다.

applicationServerKey 값은 base64 문자열을 Uint8Array로 변환하는 유틸리티 함수를 사용합니다. 이 값은 서버와 푸시 서비스 간 인증에 사용됩니다.

푸시 알림 수신 거부

사용자가 푸시 알림을 구독하고 나면, 마음이 바뀌어 더 이상 푸시 알림을 받고 싶지 않을 때를 대비해 UI에서 구독을 취소하는 방법을 제공해야 합니다.

  1. unsubscribeButtonHandler()// TODO 주석을 다음 코드로 바꿉니다.
// TODO
const registration = await navigator.serviceWorker.getRegistration();
const subscription = await registration.pushManager.getSubscription();
fetch('/remove-subscription', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({endpoint: subscription.endpoint})
});
const unsubscribed = await subscription.unsubscribe();
if (unsubscribed) {
  console.info('Successfully unsubscribed from push notifications.');
  unsubscribeButton.disabled = true;
  subscribeButton.disabled = false;
  notifyMeButton.disabled = true;
}

푸시 메시지를 수신하여 알림으로 표시

앞서 언급했듯이 서버에서 클라이언트로 푸시된 메시지를 수신하고 표시하는 작업을 처리하는 서비스 워커가 필요합니다. 자세한 내용은 푸시된 메시지를 알림으로 수신하여 표시를 참조하세요.

  1. public/service-worker.js를 열고 서비스 워커의 push 이벤트 핸들러에 있는 // TODO 주석을 다음 코드로 바꿉니다.
// TODO
let data = event.data.json();
const image = 'https://cdn.glitch.com/614286c9-b4fc-4303-a6a9-a4cef0601b74%2Flogo.png?v=1605150951230';
const options = {
  body: data.options.body,
  icon: image
}
self.registration.showNotification(
  data.title, 
  options
);
  1. 앱 탭으로 돌아갑니다.
  2. 알림 받기를 클릭합니다. 푸시 알림을 받게 됩니다.
  3. 다른 브라우저 (또는 다른 기기)에서 앱 탭의 URL을 열고 정기 결제 워크플로를 진행한 다음 모두 알림을 클릭합니다. 구독한 모든 브라우저에서 동일한 푸시 알림을 받게 됩니다. 작동하거나 작동하지 않는 것으로 알려진 브라우저/OS 조합 목록을 보려면 브라우저 호환성을 참고하세요.

다양한 방법으로 알림을 맞춤설정할 수 있습니다. 자세한 내용은 ServiceWorkerRegistration.showNotification()의 매개변수를 참고하세요.

사용자가 알림을 클릭하면 URL 열기

실생활에서는 사용자의 재참여를 유도하고 사이트를 방문하도록 유도하는 방법으로 알림을 사용할 수 있습니다. 그러려면 서비스 워커를 조금 더 구성해야 합니다.

  1. 서비스 워커의 notificationclick 이벤트 핸들러에 있는 // TODO 주석을 다음 코드로 바꿉니다.
// TODO
event.notification.close();
event.waitUntil(self.clients.openWindow('https://web.dev'));
  1. 앱 탭으로 돌아가서 자신에게 또 다른 알림을 보낸 다음 알림을 클릭합니다. 브라우저에 새 탭이 열리고 https://web.dev가 로드됩니다.

다음 단계