텔레그램 가상화폐 시세 알림봇 만들기 1편을 안보신 분은 아래 게시글을 확인해주세요.
텔레그램 가상화폐 시세 알림봇
1편에 이어 2편에서는 서버에 배포하는 코드를 작성해보도록 하겠습니다. 매일2시간씩 하루에 12번 메시지를 보내야 하기 때문에 24시간 돌아가는 서버가 필요합니다. 다행히도 저는 포트폴리오 배포를 위한 AWS ec2 Linux 서버를 돌리고 있어 텔레그램 봇이랑 같이 배포해보도록 하겠습니다.
Node Express를 사용하고 있어 코드는 자바스크립트를 사용합니다.
요구사항 중 매 2시간 단위로 메시지를 보내야 합니다. 그렇게 하기 위해서는 자바스크립트에서 제공하는 setInterval() 메서드를 사용하면 되지만, 나중에 잠자는 시간에는 메시지를 안 받게 한다거나 1시간 주기로 바꾼다거나 요구사항이 바뀔 수 있기 때문에 유지보수/확장성을 고려해 스케줄 라이브러리를 사용하보겠습니다.
스케줄 라이브러리 3개를 비교한 글이 있습니다. 위 글에서는 node-schedule을 사용했으나 같은 cron방식의 node-cron을 사용해보겠습니다.
> npm i node-cron
cron syntax
# ┌────────────── second (optional)
# │ ┌──────────── minute
# │ │ ┌────────── hour
# │ │ │ ┌──────── day of month
# │ │ │ │ ┌────── month
# │ │ │ │ │ ┌──── day of week
# │ │ │ │ │ │
# │ │ │ │ │ │
# * * * * * *
field | value |
second | 0-59 |
minute | 0-59 |
hour | 0-23 |
day of month | 1-31 |
month | 1-12 (or names) |
day of week | 0-7 (or names, 0 or 7 are sunday) |
node-cron의 자세한 설명은 아래 글을 확인해주세요.
간단하게 cron 표현식을 만들고 싶다면 아래 홈페이지에서 만들어주세요.
저는 다른 코드들과 분리하기 위해 cryptoAlarm.js 파일을 만들어 기능 구현을 하고, www.js 파일을 만들어 서버를 실행시키도록 하겠습니다.
cryptoAlarm.js
const axios = require("axios");
const token = "<Telegram Bot Token>";
const id = "<Telegram ID>";
const upbit_url = 'https://api.upbit.com/v1/ticker?markets=';
const tel_url = `https://api.telegram.org/bot${token}/sendmessage?chat_id=${id}&text=`;
const crypto = "KRW-BTC,KRW-ETH,KRW-ORBS";
const getPrice = async () => { //업비트 시세 조회
const getPrice_res = await axios(upbit_url+crypto)
.then((res) => {return res; })
.catch((err) => { return err; });
return getPrice_res;
}
const sendTel = async (msg) => { //텔레그램 메시지 전송
const sendTel_res = await axios.get(tel_url+encodeURI(msg))
.then(res => { return res; })
.catch(err => { return err; });
return sendTel_res;
}
const nowDate = () => {
const _date = new Date();
const date = `Date : ${_date.getFullYear()}/${(_date.getMonth()+1)}/${_date.getDate()}/${_date.getHours()}:${_date.getMinutes()}`;
return date;
}
const sendAlarm = async () => {
const getPrice_res = await getPrice(); //업비트 시세 조회
if(getPrice_res.status === 200){ //시세 조회 성공
const btc = getPrice_res.data[0].trade_price.toLocaleString(); //비트코인
const eth = getPrice_res.data[1].trade_price.toLocaleString(); //이더리움
const orbs = getPrice_res.data[2].trade_price.toLocaleString(); //오브스
const msg = `비트코인(₿) : ${btc}원\n이더리움(⧫) : ${eth}원\n오브스(⎔) : ${orbs}원`;
const sendTel_res = await sendTel(msg);
if(sendTel_res.status === 200){ //메시지 전송 성공
console.log(`${nowDate()} - 메세지 전송 성공`);
}else{ //메시지 전송 실패
console.log(`${nowDate()} - 메세지 전송 실패\n${sendTel_res}`);
}
}else{
await sendTel('업비트 시세 조회 실패'); //실패 메시지 전송
}
}
module.exports = sendAlarm
www.js
const cron = require('node-cron');
const sendAlarm = require("./router/cryptoAlarm.js");
cron.schedule('*/10 * * * * *', ()=> {
console.log('10초 마다 실행');
sendAlarm();
});
실행될 서버 코드까지 작성했습니다. 우선 테스트를 위해 10초마다 메시지를 보내도록 설정했고 이제 서버를 실행하기만 하면 됩니다. 실행될 파일 경로까지 터미널로 이동해 서버 실행 명령어를 입력해줍니다.
> node www.js
제 경우 pm2 프로세스 관리자를 사용하므로 아래 명령어를 사용하겠습니다.
> pm2 start www.js --watch
pm2의 클러스터 모드를 사용하는 경우 아래의 단일 프로세스에서 작동하도록 설정해주어야 합니다. 제 AWS ec2는 성능이 좋지 않아.. ㅎ
서버를 실행하고 10초마다 정상적으로 메시지가 도착하는 것을 확인할 수 있습니다. 이제 10초 주기를 2시간 주기로 변경해 주면 완성입니다.
const cron = require('node-cron');
const sendAlarm = require("./router/cryptoAlarm.js");
cron.schedule('0 */2 * * *', ()=> { //“At minute 0 past every 2nd hour.”
sendAlarm();
});
PC에서는 바로 도착했는데 핸드폰에서는 약간의 딜레이가 발생하네요.