Notikit 문서

문서 / SDK / Web

Web

이 문서는 notikit-js/packages/sdk-web 의 README 를 그대로 가져옵니다.

Notikit Web SDK — 브라우저 푸시 (FCM / Firebase Cloud Messaging).

토큰은 FCM 등록 토큰입니다. 서버는 안드로이드·iOS 와 같은 경로로 발송하므로 웹 전용 전송 분기가 필요 없습니다.

설치

npm install @mint-soft/notikit-web firebase

firebase 는 peer dependency 입니다(선택). getToken 을 직접 넘기면 설치하지 않아도 됩니다.

1) 서비스워커 배치

public/notikit-sw.js 로 SDK 의 NOTIKIT_SERVICE_WORKER 문자열을 그대로 저장하세요.

import { NOTIKIT_SERVICE_WORKER } from "@mint-soft/notikit-web";
// 빌드 스크립트에서: fs.writeFileSync("public/notikit-sw.js", NOTIKIT_SERVICE_WORKER)

워커는 설정을 자기 URL 쿼리에서만 읽습니다(워커에는 SDK 인스턴스가 없습니다). register() 가 쿼리를 자동으로 붙이므로 경로만 맞추면 됩니다.

2) 등록

firebase 설정은 항상 필요합니다. 워커에는 앱의 Firebase 인스턴스가 없어서, 이 값으로 직접 초기화해야 백그라운드 메시지를 받습니다.

import { NotikitWeb } from "@mint-soft/notikit-web";

const notikit = new NotikitWeb({
  baseUrl: "https://push.example.com",
  apiKey: "nk_xxx",
  vapidPublicKey: "B...",   // Firebase 콘솔 > 클라우드 메시징 > 웹 푸시 인증서
  userId: "user-123",       // 고객 서비스의 유저 id (서버에는 user_id 로 전송)
  firebase: {
    apiKey: "AIza...",
    projectId: "my-project",
    messagingSenderId: "1234567890",
    appId: "1:1234567890:web:abc",
  },
  // 워커가 불러올 compat SDK 버전. 설치한 firebase 와 메이저를 맞추세요.
  firebaseSdkVersion: "12.0.0",
});

if (NotikitWeb.isSupported()) {
  await notikit.register(); // 권한 요청 → FCM 토큰 → 서버 등록
}

userId 는 고객 서비스의 유저 id 이며 서버에 user_id 로 보냅니다. 이전 이름 externalId(external_id)도 그대로 동작하지만 deprecated 입니다 — 둘 다 주면 userId 가 이깁니다. identify(userId, attributes?, name?) 도 같습니다.

이미 Firebase 를 초기화한 앱이라면 토큰 획득만 넘겨받게 할 수 있습니다 — SDK 가 initializeApp 을 또 부르면 앱이 쓰던 인스턴스와 어긋납니다. (firebase 설정은 그래도 워커용으로 함께 넘겨야 합니다.)

import { getMessaging, getToken } from "firebase/messaging";

const notikit = new NotikitWeb({
  /* ...위와 동일... */
  getToken: (reg) =>
    getToken(getMessaging(myFirebaseApp), { vapidKey: "B...", serviceWorkerRegistration: reg }),
});

3) 토큰 교체

FCM 은 토큰을 갱신합니다. 새 토큰으로 register() 를 다시 부르면 행이 하나 더 생겨 같은 사람에게 중복 발송됩니다. 교체는 전용 메서드를 쓰세요 — 서버가 기존 행을 제자리 갱신해 토픽 구독·클릭 이력이 보존됩니다.

웹에는 토큰 갱신 이벤트가 없습니다. 네이티브의 onNewToken/didReceiveRegistrationToken 에 해당하는 것이 모듈 API(v10~v12)에 없으므로, 앱이 직접 비교해야 합니다. 앱을 열 때 한 번 확인하는 정도면 충분합니다 — FCM 토큰은 수명이 깁니다.

const saved = localStorage.getItem("fcm_token");
const current = await getToken(getMessaging(app), { vapidKey, serviceWorkerRegistration: reg });

if (saved && current && saved !== current) {
  await notikit.rotateToken(saved, current);
}
localStorage.setItem("fcm_token", current);

서버가 옛 토큰을 찾지 못하거나 증명이 맞지 않아 교체하지 못하면(rotated: false), SDK 가 새 토큰을 현재 userId·identityHash 로 직접 등록합니다. 그것마저 실패하면 던지므로 저장한 토큰을 갱신하지 말고 다음에 다시 시도하세요(위 예제는 던지면 setItem 까지 가지 않습니다).

클릭 추적

워커가 notificationclick 에서 자동으로 보고합니다. 탭이 보이는 상태(포그라운드)에서 온 푸시도 onForegroundMessage 를 넘기지 않았다면 SDK 가 서비스워커 등록으로 같은 모양의 알림을 띄우므로 클릭은 같은 경로로 보고됩니다(무음 푸시는 띄우지 않습니다). 보고에 쓸 FCM 토큰은 등록 시점에 IndexedDB 에 저장된 값을 읽습니다 — 워커에서는 getToken 을 부를 수 없기 때문입니다.

수신(도달) 추적

워커가 push 이벤트에서 자동으로 보고합니다(POST /api/v1/messages/received). 앱 코드는 아무것도 하지 않아도 됩니다 — 워커만 최신 NOTIKIT_SERVICE_WORKER 로 배치하세요.

notificationclick 이 아니라 push 에 다는 이유: 무음(data-only) 푸시는 알림을 띄우지 않고, 사용자가 알림을 누르지 않는 경우가 대부분입니다. push 는 배달된 모든 메시지에 대해 한 번 뜨므로 "받았다"의 정의와 정확히 겹칩니다.

이 보고가 없으면 콘솔의 "도달" 칸은 계속 비어 있습니다 — 발송 성공(FCM 접수)은 기기가 꺼져 있어도 성공하므로 도달이 아닙니다. 같은 워커 인스턴스 안에서 같은 발송이 다시 배달되면 요청을 내보내지 않고, 서버도 (발송, 기기) 유니크로 한 번만 셉니다.

iOS Safari 는 홈화면에 추가한 PWA 에서만 웹 푸시가 동작합니다(16.4+).

라이선스

Apache-2.0

GitHub 에서 이 문서 고치기