[단어 정의]
Non-persistent notification : a notification without an associated service worker registration.
Persistent notification : a notification with an associated service worker registration.
구현 코드
의사 코드 발췌
To create a notification, given a string title, NotificationOptions dictionary options, environment settings object settings, and optionally a ServiceWorkerRegistration object serviceWorkerRegistration, run these steps:
- Let notification be a new notification.
- If a serviceWorkerRegistration was provided, then set notification’s service worker registration to serviceWorkerRegistration.
- 타입 에러가 나는 경우
- If a serviceWorkerRegistration was not provided and options["actions"] is not empty, then throw a TypeError.
-> Actions are only currently supported for persistent notifications. - If options["silent"] is true and options["vibrate"] exists, then throw a TypeError.
- If options["renotify"] is true and options["tag"] is the empty string, then throw a TypeError.
- If a serviceWorkerRegistration was not provided and options["actions"] is not empty, then throw a TypeError.
- 알림 세팅
- Set notification’s data to StructuredSerializeForStorage(options["data"]).
- Set notification’s title to title.
- Set notification’s direction to options["dir"].
- Set notification’s language to options["lang"].
- Set notification’s origin to settings’s origin.
- Set notification’s body to options["body"].
- Set notification’s tag to options["tag"].
- Let baseURL be settings’s API base URL.
- If options["image"] exists, then parse it using baseURL, and if that does not return failure, set notification’s image URL to the return value. (Otherwise image URL is not set.)
- If options["icon"] exists, then parse it using baseURL, and if that does not return failure, set notification’s icon URL to the return value. (Otherwise icon URL is not set.)
- If options["badge"] exists, then parse it using baseURL, and if that does not return failure, set notification’s badge URL to the return value. (Otherwise badge URL is not set.)
- If options["vibrate"] exists, then validate and normalize it and set notification’s vibration pattern to the return value.
- If options["timestamp"] exists, then set notification’s timestamp to the value. Otherwise, set notification’s timestamp to the number of milliseconds from the Unix epoch to settings’s current wall time, rounded to the nearest integer.
- Set notification’s renotify preference to options["renotify"].
- Set notification’s silent preference to options["silent"].
- Set notification’s require interaction preference to options["requireInteraction"].
- Set notification’s list of actions to an empty list, then for each entry in options["actions"], up to the maximum number of actions supported (skip any excess entries):
- Let action be a new action.
- Set action’s name to entry["action"].
- Set action’s title to entry["title"].
- If entry["icon"] exists, then parse it using baseURL, and if that does not return failure, set action’s icon URL to the return value. (Otherwise icon URL is not set.)
- Append action to notification’s list of actions.
- Return notification.
구현 코드
- 'firebase.js' 파일 내에 FCM에서 제공해주는 onMessage 메서드를 이용해 구현하였다.
- 주의해야할 점은 notification API가 안드로이드 모바일(삼성 인터넷 등)에서는 TypeError를 출력하며 동작하지 않는다는 것이다.
- 따라서 안드로이드 모바일일 때의 로직은 서비스 워커를 이용하여 구현했다.
/**
* onMessageListener - 앱 사용 중 메시지 수신 (포그라운드)
*/
export const onMessageListener = () => {
if (process.client) {
// firebase FCM 기능 사용
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
// foreground 메시지 수신 로직
onMessage(messaging, (payload) => {
const notificationTitle = payload.data.title;
const notificationOptions = {
body: payload.data.body,
image: payload.data.image_url,
icon: "https://주소/icon.png",
};
// 웹일 때
if (!isMobile) {
const notif = new Notification(
notificationTitle,
notificationOptions,
);
notif.onclick = (event) => {
event.preventDefault();
const landing_url = payload.data.landing_url;
const newPath = landing_url ? landing_url : "/chat";
window.location.href = `${BASE_FRONT_URL}${newPath}`;
notif.close();
};
// 모바일 중에서도 안드로이드(모바일웹 또는 PWA)일 때
} else if (!isIOSApp()) {
// 서비스 워커 로직으로 구현
navigator.serviceWorker.ready.then(function (registration) {
registration.showNotification(
notificationTitle,
notificationOptions,
);
});
}
});
}
};
트러블 슈팅
구현 코드 카테고리에서 이미 언급했던 것처럼 notification API가 아래와 같이 안드로이드 모바일(삼성 인터넷 등)에서는 TypeError를 출력하며 동작하지 않았다.
Failed to construct 'Notification': Illegal constructor. Use ServiceWorkerRegistration.showNotification() instead.
관련 이슈 내용
결론적으로는 안드로이드 모바일에서 서비스 워커를 통한 알림 기능을 구현하여 해결하였다. 현재는 onClick 이벤트 일부 구현으로 웹 / 모바일 분기를 해놨지만 서비스 워커로 onClick까지 로직을 넣어둔다면 디바이스와 상관없이 서비스 워커로 통일하는 방법이 최선인 것으로 보인다.
레퍼런스
728x90
'📌 대외 활동 > 2311~ Look : AI 기록 서비스' 카테고리의 다른 글
[PWA] FCM으로 알람 기능 구현하기 (2) : 백그라운드 (0) | 2024.01.15 |
---|---|
[PWA] FCM으로 알림 기능 구현하기 (1) : Notification API (0) | 2024.01.14 |
[Nuxt3 / PWA] service worker로 앱 오프라인 캐싱하기 (0) | 2023.12.04 |
PWA(Progressive Web Application)란? (0) | 2023.11.24 |
react와 vue 비교 (0) | 2023.11.24 |