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

Kate Jeffreys
Kate Jeffreys

이 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에서 Tools를 클릭한 다음 Terminal을 클릭하여 Glitch Terminal을 엽니다.
  2. Glitch Terminal에서 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. 글리치 터미널을 닫습니다.
  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. 사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면 전체 화면을 누릅니다.
  1. `Control+Shift+J` (또는 Mac의 경우 `Command+Option+J`)를 눌러 DevTools를 엽니다.
  2. 콘솔 탭을 클릭합니다. 콘솔에 로깅된 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가 로드됩니다.

다음 단계