새소식

AWS

AWS Lambda 를 이용하여 CloudFront Cache 무효화 처리하기

  • -

AWS Lambda 를 이용하여 CloudFront Cache 만료 처리하기

AWS S3 와 CloudFront 를 사용하여 정적 웹을 호스팅 할 수 있습니다.

정적 컨텐츠를 저장하는 스토리지로 S3 를 사용하고, CDN 서비스로는 CloudFront 를 사용하여 정적 웹 호스팅을 구성합니다. 이러한 구성은 컨텐츠 보안 유지 및 컨텐츠 배포 상향시킵니다.

 

위 구성에서 S3에 저장된 동일한 이름의 정적 컨텐츠가 변경될 경우 CloudFront에 저장된 Cache 를 만료시켜야 변경된 최신 컨텐츠를 사용자에게 제공할 수 있습니다.

 

이 글에서는 Lambda 를 사용하여 S3에 저장된 컨텐츠가 변경될 경우 CloudFront의 Cache 를 만료시키는 방법에 대해 알아봅니다.

Lambda 함수에서 사용한 runtime 은 Node.js 18 이며  18버전 부터는 AWS SDK 3버전만 지원합니다.

 

 

Architecture

 

 

 

 

CloudFront 는 Origin 으로 설정된 S3의 컨텐츠를 Cache 처리하여 사용자에게 제공합니다.

제공되는 컨텐츠에 변경(S3 에 새로운 컨텐츠로 업로드)이 생기면 CloudFront 의 캐시를 만료 후 새롭게 업로드된 컨텐츠로 Cache 처리가 필요합니다.

이 예제에서는 S3 에 객체 생성 이벤트 트리거로 CloudFront Cache 를 만료시키는 Lambda 함수를 호출하여 자동으로 사용자에게 최신의 컨텐츠를 제공하도록 구성합니다.

 

개발환경에 Node.js 설치

구성하려는 Lambda runtime 버전과 동일하게 Local PC 에 Node.js 18 버전을 설치합니다.

설치된 node.js 버전 확인

 

 

 

NPM 설정

개발환경에 작업 폴더 생성 후 Node Package Manager 를 설정합니다.

npm 설정

 

 

 

 

npm init 으로 생성된 package.json 파일

 

 

 

 

 

Node.js 용 AWS CloudFrontClinet SDK 설치

아래 링크로 이동해서 개발 환경에 맞게 CloudFrontClient를 설치합니다.

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudfront/

 

AWS SDK for JavaScript v3

 

docs.aws.amazon.com

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudfront/

 

 

 

npm install @aws-sdk/client-cloudfront

 

 

 

 

 

 

 

index.js 파일 생성 및 코드 작성

아래 url 에서 CloudFrontClient - CreateInvalidationCommand Operation 의 Example Syntax 를 참고하여 index.js 파일을 생성합니다.

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudfront/

 

AWS SDK for JavaScript v3

 

docs.aws.amazon.com

 

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudfront/

 

 

 

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cloudfront/command/CreateInvalidationCommand/

 

 

 

 

아래 코드로 index.js 파일을 생성합니다.

'use strict';
const { CloudFrontClient, CreateInvalidationCommand } = require("@aws-sdk/client-cloudfront"); // CommonJS import
const client = new CloudFrontClient();

exports.handler = async (event, context, callback) => {

    //요청 Parameter 
    let timestamp = new Date().getTime();
    let input = { // CreateInvalidationRequest
        DistributionId: "E2FG7I3YDTRZW0", // cf-id
        InvalidationBatch: { // InvalidationBatch
            Paths: { 
                Quantity: 1, 
                Items: [ // PathList                    
                    encodeURI("/img/aws.png")
                ]
            },
            CallerReference: timestamp.toString() // required
        },
    };

    //CloudFront Invalidation 요청 생성
    let command = new CreateInvalidationCommand(input);
    
    //CloudFrontClient 요청 수행 및 결과
    let response = await client.send(command);
    
    //응답 결과 출력
    console.log(JSON.stringify(response));
    
    callback(null, `cf-invalidation`);
};

 

index.js 파일을 포함하여 생성한 Package 를 zip 파일로 압축합니다.

생성한 package 를 zip 파일로 압축

 

 

 

 

Lambda 생성 및 테스트 이벤트

Lambda 함수를 생성합니다.

lambda 함수 생성

 

 

 

 

 

생성된 람다 함수에 zip 으로 압축한 package 를 upload 합니다.

nodejs package upload

 

 

 

 

 

생성된 Lambda 함수에 적용된 role에 CloudFront 에 대한 CreateInvalidation Action 을 추가합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:ap-northeast-2:<your-account-id>:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:ap-northeast-2:<your-account-id>:log-group:/aws/lambda/cf-invalidation-lmb:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudfront:CreateInvalidation"
            ],
            "Resource": [
                "<your-cf-arn>"
            ]
        }
    ]
}

 

 

 

 

