Infra

S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(5) - Lambda@Edge 배포 셋팅 및 로그 확인

연_우리 2023. 5. 28. 20:45
반응형

 

 

 

 

이 게시글은 시리즈물입니다!
아래 목차를 먼저 확인해주세요

1. Lambda@Edge란?
2. S3, CloudFront 셋팅
3. CloudFront 쿼리스트링 캐시 셋팅
4. IAM 역할 생성
5. Lambda@Edge 배포 셋팅 및 로그 확인
6. 리사이징 로직 작성 및 테스트

 

 

 

 

프로젝트 셋팅

  • serverless framework를 사용하여 람다를 배포할 예정입니다.
  • 이미 존재하는 S3와 CloudFront에 Lambda@Edge를 연결하므로
    serverless-lambda-edge-pre-existing-cloudfront 플러그인을 사용합니다.
 

Serverless Framework: Plugins

The Serverless Framework Plugin Registry. Search thousands of Serverless Framework plugins.

www.serverless.com

링크를 참조해서도 설정할 수 있는데,
CloudFront 배포 구성단계에서 사용하는 "resources: Resources:" 설정을 사용하면
람다를 배포함과 동시에 클라우드프론트도 제거되었다가 새로 생성되는 것 같습니다....
자세한 원인은 모르겠다...

 

 

 

 

 

Serverless 설치

1. 명령어 입력

npm install -g serverless

 

 

프로젝트 폴더 생성

serverless
  • 템플릿 : AWS - Node.js - Starter
  • 프로젝트명 : serverless-lambda-edge-image-resize

서버리스 프로젝트를 만들고나면 아래와 같이 4개의 파일이 생성됩니다.

index.js : 람다에서 수행될 비즈니스 로직이 작성될 파일

serverless.yml : 람다 배포 시 필요한 셋팅 파일

 

 

node 모듈 관리를 위해 npm init 수행

npm init

 

 

 

 

 

 

 

배포 셋팅

람다와 클라우드 프론트가 잘 연결되는지 확인하기 위해 람다에 console.log()만 찍어서 배포해봅니다.

 

 

index.js 수정

serverless.yml파일의 provider.runtime이 nodejs18.x로 되어있다면

index.js에 module.exports.handler, require는 더이상 사용할 수 없습니다.

또한 package.json에 type필드가 module로 지정되어야만 ES6방식으로 처리됩니다.

 

 

1. 링크 참고하여 index.js 수정

2. 어떤 함수인지 명확히 나타내기 위해 함수명 handler → imageResize로 수정

//node 16 : CommonJS 방식
exports.imageResize = async function (event, context) { ~ };

//node 18 : ES6 방식
export const imageResize = async (event, context) => { ~ };

3. 링크 참고하여 package.json에 type:module 추가

//package.json
{
  "name": "serverless-lambda-edge-image-resize",
  "version": "1.0.0",
  "type": "module",
  "description": "<!-- title: 'AWS Simple HTTP Endpoint example in NodeJS' description: 'This template demonstrates how to make a simple HTTP API with Node.js running on AWS Lambda and API Gateway using the Serverless Framework.' layout: Doc framework: v3 platform: AWS language: nodeJS authorLink: 'https://github.com/serverless' authorName: 'Serverless, inc.' authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4' -->",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "serverless-lambda-edge-pre-existing-cloudfront": "^1.2.0"
  }
}

4. 람다함수에 console.log문 작성

실제로 event객체에 어떤 값이 들어오는지 클라우드 워치에서 확인할 예정입니다.

여기에서도 확인할 수 있다.

export const imageResize = async (event, context) => {
    console.log("serverless-lambda-edge-image-resize 실행!");
    console.log(JSON.stringify(event));
    const res = event.Records[0].cf.response;

    return res;
};

 

 

플러그인 설치

  • 명령어 입력하여 설치
npm install --save-dev serverless-lambda-edge-pre-existing-cloudfront

#serverless.yml

service: serverless-lambda-edge-image-resize
frameworkVersion: '3'
plugins:
  - serverless-lambda-edge-pre-existing-cloudfront

