
1. 개요
AWS의 Lambda Function 을 이용한 Serverless 환경을 구축하는 것은 이제 많이 대중화가 된 것 같습니다.
Lambda Function을 사용하게 되면 서버의 관리 필요성도 없어지고, 사용자가 급격하게 증가할 때 발생하는 문제들도 고민이 줄어들게 됩니다.
CloudFront를 사용하는 경우 Edge Location에서 Lambda@Edge를 사용하여 로직 처리가 가능합니다.
주로 Static 파일들을 서비스하는 CloudFront에 Lambda@Edge를 연결하여, 사용자의 지역과 가까운 Edge Location에서 더욱 빠르게 로직 처리가 가능한 장점이 있습니다. 이 글에서는 CloudFront+S3 환경에서 S3에 저장된 이미지를 Lambda@Edge를 통해서 사용자의 화면에 맞는 사이즈로 리사이즈하는 Lambda@Edge Function을 구성합니다. Lambda@Edge Function 구성과 CI/CD Pipeline 구축 방법에 대해서 알아보겠습니다.
2. 구성 방안
2.1 아키텍처
참고 : https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/lambda-edge.html

Lambda@Edge 가 실행되는 이벤트는 4가지가 있습니다. Origin은 CloudFront에 Cache 될 대상으로 여기서는 S3가 해당됩니다.
● Viewer Request
● Viewer Response
● Origin Request
● Origin Response
이번 구성에서는 Origin Response 이벤트에 Lambda@Edge가 동작하도록 설정하였습니다.
Resize를 할 대상 이미지는 Origin(S3)에 있고, 해당 이미지를 S3에서 Load 하여 Resize 후 CloudFront에 Cache로 저장하게 됩니다.
Cache가 되고 나면, 다음 호출부터는 빠르게 응답할 수 있습니다.
2.2 CloudFront Function vs Lambda@Edge
참고 : https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/edge-functions.html
Lambda@Edge 와 유사한 CloudFront Function이라는 서비스도 있는데요.
CloudFront Function 은 밀리초 미만의 시작 시간을 제공하고, 더 작고 가벼운 함수에 최적화되어있습니다.
최대 메모리 지원과 함수 지속 시간을 고려하여, Lambda@Edge를 사용하게 되었습니다.
큰 이미지 리사이즈 시 함수 지속 시간 제약으로 실행이 제대로 되지 않을 수 있습니다.
Lambda 코드 구성 시 지속시간(timeout)을 30초로 설정하였습니다.
2.3 Lambda@Edge 제약사항
제약사항 리스트는 CloudFront Document에서 가져왔습니다.
• VPC 내부 리소스에 액세스하도록 Lambda 함수 구성
• Lambda 함수 DLQ(Dead Letter Queue)
• Lambda 환경 변수
• AWS Lambda 계층이 있는 Lambda 함수
• AWS X-Ray 사용
• Lambda 예약된 동시성 및 프로비저닝된 동시성
• 컨테이너 이미지로 정의된 Lambda 함수
• arm64 아키텍처를 사용하는 Lambda 함수
• 512MB를 초과하는 임시 스토리지가 있는 Lambda 함수
Lambda@Edge 를 지원하는 언어와 버전은 아래와 같습니다.
• Node.js 16
• Node.js 14
• Node.js 12 이전 버전은 사용이 중지되었고, 12 버전은 곧 중지될 예정입니다.
• Python 3.9
• Python 3.8
CI/CD Pipeline으로 구성할 때 Lambda 함수에서 Import 해야 되는 module들을 Layer로 구성하면 좀 더 쉽게 만들 수 있는데요.
Lambda@Edge 구성할 때는 Lambda 계층(Layer)와 컨테이너 이미지로 Lambda 함수를 정의할 수 없습니다.
Lambda와 비슷한 환경의 컨테이너에서 npm install 을 통해 필요한 모듈들을 설치 후 압축하여 배포하는 방식으로 해결했습니다.
상세한 내용은 CI/CD Pipeline 코드에서 확인하실 수 있습니다.
2.4 Lambda@Edge Resize 코드
Node.js 16버전으로 코드를 구성하였습니다.
w(=width), h(=height), q(=quality), f(=format) 을 파라미터로 사용하여 리사이즈를 합니다.
sharp 모듈의 설치가 필요합니다.


