node-cron을 활용한 알람 기능 구현

Server_side·2023년 10월 29일
1
post-custom-banner

node-cron을 통해 간단하게 알람 기능을 구현할 수 있는 방법에 대해 알아보고자 한다.
해당 라이브러리는 node.js를 기반으로 cron을 활용한 스케쥴러 구현 기능을 제공한다.


Cron??

먼저 크론에 대해 간단하게 알아보자.

Cron이란 시간, 요일 등에 따라 주기적으로 반복해야하는 작업을 수행하기 위한 작업 스케쥴러다.
작업 스케쥴은 아래의 크론식을 통해 설정할 수 있다.

크론 식

* * * * * *
  • 순서대로 '초 / 분 / 시 / 일 / 월 / 요일' 을 나타내며 각 내용 사이를 한칸씩 띄워 구분한다.
  • *은 들어가는 요소마다 모든 시간/날짜를 뜻한다.
  • 요일의 표현 (일: 0, 월: 1, ~~ 토: 6)

크론 식 예시

  • * * * * * * 1초 마다 실행
  • 15,30,45,0 * * * * * 15초마다 실행(',' 이후 띄워쓰기 금지!)
  • 0 0 21 * * * 매일 21시마다 실행
  • 0 0 0 * * 1 매주 월요일 0시 0분 0초마다 실행

구현


모듈 설치

다들 아시는바와 같이 npm 또는 yarn을 이용하여 설치한다.

  • npm install node-cron
  • yarn add node-cron

코드 작성

import cron from 'node-cron';
import { sendEmail } from './email';
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// 유저 설정에 따른 일기 작성 알림 메일 발송
export const sendAlarm = async () => {
  // 매일 21:00:00 스케쥴링 실행
  cron.schedule('0 0 21 * * *', async () => {
    console.log('!!일기 알람 스케쥴링!!');

    // 알림을 위한 각 유저 정보/개인 Diary 조회
    const needKeepDiaryUser = await prisma.user.findMany({
      select: {
        email: true,
        alarmSetting: true,
        Diary: {
          select: {
            createdAt: true,
          },
          orderBy: { createdAt: 'desc' },
        },
      },
    });

    // 한국시간 반영하여 오늘 날짜 조회
    const offset = 1000 * 60 * 60 * 9;
    const koreaNow = new Date(new Date().getTime() + offset);
    const today = parseInt(
      koreaNow.toISOString().slice(0, 10).replace(/-/g, ''),
    );

    // 각 유저를 돌며 for문 실행
    for (let user of needKeepDiaryUser) {
      // 해당 유저가 작성한 Diary가 있는지 확인 없다면 pass 있다면 if 문 실행
      if (user.Diary[0]) {
        // 해당 유저의 최신 일기 작성일 조회
        const diaryCreatedTime = new Date(
          user.Diary[0].createdAt.getTime() + offset,
        );
        const diaryLastWrite = parseInt(
          diaryCreatedTime.toISOString().slice(0, 10).replace(/-/g, ''),
        );
        // 해당 최신일기와 오늘 일자 비교
        const daysSinceLastWrite = today - diaryLastWrite;

        // daysSinceLastWrite가 유저별로 설정한 알림일수 이상일 경우 메일 발송
        if (daysSinceLastWrite >= parseInt(user.alarmSetting)) {
          await sendEmail(
            user.email,
            '[Emotiary] 오늘 하루는 어땟나요? ',
            ``,
            `<div style="text-align:center;">
              <p>오늘 하루도 수고많으셨어요!</p><br />
              <p>오늘 하루를 되짚어보며 일기로 기록해 보는건 어떨까요?</p><br />
              <a href="${process.env.SERVER_URL}" style="
              display: inline-block;
              margin-top: 10px;
              padding: 10px 20px;
              background-color: #FFA2AD;
              color: white;
              text-decoration: none;
              border-radius: 5px;">오늘 하루 기록하러 가기</a>
            </div>`,
          );
        }
      }
    }
  });
};

위와 같이 cron식을 활용하여 원하는 시간에 알람메일을 전송하는 코드를 완성하였다.
일기를 작성하지 않은 유저에게만 알람을 보내기 위해 prisma를 활용하여 각 유저의 일기를 내림차순 조회하였고 이를 활용하여 유저가 설정한 알람 셋팅에 따라 알람 메일 발송할 수 있도록 코드를 작성하였다.

메일 확인

위와 같이 메일이 잘 수신된 것을 확인 할 수 있다.


앞으로 이를 응용하여 스케쥴러를 여러가지 방법으로 활용할 수 있을 것 같다는 자신감이 뿜뿜하는 것을 느끼며... 오늘의 포스팅은 여기까지!!

해당 포스팅은 "daechan_jo"님의 글을 참고하여 작성

profile
아마도 난 백엔드 style?
post-custom-banner

0개의 댓글