티스토리 뷰

https://michimani.net/post/development-lambda-edge-for-hugo-hosted-aws 출처

 

이전 글들은 이 글을 쓰기위한 빌드업이 었다.

 

1. AWS S3와 CloudFront 연동 끝까지 가보기

2. WSL/WSL2에 Go(Golang) 설치하기

3. Go + serverless framework로 Lambda 관리하기

4. 꼭 읽어줬으면 하는 AWS Lambda@Edge의 특이 사항들 정리

 

개인적으로는 Lambda@Edge를 시작하기전에 4번은 꼭 훑고 갔으면 좋겠다.

 

1번 글의 마치며에서도 언급한 내용이지만,

 

이미지가 아직 CloudFront(CDN)에 등록되지 않았을 경우 첫 로딩에 문제가 발생할 수 있다.

 

그리고 그 문제는 이미지의 크기가 커질수록, 더 커질 것이다.

 

그래서 이미지의 사이즈를 작게 만드는 과정이 필요하다.

(리사이징이든, 확장자 변환이든 여러가지 방법이 있다)

 

하지만 원본 이미지를 S3에 저장하기 전에 변환하게 되면, 원본 이미지가 손실되기 때문에 문제가 발생할 수 있다.

(서비스 운영 중에는 원본 이미지를 사용해야할 경우가 언제 생길지 모른다)

 

그래서 사용자가 이미지를 업로드하는 아래의 프로세스에서 request 부분은 손댈 수 없다.

 

Lambda Edge가 위치할 수 있는 곳

 

그래서 여기서 손댈 부분은 origin response다.

 

앞으로 할 내용을 요약해보면,

 

1. origin(S3)에서 CloudFront로 응답이 나가는 부분을 캐치

2. 이벤트 정보를 바탕으로 이미지를 가져옴

3. webp 형식으로 변환

4. CloudFront에 base64 형식으로 전달

 

위 방식으로 진행될 것이다.

 

AWS 리소스들은 1. AWS S3와 CloudFront 연동 끝까지 가보기 이 글에서 썼던 것들을 모두 재활용할 것이다.

 

그리고, 앞서 언급한 빌드업이 차례대로 사용될 예정이다.

 

결론적으로 이야기하면 아래와 같은 프로세스로 동작하게 될 것이다.

 

일단 Lambda를 구성해야하므로 serverless.yml부터 작성해보자.

serverless.yml

람다를 수동으로 연결하는 방식도 있다. 하지만 재배포할 때 번거로워지므로 코드베이스로 관리하게끔 했다.

service: edge
frameworkVersion: '3'

plugins:
  - serverless-plugin-common-excludes
  - serverless-plugin-include-dependencies
  - serverless-lambda-edge-pre-existing-cloudfront

provider:
  name: aws
  runtime: nodejs18.x
  architecture: x86_64
  region: us-east-1
  memorySize: 256
  timeout: 10
  logRetentionInDays: 30
  iam:
    role: arn:aws:iam::301591718339:role/test-edge-role

functions:
  imageConverter:
    name: webpConverter
    handler: webpConverter.main
    events:
      - preExistingCloudFront:
          distributionId: E2xxxxx // 대문자로 시작하는 cloudfront id
          eventType: origin-response
          pathPattern: '*'
          includeBody: false

 

플러그인들 중 가장 중요한건 serverless-lambda-edge-pre-existing-cloudfront이다.

 

events에 preExistingCloudFront를 사용할 수 있게 해주는 플러그인이다.

 

매번 수동으로 재배포하기 싫으면 이 기능을 사용하는게 좋다.

 

나머지는 자동으로 불필요/필요한 패키지들을 제외/포함하는 플러그인들이다.

 

모두 설치해주자.

npm install serverless-lambda-edge-pre-existing-cloudfront
npm install serverless-plugin-common-excludes
npm install serverless-plugin-include-dependencies

 

이벤트 처리

코드로 가기전에 이벤트가 어떤형식으로 날아오는지 알아야 데이터를 가져올 수 있다.

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html#lambda-event-structure-response-origin

 

Records[0].cf.request.origin.s3.domainName에서 S3의 경로를 가져올 수 있다.

{
  config: {
    ...
  },
  request: {
    ...
    uri: '/background.png'
  },
  response: {
    ...
    },
    status: '200',
    statusDescription: 'OK'
  }
}

그리고, Records[0].cf.request.uri 에서 파일 이름인 uri를 가져와야한다.

{
  clientIp: '',
  headers: {
    'x-forwarded-for': [ [Object] ],
    'user-agent': [ [Object] ],
    via: [ [Object] ],
    'accept-encoding': [ [Object] ],
    host: [ [Object] ]
  },
  method: 'GET',
  origin: {
    s3: {
      authMethod: 'none',
      customHeaders: {},
      domainName: 'testbed-image-bucket.s3.ap-northeast-2.amazonaws.com',
      path: ''
    }
  },
  querystring: '',
  uri: '/background.png'
}

 

함수 코드

이미지 변환 라이브러리는 sharp를 사용했다. 

 

내 환경은 WSL이기 때문에 아래와 같이 설정

npm install --os=linux --cpu=x64 sharp

window에서 sharp를 사용했으면 배포 전에 위 스크립트나 다른 방법을 통해 node_modules를 수정해줘야 한다.

 

OS에 따라 바뀌는게 있는 것 같다.

 

함수 코드는 GitHub에서 확인하자.

https://github.com/imsosleepy/serverless-lambda/blob/main/edge/webpConverter.js

 

코드는 앞서 언급했듯이 들어오는 이미지를 400x400 webp로 변환해서 base64로 인코딩한 후 reponse에 실어 cloudfront로 보내주는 코드다.

 

결과 화면

 

Response headers를 보면 Content-Type이 webp로 설정된 것을 확인할 수 있다.

 

이미지 크기도 원본 1MB 였는데 154kb로 줄어든 걸 확인할 수 있다.(초기 요청시)

 

GitHub

https://github.com/imsosleepy/serverless-lambda/tree/main/edge

 

마치며 

회사 컨플루언스에 작성한 내용을 각색해서 다시 올린 글이다.

 

완성본은 on-the-fly 방식이지만, 리뷰하는 형식으로 따라만들다보니 내용이 많이 축약됐다.

 

처음에는 Go로 작성했는데, Lamda@Edge에는 Go를 사용할 수 없어 nodejs로 변경했다.

 

솔직히 쿠버네티스가 너무 부담스러워서 빙빙 돌았는데,

 

지인들과 이런저런 이야기를 나눠보니 일단 시작하는게 중요한 것 같다는 결론을 내렸다.

 

이제 쿠버네티스를 진짜 손대야 할 때가 온 것 같다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함