Lambda 테스트 이벤트를 생성합니다.

테스트 이벤트 생성

 

 

 

테스트 이벤트를 실행하여 작성한 코드가 정상 동작 하는지 확인합니다.

테스트 이벤트 성공

 

 

 

 

CloudFront Cache 무효화 확인

변경전 이미지를 확인합니다.

변경전 이미지

 

 

 

S3 에 동일한 파일명으로 새로운 컨텐츠를 업로드 합니다.

동일한 경로에 동일한 파일명으로 업로드

 

 

 

Lambda 함수를 실행합니다.

Lambda 함수 실행

 

 

 

 

 

CF 무효화 요청이 처리 되었는지 확인합니다.

CF 무효화 처리완료

 

 

 

 

CloudFront Cache 무효화처리가 완료되어 새롭게 업로드한 컨텐츠가 제공되는지 확인합니다.

새롭게 업로드한 이미지가 제공됨

 

 

 

 

Lambda 함수 호출을 통해 CloudFront Cache 무효화가 정상 처리됨을 확인하였습니다.

 

 

S3 파일 업로드시 자동으로 CloudFront Cache 무효화 처리하기

이번에는 CloudFront Cache 무효화 처리를 자동화 해보겠습니다.

S3 파일 업로드 이벤트가 발생하면 Lambda 함수가 호출되어 CloudFront Cache 무효화를 처리하게 됩니다.

 

Lambda 함수를 아래와 같이 수정하여 배포합니다.

'use strict';
const { CloudFrontClient, CreateInvalidationCommand } = require("@aws-sdk/client-cloudfront"); // CommonJS import
const client = new CloudFrontClient();

exports.handler = async (event, context, callback) => {

    //요청 Parameter 
    let paths =[];

    event["Records"].forEach(items => {
        let key = items["s3"]["object"]["key"];

        if (key.endsWith("index.html")){
            paths.push("/" + key.slice(0, key.length - 10));
        } else {
            paths.push("/" + key)
        }        
    });
    
    let timestamp = new Date().getTime();
    let input = { // CreateInvalidationRequest
        DistributionId: "E2CWYO03NUQKOG", // cf-id
        InvalidationBatch: { // InvalidationBatch
            Paths: { 
                Quantity: paths.length, 
                Items: paths
            },
            CallerReference: timestamp.toString() // required
        },
    };

    //CloudFront Invalidation 요청 생성
    let command = new CreateInvalidationCommand(input);

    //CloudFrontClient 요청 수행 및 결과
    let response = await client.send(command);
    
    //응답 결과 출력
    console.log(JSON.stringify(response));
    
    callback(null, `cf-invalidation`);
};

 

 

생성한 Lambda 함수에 S3 트리거를 추가해줍니다.

트리거 추가

 

 

정적 컨텐츠가 업로드 될 S3 버킷을 선택하고 Event Types 은 'All object create events' 를 선택합니다.

트리거 구성

 

 

 

트리거 구성을 완료합니다.

S3 트리거 추가 완료

 

 

 

 

 

 

 

현재 이미지를 확인합니다.

현재 제공되고 있는 컨텐츠

 

 

 

S3 에 동일한 경로에 동일한 파일명으로 정적 컨텐츠를 업로드 합니다.

동일한 경로에 동일한 파일명으로 업로드

 

 

 

 

 

CF 무효화가 처리되었는지 확인합니다.

CF 무효화 처리 완료

 

 

 

 

 

CloudFront Cache 가 무효화가 완료되었고 새롭게 업로드된 컨텐츠가 Cache 제공됩니다.

새롭게 업로드된 컨텐츠가 제공됨

 

 

 

 

결론

 S3 이벤트 트리거를 이용하면 사용자의 개입 없이 CloudFront 의 오리진으로 구성된 S3의 오브젝트가 변경(모든 객체 생성 이벤트)을 감지하여 Lambda 함수를 실행하여 업데이트된 파일에 대해서만 CloudFront Cache 를 무효화 처리하게 됩니다.

 

 

Lambda 할당량 및 파일 무효화 요금은 아래 링크에서 확인 가능합니다.

 

Lambda 할당량

https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/gettingstarted-limits.html

 

Lambda 할당량 - AWS Lambda

Lambda 문서, 로그 메시지 및 콘솔은 약어 MB(MiB 대신)를 사용하여 1,024KB를 나타냅니다.

docs.aws.amazon.com

 

파일 무효화 요금 및 요청 최대값

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html#InvalidationLimits

 

파일 무효화 - Amazon CloudFront

아직 진행 중인 무효화를 복사하고 무효화 경로의 목록을 업데이트하여 업데이트된 무효화를 실행하는 경우, CloudFront에서는 복사한 무효화를 중단하거나 삭제하지 않습니다. 무효화 경로가 원

docs.aws.amazon.com

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.