AWS-SDK S3 getObject(with lambda)

hs·2023년 1월 9일
1

이전에 lambda에 대한 글을 쓸 때 썼던 간단한 SDK이지만 수정하면서 겪은 일도 있고 나중에 잊을 수도 있다는 생각에 다시 정리해본다.

코드

// import AWS from 'aws-sdk';
const AWS = require('aws-sdk');

const s3 = new AWS.S3();

exports.handler = async (event, context, callback) => {
    try{
        const { id } = event;
        
        const arCategory = id.split(' ');
        
        let bucket, key;
        
        if (arCategory[0] === 'video') {
            bucket = '버켓명';
            key = arCategory[1] + '.arexport';
        }
        if (arCategory[0] === 'makers') {
            bucket = '버켓명';
            key = arCategory[1] + '/' + id + '.arexport';
        }
        
        // console.log(bucket,key)
        
        const params = {
            Bucket: bucket,
            Key: key,
        };
        
        // return params;
    
        return s3.getObject(params, async (err, data) => {
            if (err) {
                err.message = 'Not yet!!!!!!!!';
                return err.message;
                // next(err); // an error occurred
            } else {
                const jsonData = data.Body;
                // 여기 수정 현재는 파일안의 링크 => 파일 자체 링크
                // const jsonText = `https://${params.Bucket}.s3.ap-northeast-2.amazonaws.com/${params.Key}`;
                const jsonText = JSON.parse(jsonData.toString());
                console.log(jsonText);
                if (jsonText) {
                    callback(null, jsonText);
                    return {statusCode: 200, body: JSON.stringify(jsonText)};
                //    res.status(200).json(jsonText);
                } else {
                    return params;
                //    res.sendStatus(400);
                }
            } // successful response
        }).promise();
    }catch(e){
        console.log(e);
    }
}

기능을 간단하게 설명하면 S3에 파일이 업로드 되었는지 체크하는 API이다.

1. 리전 문제

해당 lambda 함수는 최초에 오레곤(us-west-2)에서 작성이 되었고 s3 또한 오레곤에 존재했었다. 하지만 메인 서버는 서울(ap-northeast-2)에 존재 하였고 이에 맞춰 S3를 서울에 새로 생성하니 테스트시 지속적인 에러가 발생하였다.

Error Log

  "errorType": "NoSuchKey",
  "errorMessage": "Not yet",
  "trace": [
    "NoSuchKey: Not yet",
    "    at Request.extractError (/opt/nodejs/node_modules/aws-sdk/lib/services/s3.js:711:35)",
    "    at Request.callListeners (/opt/nodejs/node_modules/aws-sdk/lib/sequential_executor.js:106:20)",
    "    at Request.emit (/opt/nodejs/node_modules/aws-sdk/lib/sequential_executor.js:78:10)",
    "    at Request.emit (/opt/nodejs/node_modules/aws-sdk/lib/request.js:686:14)",
    "    at Request.transition (/opt/nodejs/node_modules/aws-sdk/lib/request.js:22:10)",
    "    at AcceptorStateMachine.runTo (/opt/nodejs/node_modules/aws-sdk/lib/state_machine.js:14:12)",
    "    at /opt/nodejs/node_modules/aws-sdk/lib/state_machine.js:26:10",
    "    at Request.<anonymous> (/opt/nodejs/node_modules/aws-sdk/lib/request.js:38:9)",
    "    at Request.<anonymous> (/opt/nodejs/node_modules/aws-sdk/lib/request.js:688:12)",
    "    at Request.callListeners (/opt/nodejs/node_modules/aws-sdk/lib/sequential_executor.js:116:18)"
  ]
}

해결
S3와 Lambda는 같은 리전에서 사용한다.

2. Timeout (시간 제한)

제일 처음 나왔던 에러메세지는 다음과 같다.

Task timed out after 3.00 seconds

이런 에러 메세지와 함께 함수가 아예 실행되지 않았다.
찾아보니 Lambda의 기본 제한 시간 설정이 3초로 되어 있어 설정한 시간동안 함수가 끝이 나지 않으면 Timeout을 리턴하는 것이였다.

  • 람다 함수의 제한 시간 설정
    - 설정한 시간이 지날 때까지 함수의 실행이 끝나지 않으면 함수는 실패함
    - 함수의 실행이 예상 외로 오래걸리거나 무한로딩되지 않도록 제한 시간이 지나면 실패시킴
  • 발생 원인
    - 원격 API에 연결할 수 없거나 API 호출에 응답하는 데 오래 걸림
    - API 호출 시 소켓 제한 시간 내에 응답을 받지 못함
    - API 호출 시 Lambda 함수의 제한 시간 내에 응답을 받지 못함
    - 네트워크 문제로 인해 재시도 및 중복 API 요청이 발생시

해결

[구성] -> [일반구성] -> [편집] 에 들어가 제한 시간을 늘려주면 된다.

3. try/catch

위와 같이 timeout이 발생했을때에 관하여 찾아보다가 알게된 부분이다.
단순 handler 함수라고 생각하고 기능적인 부분만 생각을 하고 작성을 하였었는데
람다 함수의 성능 개선 부분에서 try/catch를 통해 API가 설정한 제한 시간까지 무한정 기다리지 않게 작성을 해주는 것이 좋다.

[참고] - https://dev.classmethod.jp/articles/lim-lambda-performance/

profile
무엇이든 끝까지 보람차게

0개의 댓글