CloudFront Function 을 활용하여 원하는 S3 객체 경로로 라우팅하기

kms·2024년 2월 21일
0

🚀 들어가기 전

현재 배포되어 있는 CloudFront 에는 Custom Domain(image.itthatcat.xyz) 이 적용되어있다. 그리고 S3 와 API Gateway 에 연결되어 있는 상태이다.
Cloudfront 배포 서버로 접근하면 라우팅 경로에 따라 API Gateway(/api/), S3(/ 기본값) 을 바라볼 수 있도록 하였다.

🤔 문제

CloudFront 에는 아무런 Routing 이 적용되어 있지 않아 원하는 이미지를 조회하기 위해서는 버킷 경로를 Path 에 적어야하는 문제가 있다. 이미지를 조회하기 위해 s3 경로에 맞게 적어줘야 한다. 이는 s3 이미지 저장 경로가 조금이라도 바뀌면 요청하는 API 경로도 바꿔야 하는 문제가 있다.

현재 potenday-img-resized 라는 이름의 Budget 하위에 원본 사이즈 크기별 디렉토리가 존재한다.

potentday-img-resized
- 50(directory)
--- 237beb84-eca4-4746-bd9e-19640dd8ccff.jpg(filename)

- 200
--- 237beb84-eca4-4746-bd9e-19640dd8ccff.jp g

- 500
---237beb84-eca4-4746-bd9e-19640dd8ccff.jpg
... 

크기가 width 가 50px 인 이미지를 가져오고 싶다면 `https://image.itthatcat.xyz/50/237beb84-eca4-4746-bd9e-19640dd8ccff.jpg` 로 요청하면 된다.

`https://image.itthatcat.xyz/{directory}/{file_name}` 형태로 s3 의 디렉토리 구조에 맞춰 요청해야한다.

이는 이미지를 조회하는 URI 경로가 S3 디렉토리 구조에 의존적이다. 이는 S3 디렉토리 구조가 조금이라도 바뀌게 될 경우 이미지를 조회하는 URI 경로도 바꿔야 하는 문제가 생긴다.
쉽게 말해 저장된 이미지의 경로가 바뀌면 URI 도 그에 맞게 수정해야하는 문제가 있었다.

✅ 해결

AWS S3 with Cloudfront CDN for different files according to behavior query string

실제로 CloudFront 에서는 관련한 기능을 제공한다. 크게 CloudFront 와 Lambda@Edge 가 존재한다. 나는 치 CloudFront Function 을 사용하여 경로가 아닌 QueryString 을 이용하여 원하는 사이즈의 이미지를 가지고 올 수 있도록 하였다.

경로에는 S3에 디렉토리가 이름이 들어나는 것이 아닌 queryString 으로 사이즈를 줄 수 있도록 하였다.

이전

50/237beb84-eca4-4746-bd9e-19640dd8ccff.jpg

이후

237beb84-eca4-4746-bd9e-19640dd8ccff.jpg?size={weight}

그리고 CloudFront Function 에서는 size 별로 해당되는 s3 디렉토리 경로에 맵핑하여 원하는 이미지를 찾아 반환하도록 한다. 이렇게 된다면 설령 s3 디렉토리 구조가 바뀌었다 하더라고 function 만 수정하면 되기 때문에 클라이언트는 매번 API 경로를 수정할 필요가 없게 된다.

🔍 진행과정

CloudFront 배포 페이지에 가면 좌측에 함수 > 함수생성 버튼을 누른다.

함수의 이름을 입력하고 함수를 실행할 Js Runtime 버전을 선택한다. CloudFront Function Runtime 는 JS 로 동작된다.

함수를 만들고 상세정보에 들어가면 다음과 같다.

생긴 모습이 Lambda Console 화면과 비슷하다. Lambda 와 마찬가지로 함수 코드를 작성하는 부분, 테스트, 그리고 개시(Publish) 하는 부분이 있다.

Publish(개시) 하기 위해서는 Distributaion 을 추가해야한다. 기존에 만들어놓은 CloudFront 자원가 연결해준다.

적용하려고 하는 Cloud Front 와 캐시 동작을 선택한다. 이때 캐시 동작의 경우에는 기존에는 기본 경로로 캐시가 동작되었지만 이제는 쿼리 파라미터로 동작해야하기 때문에 이 부분은 수정이 필요하다. 이 부분은 추후에 다루어 보도록 하겠다.

원하는 S3 이미지 URI 경로로 라우팅 하기 위해 Cloudfunction 에 들어갈 함수를 작성한다.

적용하려고 하는 Cloud Front 와 캐시 동작을 선택한다. 이때 캐시 동작의 경우에는 기존에는 기본 경로로 캐시가 동작되었지만 이제는 쿼리 파라미터로 동작해야하기 때문에 이 부분은 수정이 필요하다. 이 부분은 추후에 다루어 보도록 하겠다.

원하는 S3 이미지 URI 경로로 라우팅 하기 위해 Cloudfunction 에 들어갈 함수를 작성한다.

function handler(event) {
    var request = event.request;
    var uri = request.uri;
    
    const pathSegments = request.uri.split('/')
    const filename = pathSegments[1]
    var size;
    try {
        size = request.querystring['size'].value;
    } catch(err){
        // 기본 사이즈 weight = 200 로 요청
        request.uri = `/200/${filename}`;
        return request;
    }

		const newUri = `/${size}/${filename}`;
    request.uri = newUri;
    return request;
}
  1. 먼저 요청 uri 에 있는 pathname 을 파싱한다. 237beb84-eca4-4746-bd9e-19640dd8ccff.jpg
  2. 이후 querystring 중 size 를 가져온다.
  3. 만약 querystring size 를 파싱하는 과정에 에러가 발생한다면 200 사이즈의 s3 이미지 경로를 가리킬 수 있도록 하는 요청 uri 를 반환한다.
  4. 에러가 발생하지 않는 다면 s3 경로에 맞게 request uri 를 수정하여 반환한다.

함수 작성이 끝나면 저장 후 해당 함수를 개시합니다.
이후 https://image.itthatcat.xyz/237beb84-eca4-4746-bd9e-19640dd8ccff.jpg?size=200 URI 로 요청했을 때 원하는 이미지가 나오는 것을 알 수 있다

cloudfront 를 이용해 라우팅처리를 한 uri : https://image.itthatcat.xyz/200/237beb84-eca4-4746-bd9e-19640dd8ccff.jpg

s3 uri : https://potenday-img-resized.s3.ap-northeast-2.amazonaws.com/200/237beb84-eca4-4746-bd9e-19640dd8ccff.jpg


참고

https://github.com/aws-samples/amazon-cloudfront-functions

0개의 댓글