Back/Node.js

[Node.js] FCM Notification 알람 자동화 작업

앱에서 각종 알람들을 자동화해야했다ㅠ

 

나는 회사에서 사용하는 서비스를 AWS에서 작은 용량의 ec2를 여러개 놓고, 용도와 필요에 맞게 나눠서 쓰는 식으로 설계했는데,

 

알람도 자동화를 돌릴 알람들을 용도와 연결된 것들에 맞게끔 나눴다.

 

그래야 유지보수가 편할 것 같아서인데, 이건 나중에 지켜봐야겠지..

 

일단 간단한 예제 파일을 만들었다.

 

실제 프로덕트에 적용할 땐 인터페이스와 모듈화를 잘 해놓아야한다.

 

app.controller.ts

const customNotiCron = cron.schedule('* * * * *', async () => {
  try {
    const day: number = dayjs().tz('Asia/Seoul').day();
    const notiTime: string = dayjs().tz('Asia/Seoul').format(CUSTOM_PARSE_FORMAT);
    const query: string = await notiSelectQuery(day);
    const [customNotiList] = await mysqlRead.query<RowDataPacket[string]>(query, [notiTime]);
    customNotiStart(customNotiList);
    return;
  } catch (err) {
    console.log(err);
  }
});

export = customNotiCron;

 

라이브러리는 node-cron을 활용했다.

 

컨트롤러에선 쿼리를 이용해서, 원하는 알람 목록들을 뽑아오고, 미리 만들어둔 customNotiStart라는 함수를 사용한다.

 

여기서 값을 뽑아올 때 임시로 mysql을 이용했지만, cache서버나, 프로덕트 상황에 맞게끔 이용해서 뽑아오면 되겠다.

나는 실제로 할 땐 mysql과 스택큐를 활용하려했지만, 어긋나는 부분이 있어서, cache를 이용해서 해쉬를 다뽑아오는 것으로 했다.

 

모든 유저가 동일한 메시지를 받는다면 문제가 쉬워지겠지만,

 

각각의 메시지들을 언제 어느때나 CRUD할 수 있었고, 그에 따라 보내는 값들이 매분 매초 달라지기 때문에 단순하게 데이터를 저장했다가 보낼 수는 없는 구조였다.

 

app.service.ts

async function customNotiStart(
  notiTokenArray: Array<{ title: string; push_token: string; noti_title_emoticon_unicode: string; member_name: string }>,
) {
  try {
    const notiPromises = notiTokenArray.map((noti) =>
      fcmNotiApi(noti.title, noti.push_token, noti.noti_title_emoticon_unicode, noti.member_name),
    );
    await Promise.all(notiPromises);
  } catch (err) {
    console.log(err);
  }
}

서비스에선 fcmNoti를 보내는 함수를 Promise묶은 뒤, 한번에 보낸다.

 

파이어베이스에선 어떤 식으로 처리되는지 알 수 없지만, 병렬적으로 보내도 처리는 직렬적으로 되는 것 같다.

 

fcmNotiApi.ts

function fcmNotiApi(title: string, pushToken: string, emoji: string, memberName: string) {
  return new Promise((resolve, reject) => {
    try {
      admin
        .messaging()
        .send({
          notification: {
            title: `${emoji} ${title} ${emoji}`,
            body: `${memberName}님, '${title}' 잊지 말고 챙기세요! 😉`,
          },
          data: {
            id: 'id',
            head: 'data-title',
            body: 'data-body',
            origin: 'chat',
          },
          android: {
            priority: 'high',
            notification: {
              title: `${emoji} ${title} ${emoji}`,
              body: `${memberName}님, '${title}' 잊지 말고 챙기세요! 😉`,
              sound: 'default',
              priority: 'high',
              icon: 'default',
              channelId: '500',
            },
          },
          token: pushToken,
        })
        .then((response) => {
          // console.log('success', response);
        })
        .catch((err) => {
          console.log('customPushError : ', err);
        });
      return;
    } catch (err) {
      console.log(err);
    }
  });
}

 

알람이 동시에 잘 간다.

 

현재 자동화된 각종 커스텀 알람들이 맞물려 있고,

 

어떤 알람들은 서로 유기적으로 연결되어 있는 경우도 있어서, 설계할 때 잘 해야 나중에 유지보수 할 떄 쉬워질텐데,


현재는 디비, 인프라, 서버 등 혼자 제작해야하니, 어떤 것이 옳은 방식일지 확신 할 수 없고, 확신할 만큼 실력에 대한 자신도 없다.

 

주변 다른 회사 개발자들과 교류하며, 여러 인사이트를 얻기도 하고

문제 상황에 부딪쳤을 때 비슷한 상황의 다른 회사 코드도 참고하며,

우리 프로덕트 상황에 맞게 소급적용 하며 개발할 때도 있고 그렇다..

 

하지만 그런 것들은 임시방편일 뿐이고, 본질적인 부분에 막혀서 시간이 많이 드는 일들이 있다..

할 때마다 느끼지만 많이 부족하고, 공부가 더 필요하다.

그래도 어떤 것이 옳은 방식의 작업일지는 모르겠으나, 이 분야에서 일을 어떤 식으로 처리해나가야할 지에 대해선 감을 잡고 있다.