본문 바로가기

프론트엔드

Next.js + Firebase를 활용한 모바일 푸시 구현

반응형

요즘 코드드림팀에서는 교회를 대상으로 하는 서비스를 개발하고 있습니다.

교회 다니는 팀원이 있어 간단한 서비스를 제공해볼까라는 이야기에서 시작되었는데요. 개발할수록 기능이 하나씩 추가되고 있어요. 최근에 서비스 안에 기능 중 모바일 앱으로 푸시를 보내는 기능이 필요해졌는데요.

파이어베이스에서 Node를 지원하는 것을 보고 파이어베이스를 이용하기로 했습니다.

 

Spring에서만 해봤던 기능을 Next.js에서는 처음 해보게 돼서 포스팅을 작성해봤고, 테스트 환경은 다음과 같습니다.

*모바일앱은 Flutter를 이용했고 푸시를 받기 위한 환경은 갖춰진 상태입니다.

  • Next.js 14
  • Firebase admin sdk
  • Typescript 5

1. 서비스 키 생성

1-1) 파이어베이스에 접속 후 프로젝트 선택

1-2) 프로젝트 설정 - 서비스 계정 - 비공개 키 생성 클릭

 

1-3) 다운받은 키는 프로젝트 특정 폴더에 위치시킵니다.

 

2. Firebase 설치

npm install firebase-admin --save

 

3. Firebase SDK 초기화

3-1) 파이어베이스 api를 생성합니다. 

SDK 초기화시 1-3)에서 위치한 경로를 지정해줍니다.

 

api/fcm/route.ts

import admin from "firebase-admin";
import { getMessaging } from "firebase-admin/messaging";

const firebaseConfig = require("@constants/fcm/firebase-admin-sdk.json");

export async function GET(req: Request, res: Response) {
  try {
    if (admin.apps.length === 0) {
      admin.initializeApp({
        credential: admin.credential.cert(firebaseConfig),
      });
      
      console.log("Authentication success");
    }    

    return Response.json({
      message: message,
    });
  } catch (error) {
    return Response.error();
  }
}

 

localhost:3000/api/fcm 호출 후 초기화가 잘되었는지 확인합니다.

 

*초기화 상태를 체크하지 않고 중복 초기화를 하게 되면 아래와 같은 에러 메세지가 발생합니다.

 

4. 푸시 테스트

이제 토큰을 파라미터로 전달받아 푸시를 전송하는 코드를 작성해봅니다.

message에 선언된 data 섹션은 클라이언트에 전달될 부분과 동일해야 합니다.

모바일앱 FCM 수신 중 일부

 

api/fcm/route.ts

import admin from "firebase-admin";
import { getMessaging } from "firebase-admin/messaging";

const firebaseConfig = require("@constants/fcm/firebase-admin-sdk.json");

/**
 * 푸시 테스트
 * @param req
 * @param token 테스트 토큰
 * @returns
 */
export async function GET(req: Request, res: Response) {
  const { searchParams } = new URL(req.url);
  const token = searchParams.get("token");
  let message = "OK";

  try {
    if (admin.apps.length === 0) {
      admin.initializeApp({
        credential: admin.credential.cert(firebaseConfig),
      });

      console.log("Authentication success");
    }

    if (token) {
      const message = {
        notification: {
          title: "푸시 테스트",
          body: "푸시 내용입니다.",
        },
        data: {
          id: generateRandomString(6),
          title: "푸시 테스트",
          content: "푸시 내용입니다.",
        },
        token: token,
        apns: {
          payload: {
            aps: {
              contentAvailable: true,
              badge: 0,
              sound: "default",
            },
          },
        },
      };

      getMessaging()
        .send(message)
        .then((response) => {
          console.log("Successfully sent message:", response);
        })
        .catch((error) => {
          console.log("Error sending message:", error);
        });
    } else {
      message = "Token is not available";
    }

    return Response.json({
      message: message,
    });
  } catch (error) {
    return Response.error();
  }
}

 

api를 테스트해봅니다.

 

푸시가 성공되면 아래와 같이 조회됩니다.

 

개발하고 보니 서버에서 푸시 메세지를 보내는 것이 클라이언트에서 푸시를 받는 설정보다 더 간편했던 것 같습니다.

푸시 수신 설정시에 앱 특성상 기기 상태별로 따로 처리해줘야하는 부분(background, foreground, terminated 상태에 따른) 이 많더라구요. 특히 IOS 설정 부분은 깨나 애먹었던 것 같아요.

 

참고문서
 

서버에 Firebase Admin SDK 추가

Admin SDK는 권한이 있는 환경에서 Firebase와 상호작용할 수 있는 서버 라이브러리 집합입니다.

firebase.google.com

 

반응형