provider:
  name: aws
  runtime: nodejs18.x
  region: us-east-1 #lambda@edge는 북미서버에만 등록 가능하다.
  iam:
    role: 'arn:aws:iam::~'

functions:
  imageResize:
    name: 'serverless-lambda-edge-image-resize'
    handler: index.imageResize #index.js 파일의 imageResize 함수를 바라본다
    events:
      - preExistingCloudFront:
          distributionId: E3AICXLJSBYDFW #s3-lambda-edge-image-resize의 cloudfront id값 입력
          eventType: origin-response
          pathPattern: '*'
          includeBody: false
  • provider > iam > role : 람다가 실행될 수 있도록 이전에 만들었던 iam의 arn을 입력합니다.
  • handler > index.Resize : index.js파일의 imageResize함수를 바라보도록 입력합니다.
  • events > preExistingCloudFront
    • distributionId : 이전에 만들었던 cloudfront의 id값을 입력합니다.
    • eventType: origin-response를 입력해두었으니 캐싱처리되지 않은 이미지를 호출할때 람다가 호출됩니다.                              eventType에 대한 더 자세한 내용은 링크를 참조해주세요.

 

 

 

 

 

 

배포

  • 배포 명령어를 입력하고 기다리면 2번째 사진처럼 성공 메시지가 출력됩니다.
serverless deploy

 

  • 버지니아 북부리전 > Lambda > 함수 > serverless-lambda-edge-image-resize

  • 버전 > 최신버전 클릭

 

  • 가장 최신버전에 트리거로 CloudFront가 잡혀있는지 확인

 

 

 

 

 

테스트

F12를 눌러 개발자도구를 켜놓고, 우리가 연결한 클라우드 프론트로 이미지 파일을 호출하면 람다가 수행되는지 확인해봅시다.

* 만약 X-Cache가 Hit from cloudfront로 되어있다면, 클라우드프론트로 한번도 호출하지 않은 이미지 파일을 호출해주세요. 

Miss로 응답받았으니 클라우드워치에서 로그를 확인합니다.

 

 

 

 

 

클라우드워치 로그 확인

제가 가장 해맨 부분 중 하나입니다,... 눈 크게 뜨고 봐주세요

 

 

로그 저장되는 리전 주의

기존에 람다를 사용해보신 분들이라면 람다 함수의 "테스트" 메뉴에 대해 알고계실겁니다.

위처럼 템플릿을 cloudfront-modify-querystring으로 선택하고 테스트버튼을 누르면

실행 성공으로 뜨며 로그를 볼수있는 링크가 나오는데, 해당 로그는 버지니아 리전에 저장된 것을 볼 수 있습니다.

(이벤트 JSON에 있는 uri도 /test로 동일함)

 

 

하지만 CloudFront를 통해 수행된 람다의 로그는... 서울리전에 저장됩니다.

 

생각해보면 당연합니다

람다엣지는 버지니아 리전에 만들어두면 AWS가 전 세계 리전에 자동으로 복사해주고, 

클라우드 프론트는 내 위치에서 가장 가까운 리전에서 실행될테니..

람다엣지도 내 위치에서 가장 가까운 리전에서 실행되겠죠!

 

공식문서 에도 나와있습니다

 

 

Miss와 Hit에 따른 로그 출력 확인

어쨋든 위에서 호출한 /lucy.jpg에 대한 로그가 찍혀있으면 람다가 잘 수행된것입니다.

 

혹시 모르니 다시한번 /lucy.jpg를 호출해봅시다

 

이번엔 Hit이 떴으니 람다가 수행되면 안됩니다. 클라우드 워치에 로그가 찍혔는지 봅시다.

 

Miss일때만 람다가 실행되고, Hit일때는 람다가 실행되지 않는 것을 보니 이벤트 타입에 맞게 잘 동작하네요! 

 

 

 

 

 

 

 

반응형
  • 네이버 블러그 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 구글 플러스 공유하기
  • 카카오톡 공유하기