예전에 저는 이메일 봇을 Github Actions를 통해 만든 적이 있습니다. 이번에는 그 봇을 조금 더 개선해본 경험을 정리해보겠습니다.
.then()
체이닝에서 async function으로JS에서 비동기 작업을 처리하는 데에는 여러 방법이 있습니다. 옛날 부터 많이 쓰였던 CallBack도 있고, 반환 결과에 따라 다른 결과를 연결하기 쉽게 .then()
으로 처리하는 Promise도 있고, 이를 동기함수 처리하듯이 짜기 위해 만들어진 asynce function도 있습니다. 처음에는 직관적으로 바로 다음 작업이 연계되는 Promise와 .then()
을 기반으로 짰었는데 뭔가 아쉬웠습니다.
then
으로 연결되어 있으니 각 부분이 뭘 하는 지가 명확하지 않습니다..catch()
를 쓰면 되긴 하지만, 체이닝을 반복하다 보면 어디가 어디인지 헷갈리게 됩니다. 이런 이유로, 그 동안 작업하면서 비교적 익숙해진 async function을 사용해서 각 부분을 이름을 달아서 바꿔주고, 각 부분 로직을 나누어서 변경 해 주었습니다. 또한 각 부분 마다 에러 처리 부분을 달아주었고요.
before
getHTML()
.then(html) => {}
.then(uList) => {}
.then(bodyList) => {}
after
const getHTML = async => {}
const getArticles = async (now) => {}
(async function sendEmail() {})
앞에 sendEmail()
을 보면, 함수가 () 안에 들어가 있는 것을 볼 수 있습니다. 이 문법은 즉시 실행 함수라는 문법(MDN)으로, 함수가 선언과 동시에 실행 될 수 있도록 합니다. 저의 경우엔 sendEmail()
은 딱 한번만 실행되면 되는 함수이다 보니 그냥 바로 선언과 동시에 실행되도록 하였습니다.
Github Actions는 기본적으로 npm을 통해서 돌아가는데, 저는 주로 yarn을 썼습니다. 그래서 lock파일을 변환해주는 라이브러리를 사용했는데, 이 라이브러리가 지원이 끊긴 다른 라이브러리에 의존하고 있었습니다. 그래서 그걸 제거하고 npm으로만 관리하기로 했습니다.
원래는 일주일에 3번 이메일을 받고 상단 고정이 되어 있는 공지를 포함해서 보냈었는데, 이 부분을 상단 고정된 공지를 제외하고 올라온지 2일이 안 지난 메일을 정리해서 보내도록 했습니다.
const compareDate = (article) => {
return (now - article.date) / (1000 * 60 * 60 * 24) < 2;
};
const result = articles.filter(compareDate)
보낼 내용이 없을 때, 즉 빈 배열일 때 이메일을 보내지 않는 방법입니다. 처음에는 === []
으로 비교 했는데, 이게 잘못된 비교 방법이라 항상 false를 반환하더라고요. 관련 스택오버플로우 질문
그 대신에 Array.prototype.length
를 이용하여 비교하였습니다.
if (articles.length === 0) {
console.log("Nothing to Send");
return;
}
이렇게 제 코드를 전체적으로 리팩토링하고 개선하였습니다. 그렇게 복잡한 프로젝트도 아니고 어렵지는 않았지만, 자바스크립트에서 객체 비교 같은 좀 주의해야할 기본적인 지식을 알 수 있었습니다. 다음 목표는 여기에 Typescript를 적용하여 보다 더 명시적인 코드를 작성하는 것입니다.