목차
이 게시글은 시리즈물입니다!
아래 목차를 먼저 확인해주세요
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 플러그인을 사용합니다.
링크를 참조해서도 설정할 수 있는데,
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도 플러그인의 가이드대로 수정해줍니다.
#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일때는 람다가 실행되지 않는 것을 보니 이벤트 타입에 맞게 잘 동작하네요!
'Infra' 카테고리의 다른 글
S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(6) - 리사이징 로직 작성 및 테스트 (2) | 2023.05.29 |
---|---|
S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(4) - IAM 역할 생성 (0) | 2023.05.28 |
S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(3) - CloudFront 쿼리스트링 캐시 셋팅 (0) | 2023.05.28 |
S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(2) - S3, CloudFront 셋팅 (0) | 2023.05.28 |
S3, CloudFront, Lambda@Edge를 이용한 이미지 리사이즈(1) - Lambda@Edge란? (0) | 2023.05.28 |