Back/Node.js

[Node.Js, ReactNative] FCM Notification firebase-admin 전체 유저에게 푸쉬알람 보내기

파이어베이스 콘솔에서 메시지를 푸시할 수도 있겠지만,

여러 이유들로 서버에서 전체메시지를 직접 보내기로했다..

애널리틱스등 유저활동을 감지했으면 좋겠을 경우에는 그냥 콘솔에서 보내면 되는데,

보내야 할 전체 알람의 기능적 성격과 실무자들의 편의를 위해 서버에서 직접 보내기로 했다.

npm install firebase-admin


firebase-admin을 설치해준다.

 

firebase-admin

Firebase admin SDK for Node.js. Latest version: 10.0.2, last published: 21 days ago. Start using firebase-admin in your project by running `npm i firebase-admin`. There are 1900 other projects in the npm registry using firebase-admin.

www.npmjs.com


보낼 메시지를 만든다.

      const message = {
        notification: {
          title: title,
          body: body,
        },
        data: {
          id: 'id',
          title: 'data-title',
          body: 'data-body',
          origin: 'chat',
        },
        android: {
          priority: 'high',
          notification: {
            title: title,
            body: body,
            sound: 'default',
            priority: 'high',
            icon: 'default',
            channelId: '500',
          },
        },
        tokens: pushList,
      };

1명에게 보낼 땐 token : token을 담으면 되겠다.

만든 메시지를 파이어베이스 어드민을 사용해서 보내준다.

 

여기서 중요한 점은 최대 500개까지 보낼 수 있다. (공식문서에 따르면 그렇다)

        admins
          .messaging()
          .sendMulticast(message)
          .then(function (response) {
            console.log(`success`);
          })
          .catch(function (err) {
            console.log('Error Sending message!!! : ', err);
          });

 

1명에게 보낼땐 send를 사용했다.

코드 전문

exports.pushAlarmAllUser = async (req, res, next) => {
  const pool = await mysqlWrite.getConnection(async (conn) => conn);
  try {
    const { title, body } = req.body;
    const [tokenList] = await mysqlRead.query(query, [key]);

    const changeTokenObjToStringForSlice = [];

    for (let i = 0; i < tokenList.length; i++) {
      changeTokenObjToStringForSlice.push(tokenList[i].push_token);
    }

    const notiTokenArray = [];
    for (let i = 0; i < changeTokenObjToStringForSlice.length; i += 500) {
      notiTokenArray.push(changeTokenObjToStringForSlice.slice(i, i + 500));
    }

    function fcmNotiApi(pushList) {
      return new Promise((resolve, reject) => {
        const message = {
          notification: {
            title: title,
            body: body,
          },
          data: {
            id: 'id',
            title: 'data-title',
            body: 'data-body',
            origin: 'chat',
          },
          android: {
            priority: 'high',
            notification: {
              title: title,
              body: body,
              sound: 'default',
              priority: 'high',
              icon: 'default',
              channelId: '500',
            },
          },
          tokens: pushList,
        };

        try {
          admins
            .messaging()
            .sendMulticast(message)
            .then(function (response) {
              console.log(`success`);
            })
            .catch(function (err) {
              console.log('Error Sending message!!! : ', err);
            });

          return;
        } catch (err) {
          console.log(err);
          return;
        }
      });
    }

    async function notiStart(notiTokenArray) {
      const notiPromises = notiTokenArray.map((tokenLimit500) => fcmNotiApi(tokenLimit500));
      await Promise.all(notiPromises);
    }

    notiStart(notiTokenArray);

    return res.status(200).json({ msg: `${notiTokenArray[i].length}명 전송 완료` });
  } catch (err) {
    console.log(err);
    return res.status(400).json({ msg: 'fail' });
  } finally {
    pool.release();
  }
};

promise.all로 보내려다가 걍 500개씩 끊어서 보냈다.

변화가 계속 빠른 스타트업에서는 프로덕트가 일단은 나와야 하고, 기능이 나와야 한다.

또 협업시 디자인이든 개발이든 기획이든 어느쪽에서 일이 밀려버린다면 균형이 무너질 수 있기 때문에 케파를 고려해야하는데,

개발쪽이 밀려서 일이 진행 안되는건 싫었다.
일단 만들고 리팩토링은 시간 남을 때 마다 천천히 하는 방식으로 진행하고 있다..
머리가 점점 헤롱헤롱 거린다.