Vue로 PWA 개발

48. mylog FCM 토큰 등록

그랜파 개발자 2024. 10. 31. 15:48

"같은 회원이 PC와 모바일에 fcm을 받으려면?"
위 질문으로 한 회원에 대해 여러 개의 토큰을 저장할 수 있는 코드를 답으로 받았지만, 이것은 기존에 토큰 정보가 저장되어 있는 회원에 대해 토큰을 추가하는 기능입니다. 우리가 필요한 것은 아직 FCM 토큰을 등록하지 않은 회원이 처음 토큰을 등록하는 기능도 필요하고, 또한 토큰 등록 날짜 정보도 저장하기를 원합니다.

ChatGPT에게 물었습니다.

I want to store the FCM token and creation date on multiple devices for the same member, and also tell me what to do when the token is first registered.

같은 회원에 대해 여러 기기의 FCM token과 생성 날짜를 저장하고 싶어, 그리고 토큰을 처음 등록할 때 처리도 알려줘.

ChatGPT

 

To store an FCM token and the creation date for the same user across multiple devices, you can use Firestore to save each token along with a createdAt timestamp. This ensures that each device has its own token and registration date. You can use Firestore's arrayUnion() method to add unique tokens without duplicates and check if the token is new when it's first registered. If it's a new token, you'll store it along with the timestamp.

 

여러 기기에 걸쳐 동일한 사용자의 FCM 토큰과 생성 날짜를 저장하려면 Firestore를 사용하여 'createdAt' 타임스탬프와 함께 각 토큰을 저장하면 됩니다. 이렇게 하면 각 장치에 고유한 토큰과 등록 날짜가 있습니다. Firestore의 arrayUnion() 메서드를 사용하여 중복 없이 고유한 토큰을 추가하고 토큰이 처음 등록될 때 새 토큰인지 확인할 수 있습니다. 새 토큰인 경우 타임스탬프와 함께 저장합니다.

 

Structure of Firestore Data:

Firestore 데이터 구조:

For each user, you can store a list of tokens in a field like fcmTokens, where each token has both the token itself and a createdAt timestamp.
각 사용자에 대해 fcmTokens와 같은 필드에 토큰 목록을 저장할 수 있습니다. 여기서 각 토큰에는 token 자체와 createdAt 타임스탬프가 모두 있습니다.

{
  "users": {
    "userId": {
      "fcmTokens": [
        {
          "token": "deviceToken1",
          "createdAt": "2024-10-03T10:20:30Z"
        },
        {
          "token": "deviceToken2",
          "createdAt": "2024-10-03T12:34:56Z"
        }
      ]
    }
  }
}

 

Steps to Implement: 구현 단계:

  1. Check if the token exists.
    토큰이 존재하는지 확인하세요.
  2. If it's a new token, save it to Firestore with the createdAt field.
    새 토큰인 경우 createdAt 필드를 사용하여 Firestore에 저장합니다.
  3. If the token already exists, skip adding it again.
    토큰이 이미 존재하는 경우 다시 추가하는 것을 건너뛰세요.

 

Implementation 구현

 

Here’s how you can implement this using Firebase v9, with Firestore to store tokens and their creation dates:
토큰과 생성 날짜를 저장하기 위해 Firestore와 함께 Firebase v9를 사용하여 이를 구현하는 방법은 다음과 같습니다.

import { initializeApp } from "firebase/app";
import { getFirestore, doc, updateDoc, getDoc, arrayUnion, setDoc, serverTimestamp } from "firebase/firestore";
import { getToken } from "firebase/messaging";
import { messaging } from "./firebase";  // Your Firebase Messaging config

// Firebase initialization
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};

// Initialize Firebase and Firestore
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

// Function to get FCM Token and save it with the creation date
export const getAndSaveFCMToken = async (userId) => {
  try {
    // Request notification permission from the user
    const permission = await Notification.requestPermission();

    if (permission === 'granted') {
      // Get the FCM token
      const token = await getToken(messaging, { vapidKey: 'YOUR_VAPID_KEY' });

      if (token) {
        console.log('FCM Token:', token);
        // Save the token and creation date
        await saveFCMToken(userId, token);
      } else {
        console.log('No FCM token available.');
      }
    } else {
      console.log('Notification permission denied.');
    }
  } catch (error) {
    console.error('Error getting FCM token:', error);
  }
};

