티스토리 뷰
사실 nodeJS 책을 봤는데 그 책에 크롤링 cheerio, nodemailer, exceljs, node-cron에 대해 잠깐 배울 수 있었다.
이것들을 배우고 나니 써먹고싶어서 친한 친구에게 뭐 좀 도와줄까? 하고 물어서..ㅋㅋ
증권업계에 종사하는 친구를 위해 아침 7시에 각종 지수를 모아서 엑셀로 만들어 메일로 보내주는 nodejs 코드를 작성했다.
cron.schedule(
'0 7 * * *',
async () => {
const indexes = await getIndex();
const excelFile = await genExcel(indexes);
sendMail(excelFile);
},
{
scheduled: true,
timezone: 'Asia/Seoul',
}
);
매일 아침 7시에 동작하는 크론을 작성했다. getIndex() 함수는 원하는 지수들을 전부 가져오는 함수이다.
친구가 필요로 하는 지수들이 정확했기에 일단 매개변수 없이 하나의 동작만 하는 함수로 작성했다.
그리고 그 지수들로 Excel을 생성하는 함수인 genExcel() 함수에 방금 가져온 지수를 매개변수로 주고
excelFile이 생성되면 이것을 sendMail()함수에 보내서 메일이 발송되도록 처리했다.
const getIndex = async () => {
try {
const [
responseKorea,
responseUSA,
responseTOPX,
responseEXCHANGE,
responseSwedenEXCHANGE,
] = await Promise.all([
axios.get(urlKoreaIndex),
axios.get(urlUSAIndex),
axios.get(urlTOPXIndex),
axios.get(urlEXCHANGEIndex),
axios.get(urlSwedenExchage),
]);
const $korea = cheerio.load(responseKorea.data);
const $usa = cheerio.load(responseUSA.data);
const $topx = cheerio.load(responseTOPX.data);
const $exchange = cheerio.load(responseEXCHANGE.data);
const $swedenExchange = cheerio.load(responseSwedenEXCHANGE.data);
return {
KOSPI: $korea('#KOSPI_now').text(),
KOSDAQ: $korea('#KOSDAQ_now').text(),
DOW: $usa(dowSelector).text(),
NASDAQ: $usa(nasdaqSelector).text(),
SNP500: $usa(snpSelector).text(),
TOPX: $topx('.spt_con strong').text(),
USAEX: $exchange(usaExSelector).text(),
JAPANEX: $exchange(japanExSelector).text(),
EUROEX: $exchange(euroExSelector).text(),
SWEDENEX: $swedenExchange(swedenExSelector).text(),
};
} catch (error) {
console.error(error);
return null;
}
};
생각보다 지수가 한꺼번에 모인 사이트를 찾기 어려워서 이곳저곳 들어가서 html을 가져왔다.
처음에는 지수를 가져올때마다 await을 걸어서 총 5번 await 이 걸리도록 코드를 작성했는데,
html을 가져오는 사이트들은 서로 전혀 상관없었기에 병렬적으로 처리해 주기 위해 Promise.all을 사용했다.
dowSelector 같은 곳에 문자열로 된 selector들이 저장되어 있다.
이렇게 해서 원하는 지수들을 가져온 뒤에 리턴 시켜준다.
const genExcel = async (data) => {
const workbook = new ExcelJS.Workbook();
const firstSheet = workbook.addWorksheet('지수리스트');
firstSheet.columns = excelHeader;
firstSheet.addRow(data);
const excel = await workbook.xlsx.writeBuffer();
return excel;
};
엑셀은 이렇게 만들어준다. excelHeader에 이미 매개변수로 받는 data와 key들을 맞춰놓았기 때문에
간단하게 작성할 수 있다.
const send = async (data) => {
const transporter = nodemailer.createTransport(config);
const result = await transporter.sendMail(data);
return result.messageId;
};
module.exports = { send };
const sendMail = async (buffer) => {
if (!Buffer.isBuffer(buffer)) {
throw new Error('Invalid buffer object.');
}
const filename = `${Date.now()}_각종지수.xlsx`;
const fromEmail = process.env.MAIL_FROM;
const toEmail =
process.env.ENV === 'dev'
? process.env.MAIL_TO_DEV
: process.env.MAIL_TO_PROD;
const result = await nodemailer.send({
from: fromEmail,
to: toEmail,
subject: '각종지수 엑셀발송',
text: '문의는 변기원에게',
attachments: [
{
filename,
content: buffer,
contentType:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
},
],
});
if (!result?.length) {
throw new Error('Failed to send email.');
}
return result;
};
다른 모듈에서 send 함수를 쉽게 사용할 수 있도록 만들어주고 에러 처리를 위해 result.messageId를 리턴해주자
메일을 받을 사람도 내 친구밖에 없으므로 환경변수에 담아서 작성해 주고 nodemailer.send()를 실행시켜서 메일을 보낸다.
그리고 buffer를 받아서 첨부해 주자.
생각해 보니 위에 genExcel 함수를 genExcelBuffer 같은 거로 바꾸는 게 낫겠다.
이렇게 하고 나니 하루 오전 7시에 한 번만 발송되는 게 조~금 아쉽더라.
그래서 프런트엔드 화면을 만들어서 api를 붙이고 클릭하면(GET요청을 보내면) 그 시간 기준으로 지수를 종합해서
메일로 보내주는 api를 만들었다.
일하다가 기분 좋으라고 꽃가루도 날려줬다.
누군가에게 도움이 되니 공부할 맛이 난다.
'nodeJS' 카테고리의 다른 글
nestJS 프로젝트 aws ec2에 직접 배포하기 (0) | 2023.02.25 |
---|---|
[nestJS]페이지네이션 기능 구현하기 (0) | 2023.01.19 |
[nestJS]배열의 비동기처리 병렬적으로 실행하기 (0) | 2023.01.08 |
[nestJS]class-validator 특수문자 포함여부 유효성검사 (0) | 2023.01.05 |
[nestJS] middleware 로 logger만들기 (0) | 2022.12.26 |