2.5 인프라 구성
인프라의 구성은 terraform 1.2.8 을 이용하였습니다.
디렉토리의 구성은 아래와 같습니다.

2.5.1 Lambda@Edge 구성
Lambda@Edge 는 us-east-1 리전에 구성이 되어야 합니다.
Lambda에서 사용할 Role을 정의하고 할당해 주었습니다.
timeout은 30초로 설정하여 큰 이미지 리사이즈가 가능하도록 했습니다.


2.5.2 CloudFront 구성
origin access identity를 구성하고 CloudFront에 설정합니다.
Lambda@Edge에 전달할 파라미터로 h, w를 설정했습니다.


2.5.3 S3 구성
CloudFront에서 origin access identity를 통해서 접근할 수 있도록 Policy 구성이 필요합니다.

2.6 Gitlab CI/CD Pipeline 구성
Lambda@Edge에서 사용하는 sharp 모듈 설치가 필요합니다.
Lambda@Edge에서 Layer나 container image를 지원하지 않기 때문에
Ubuntu 이미지를 사용한 컨테이너에서 npm install 실행 및 lambda function을 압축하여 deploy 하도록 했습니다.
Alpine 이미지를 사용할 경우 sharp 모듈이 달라서 Lambda@Edge가 제대로 동작하지 않았습니다.
아래의 코드는 .gitlab-ci.yml에 작성합니다.

위와 같이 구성된 코드들을 Gitlab CI/CD Pipeline을 통해서 실행을 하면
lambda_function.zip 파일 생성 후 Terraform으로 인프라 환경을 구성하게 됩니다.
2.7 결과
웹브라우저를 통해서 실행해 보도록 하겠습니다.
w와 h 파라미터로 사이즈를 지정할 수 있습니다.
Cache 되지 않은 요청일 경우에는 Response Header에 “X-Cache: Miss from cloudfront”라고 표시됩니다.
Cache가 된 이후에는 “X-Cache: Hit from cloudfront”를 확인할 수 있습니다.

3. 마무리
지금까지 Lambda@Edge를 통해서 이미지 리사이즈 처리를 해봤습니다.
Lambda보다 제약사항이 많은 관계로 구성이 조금 더 힘들었는데요.
Lambda@Edge를 통해서 최종 사용자와 가까운 영역에서 로직 처리를 하고
CloudFront의 Cache 기능을 이용하기 때문에 더욱 빠른 응답을 받을 수 있었습니다.
글로벌 사용자를 대상으로 하는 시스템이라면 더욱 큰 도움이 될 것 같습니다.

기업명을 두 글자 이상 입력해주세요.
소식을 받아 보시려면 마케팅 정보 활용과 마케팅 정보 수신에 모두 동의해 주셔야 합니다.
제출이 완료되었습니다.
제출이 완료되었습니다.
확인 버튼을 누르시면 자사 홈페이지 홈화면으로 이동됩니다.
요청하신 자료가 이메일로 발송되었습니다.
구독 설정이 저장되었습니다.
잘못된 접근입니다. 정상적인 경로를 통해 다시 시도해 주세요.
검색 중 오류가 발생했습니다. 다시 시도해주세요.
제출에 실패하였습니다.
다시 시도해주세요.
사업자등록번호는 10자리를 입력해주세요.
지원하지 않는 파일 형식입니다.
10MB 이하의 파일만 업로드하실 수 있으며, 최대 10개까지 첨부 가능합니다.
10MB 이하의 파일만 업로드하실 수 있습니다.
파일은 최대 10개까지만 첨부하실 수 있습니다.
업로드 중 오류가 발생했습니다. 다시 시도해 주세요.
파일을 교체하시겠습니까?