// Function to save the FCM token with creation date
const saveFCMToken = async (userId, token) => {
  const userRef = doc(db, "users", userId);

  try {
    const userDoc = await getDoc(userRef);

    if (userDoc.exists()) {
      const tokens = userDoc.data().fcmTokens || [];

      // Check if the token already exists
      const tokenExists = tokens.some(t => t.token === token);

      if (!tokenExists) {
        // Add the token with creation date using arrayUnion
        await updateDoc(userRef, {
          fcmTokens: arrayUnion({
            token: token,
            createdAt: serverTimestamp()  // Store server timestamp as creation date
          })
        });
        console.log('New FCM token added with creation date.');
      } else {
        console.log('FCM token already exists, no action taken.');
      }
    } else {
      // Create a new document if the user does not exist, with the token and creation date
      await setDoc(userRef, {
        fcmTokens: [{
          token: token,
          createdAt: serverTimestamp()  // Store server timestamp as creation date
        }]
      });
      console.log('User document created and token saved.');
    }
  } catch (error) {
    console.error('Error saving FCM token:', error);
  }
};

Explanation: 설명:

1. FCM Token Retrieval: FCM 토큰 검색:

  • getAndSaveFCMToken requests notification permissions and retrieves the FCM token using getToken(). If successful, it proceeds to save the token using saveFCMToken.
    getAndSaveFCMToken은 알림 권한을 요청하고 getToken()을 사용하여 FCM 토큰을 검색합니다. 성공하면 saveFCMToken을 사용하여 토큰 저장을 진행합니다.

2. Check and Add Token: 토큰 확인 및 추가:

  • The saveFCMToken function checks if the user's Firestore document already contains the token. It fetches the document using getDoc.
    saveFCMToken 함수는 사용자의 Firestore 문서에 이미 토큰이 포함되어 있는지 확인합니다. getDoc을 사용하여 문서를 가져옵니다.
  • If the token exists, it skips adding it again. If it doesn't, it uses arrayUnion() to add the token and the createdAt timestamp (serverTimestamp()).
    토큰이 존재하는 경우 다시 추가하는 것을 건너뜁니다. 그렇지 않은 경우 arrayUnion()을 사용하여 토큰과 createdAt 타임스탬프(serverTimestamp())를 추가합니다.

3. Handle Non-Existing User Document: 존재하지 않는 사용자 문서 처리:

  • If the user document doesn't exist (i.e., it's the first time the user registers an FCM token), it creates the document using setDoc.
    사용자 문서가 존재하지 않는 경우(즉, 사용자가 FCM 토큰을 처음 등록하는 경우) setDoc을 사용하여 문서를 생성합니다.

4. FCM Token and Creation Date: FCM 토큰 및 생성 날짜:

  • Each token is stored with a createdAt field, using serverTimestamp() to record the exact time it was added.
    각 토큰은 추가된 정확한 시간을 기록하기 위해 serverTimestamp()를 사용하여 createdAt 필드와 함께 저장됩니다.

Firestore Structure Example: Firestore 구조 예:

For each user, the fcmTokens field is an array of objects, where each object contains a token and a createdAt timestamp. If a user has multiple devices, they will have multiple entries in the fcmTokens array:
각 사용자의 'fcmTokens' 필드는 객체의 배열이며, 각 객체에는 'token' 및 'createdAt' 타임스탬프가 포함되어 있습니다. 사용자가 여러 장치를 가지고 있는 경우 fcmTokens 배열에 여러 항목이 있습니다.

{
  "users": {
    "userId123": {
      "fcmTokens": [
        {
          "token": "fcmToken1",
          "createdAt": "2024-10-03T08:45:12Z"
        },
        {
          "token": "fcmToken2",
          "createdAt": "2024-10-03T09:50:30Z"
        }
      ]
    }
  }
}

 

What Happens When the Token Is First Registered:

토큰이 처음 등록되면 어떻게 되나요?

  • When a token is first registered for a user, it is added to Firestore with the current timestamp (createdAt). If it's a new user, their Firestore document is created with the token and timestamp.
    토큰이 사용자에게 처음 등록되면 현재 타임스탬프(createdAt)와 함께 Firestore에 추가됩니다. 신규 사용자인 경우 토큰과 타임스탬프가 포함된 Firestore 문서가 생성됩니다.
  • If the same user registers from multiple devices, each token is saved in the fcmTokens array, with a unique createdAt timestamp.
    동일한 사용자가 여러 장치에서 등록하는 경우 각 토큰은 고유한 createdAt 타임스탬프와 함께 fcmTokens 배열에 저장됩니다.



'Vue로 PWA 개발' 카테고리의 다른 글

50. mylog Firebase Functions  (2) 2024.10.31
49. mylog 알림 요청 개선  (3) 2024.10.31
47. mylog 여러 기기에 알림  (0) 2024.10.30
46. mylog 알림 요청  (0) 2024.10.30
45. mylog FCM Token Firestore 저장  (0) 2024.10.30