클라우드/AWS

[Mac OS]서버리스 어플리케이션 (Lambda, API Gateway, S3, Thumbnail, 자동화, SNS 알림)

chanstory 2023. 2. 7. 22:32
반응형

Bare Minimum Requirements

  • 이미지가 업로드되면, 원본과 별도로 썸네일을 생성하고, 이를 별도의 버킷에 저장해야 합니다.
    • 썸네일 이미지는 가로 200px의 크기를 가집니다.
    • 썸네일을 저장할 별도의 버킷은 람다 함수의 환경 설정으로 구성되어야 합니다.
  • 썸네일 생성이 완료되면, 메일로 해당 썸네일 URL과 함께 전송이 되어야 합니다.
    • Amazon SNS를 활용합니다.
  • 아래 과제 제출 방법을 참고해 GitHub에 제출합니다.

 

Homebrew 사전 설치가 필요하다 (MacOS 기준)

참고 링크

https://brew.sh/

 

Homebrew

The Missing Package Manager for macOS (or Linux).

brew.sh


1. Quick Start Template 를 이용해 Standalone Function을 생성한다

- sam init

 

 

- 입력한 프로젝트 이름으로 생성된 디렉토리 확인

- cd <프로젝트 이름>

 

 

 

2. Lambda 함수의 파라미터를 정의한다

- Lambda Handler 내 함수를 수정함

- event, context 를 CloudWatch 에서 확인하고자함

exports.helloFromLambdaHandler = async (event, context) => {
    console.log(event)

    console.log(context)

    return 'Hello from Lambda!';
}

 

 

3. sam build 와 sam deploy -g 명령어 를 통해 빌드 & 배포 진행

- sam build  ==> .aws-sam 폴더 생성 (안에 build 폴더 생성됨)

 

- sam deploy -g    (-g 옵션은 이후부턴 안붙여도 됨 -- samconfig.toml 파일을 통해 같은 조건으로 배포됨)

 

 

4. Lambda 내 함수 생성 확인

 

5. S3 버킷 생성

 

6. Lambda 내 S3 트리거 추가

7. S3 내 .jpeg 파일 업로드 후 Cloud Watch log 확인 

=> CloudWatch -> 로그 -> 로그그룹 -> 로그스트림 -> event, context 로그 확인

파일 업로드
정보 보안을 위해 잘라서 업로드

 

8. 썸네일 저장을 위한 별도 S3 생성

- 원본 사진 저장 버킷과 같이 생성하지만 ACL 활성화 해야함

 

 

9. 썸네일 저장

- Mac Os M1 사용 시  package.json 내 코드 수정

- 아래 코드를 기존 코드에 삽입

- 람다 함수가 잘 실행되려면 npm dependency로 sharp 모듈이 필요한데 npm install 명령을 통해서 관련 모듈을 설치함

"dependencies": {
  "aws-sdk": "^2.1111.0"
},
"scripts": {
  "preinstall": "npm install --platform=linux --arch=x64 --no-save sharp"
}

 

- 제공받은 소스코드 활용 (hello-from-lambda.js 코드에 적용)

// 원본 버킷으로부터 파일 읽기
const s3Object = await s3.getObject({
  Bucket: 원본_버킷_이름,
  Key: 업로드한_파일명
}).promise()

// 이미지 리사이즈, sharp 라이브러리가 필요합니다.
const data = await sharp(s3Object.Body)
    .resize(200)
    .jpeg({ mozjpeg: true })
    .toBuffer()

// 대상 버킷으로 파일 쓰기
const result = await s3.putObject({
  Bucket: 대상_버킷_이름, 
  Key: 업로드한_파일명과_동일,
  ContentType: 'image/jpeg',
  Body: data,
  ACL: 'public-read'
}).promise()

 

 

- 작성한 코드

/**
 * A Lambda function that returns a static string
 */
/*
exports.helloFromLambdaHandler = async () => {
    // If you change this message, you will need to change hello-from-lambda.test.js
    const message = 'Hello from Lambda!';

    // All log statements are written to CloudWatch
    console.info(`${message}`);
    
    return message;
}
*/

const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
const sharp = require('sharp');

exports.helloFromLambdaHandler = async (event, context) => {
    console.log(event);
    console.log(context);

    const bucket = event.Records[0].s3.bucket.name;      // 원본 버킷 이름
    const key = event.Records[0].s3.object.key;          // 원본 버킷 키

    console.log(bucket);
    console.log(key);

    const dstBucket = 'photo-sam-bucket-test-resize'     // 썸네일 버킷 이름

    // 원본 버킷으로부터 파일 읽기
    const s3Object = await s3.getObject({
        Bucket: bucket,
        Key: key
    }).promise()

    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body) 
        .resize(200)
        .jpeg({ mozjpeg: true })
        .toBuffer()

    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
        Bucket: dstBucket,
        Key: key,                                       // 원본 버킷 키와 동일
        ContentType: 'image/jpeg',                      // 컨텐츠 타입
        Body: data,
        ACL: 'public-read'
    }).promise()
    

    return result;
}

 

 

- 원본 버킷에 .jpeg 업로드 시 200픽셀로 resize 된 썸네일 파일이 다른 resize 버킷에 저장됨

 

 

 

10. Amazon SNS 를 통한 e-mail 알림 

- 썸네일 URL 함께 전송해야함 - 코드 수정 후 재 빌드 및 배포 (sam build, sam deploy)

/**
 * A Lambda function that returns a static string
 */
