본문 바로가기

Programing/Node.js

[AWS lambda] 데이터 클린징에서 배운 내용

팀 이동을 하면서 이전에 개인정보 정리를 위한 데이터 클린징 작업을 했다.

클린징 메인 로직은 Java로 구성을 하고 트리거는 AWS lambda에서 node.js 스크립트를 구성하여 동작하게 했다.

날짜

자바스크립트 진영에서는 이미 Moment.js 가 표준으로 자리잡은 것 같다. ( 2020-11-04 성준님이 요즘 대새는 Day.js 라고 한다. 참고로 footprint가 moment.js 대비 1/33 이다.)

하지만 아쉽게도 해당 서드파티라이브러리를 이용하려면 해당 패키지를 함수 코드에 추가를 해야한다.

의존성 관리(예. 의존성 모듈 업로드) 등의 부가적인 작업을 해주어야 해서 일단 빠르게 만들어야 해서 Vanilla JS 로만 작성을 하기로 결정했다.

클린징을 위해서는 몇 일전 날짜를 구하는 것이 필요했다.

moment.js에서는 아래와 같이 subsubtract 하면 쉽게 구할 수 있다.

moment().subtract(10, 'days').format('YYYY-MM-DD'); // 10일전 날짜 구하기

하지만 순수 자바스크립트는 아래와 같이 함수를 만들었다.

function getDateBefore(days) {
    var d = new Date();
    d.setDate(d.getDate() - days);
    return d.toISOString().substring(0, 10);
}

하지만 위의 코드는 문제가 있었다. ISO String 함수가 로컬시간(KST)가 아닌 UTC 기준의 날짜를 돌려주어 9시 이후에야 지역시간에 맞는 날짜가 반환되었다. 결국 아래와 같이 수정하였다.

function getDateBefore(days) {
    var d = new Date();
    d.setDate(d.getDate() - days);
    return d.toLocaleString().substring(0, 10); // toString() 는 'Sun Oct 25 2020 12:58:05 GMT+0900 (GMT+09:00)' 이다.
}

하지만 실제 수행된 결과를 보니 예상과는 달리 아래와 같이 날짜가 생성되었다.

7/26/2020

결국 formatDate을 할 수 있는 함수를 도입했다. 출처: stackoverflow

function formatDate(date) {
    var d = new Date(date),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

    if (month.length < 2) 
        month = '0' + month;
    if (day.length < 2) 
        day = '0' + day;

    return [year, month, day].join('-');
}

function getDateBefore(days) {
    var d = new Date();
    d.setDate(d.getDate() - days);
    return formatDate(d);
}

keep-alive 설정

node.js 개발하는 분들은 axio 같은 http client 라이브러리를 썼을 테지만, Vanilla JS 지향으로 인한 제약으로 기본 노드에 포함된 http / https 모듈을 이용해야 했다.

테스트를 하다보니 기본 http client가 connection을 keep-alive가 아닌 close 로 동작한다는 것을 알게되었다.

공식 레퍼런스 문서에보니 Agent를 설정하는 것으로 예제가 나와 있었다. 하지만 이 방법은 동작하지 않았다.

const agent = new http.Agent({
  keepAlive: true,
  keepAliveMsecs: 1000
});
 
const req = http.request({
            agent: agent, // 하지만, 이 방법은 실제로 동작하지 않았다.

위와 같이 keepAlive를 true로 넣어주었지만 Response Header에 보니 설정을 하지않았을 때와 마찬가지로 "connection": "close"로 응답되었다.

 

오히려 방법은 요청 헤더에 아래 라인을 넣어주면 동작했다.

const req = http.request({
            hostname: HOST_NAME,
            port: PORT,
            path: `/cleansing`,
            method: 'DELETE',
            headers: {
                'Accept': 'application/json;charset=UTF-8',
                'Connection': 'Keep-Alive', // 여기!
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(deleteData)
            },
            agent: false
        }, (res) => {

문제는 CPU 사용 시간에 따른 과금을 하는 AWS Lambda의 경우 분리했다. 왜냐하면 keep-alive를 하면서 애플리케이션 런타임이 더 길어진다는 것을 확인했기 때문이다. 만약 연결을 한번만 하는 경우에는 오히려 과금이 더 될 수 있다.

애플리케이션이 여러번의 connection을 해야 하는 경우에만 keep-alive가 장점을 줄 수 있다는 결론을 내렸다.

HTTP Delete (or Post)

또한 삭제하는 과정도 약간의 시행착오를 겪었다.

바로 위 코드에 적혀있지만 처음에는 Content-Length를 지정해주지 않았다.

그랬더니 올바른 HTTP Delete 요청이 아닌 요청이 수행되었다.

비단 Delete 뿐만 아니라 요청 content가 있는 경우(예. HTTP Post)도 마찬가지였다.

자세한 것은 Updating post http request length in node.js를 참고.