/*
exports.helloFromLambdaHandler = async () => {
    // If you change this message, you will need to change hello-from-lambda.test.js
    const message = 'Hello from Lambda!';

    // All log statements are written to CloudWatch
    console.info(`${message}`);
    
    return message;
}
*/

const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
const sharp = require('sharp');

const REGION = "ap-northeast-2"
const snsClient = new aws.SNS(REGION)

exports.helloFromLambdaHandler = async (event, context) => {
    console.log(event);
    console.log(context);

    const bucket = event.Records[0].s3.bucket.name;
    const key = event.Records[0].s3.object.key;

    console.log(bucket);
    console.log(key);

    const dstBucket = 'photo-sam-bucket-test-resize'

    // 원본 버킷으로부터 파일 읽기
    const s3Object = await s3.getObject({
        Bucket: bucket,
        Key: key
    }).promise()

    // 이미지 리사이즈, sharp 라이브러리가 필요합니다.
    const data = await sharp(s3Object.Body) 
        .resize(200)
        .jpeg({ mozjpeg: true })
        .toBuffer()

    // 대상 버킷으로 파일 쓰기
    const result = await s3.putObject({
        Bucket: dstBucket,
        Key: key,
        ContentType: 'image/jpeg',
        Body: data,
        ACL: 'public-read'
    }).promise()

    const snsService = {
        TopicArn: '<SNS Arn 직접 입력>',
        Subject: "Creating a Successful Thumbnail",
        Message: `https://${dstBucket}.s3.ap-northeast-2.amazonaws.com/${key}`
    }

    const value = await snsClient.publish(snsService).promise();

    console.log('Send a successful thumbnail link')   
    

    return value;
}

 

- AWS SNS 생성

 

- 생성된 SNS 주제 내 구독 생성

 

 

- 프로토콜 = 이메일, 엔드포인트 = 이메일 입력

 

 

- 이메일 확인하여 구독 확인 하여야함 꼭!! - 링크 눌러서 꼭 컴펌 하기

 

 

- 대상추가 - Amazon SNS

 

- 버킷 내 사진 업로드 & 썸네일 생성 확인 & e-mail 링크 확인 

 

- 링크 접속하여 업로드 한 .jpeg 파일 정상 출력 확인

 

트러블슈팅

 

#1. sam deploy -g 오류 2가지

Error: Failed to create managed resources: An error occurred (InvalidClientTokenId) when calling the CreateChangeSet operation: The security token included in the request is invalid.

 

*** root 의 액세스 키를 설정하면 해결되지만 위험한 행동임

=> IAM 권한 오류라 AWS_ACCESS_KEY_ID  AWS_SECRET_ACCESS_KEY를 재설정 해주었다.

(aws configure 로 키를 먼저 확인함

  export AWS_ACCESS_KEY_ID=********

  export AWS_SECRET_ACCESS_KEY=*******    이 두줄 명령어 실행으로 바꿈)

 

아래 오류도 권한 설정으로 해결함

 

 

#2. s3 is not defined

- S3에 .jpeg 를 삽입한 후 썸네일 파일이 생성 되지 않음

- hello-from-lambda.js 코드 내 S3 객체 선언 추가 

const aws = require('aws-sdk');

const s3 = new aws.S3({ apiVersion: '2006-03-01' });

 

- 아래 공식문서 참고

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-example.html

 

자습서: Amazon S3 트리거를 사용하여 Lambda 함수 호출 - AWS Lambda

자습서: Amazon S3 트리거를 사용하여 Lambda 함수 호출 이 자습서에서는 콘솔을 사용하여 Lambda 함수를 생성하고 Amazon Simple Storage Service(Amazon S3)에 대한 트리거를 구성합니다. 이 트리거는 Amazon S3 버

docs.aws.amazon.com

 

 

#3. sharp is not defined

- const sharp = require('sharp'); 를 hello-from-lambda.js 에 추가 해줘야함 (맨위에 선언)

- npm install 미실행 후 배포해버림

- scripts 내 npm install sharp 를 통해 sharp 설치 진행됨 (npm install 만 진행 하면 됨)

- 그래도 안되면 mac 의 경우 node_modules 지우고 npm install --platform=linux --arch=x64 --no-save sharp 실행

"scripts": {
        "test": "jest",
        "preinstall": "npm install --platform=linux --arch=x64 --no-save sharp"
    }

 

#4. 해결못한 오류

- 가끔 Cloud Watch에 로그가 안뜸

- 최신 로그에 쌓이지도 않음

- 다 지우고 로그를 쌓으려고 해도 뜨지 않음 

- 갑자기 그럼

 

 

#5. TopicArn or TargetArn Reason: no value for required parameter

- 코드 내 TopicArn 오타 수정

 

 

 

참고링크

https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-publishing.html

 

Amazon SNS 메시지 게시 - Amazon Simple Notification Service

속성 유형 String.Array에 대해 배열을 대괄호로 묶습니다([]). 배열 안에서는 문자열 값을 큰따옴표로 묶습니다. 숫자 또는 키워드 true, false 및 null에는 따옴표가 필요 없습니다.

docs.aws.amazon.com

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/notification-content-structure.html

 

이벤트 메시지 구조 - Amazon Simple Storage Service

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SNS.html#publish-property

 

Class: AWS.SNS — AWS SDK for JavaScript

The modular AWS SDK for JavaScript (v3), the latest major version of AWS SDK for JavaScript, is now stable and recommended for general use. For more information, see the Migration Guide and API Reference. Class: AWS.SNS Inherits: AWS.Service Object AWS.Ser

docs.aws.amazon.com

 

 

반응형