본문 바로가기
★ 프로젝트 + 트러블 슈팅 ★

Lambda@Edge / CloudFront / S3 프로젝트 최종정리 (이미지 파일 관리 개선 프로젝트)

by 리승우 2024. 2. 4.

프로젝트가 모두 완료되었다. 그 내용을 추후에 참고하기 좋게 정리 차, 글을 올리게 되었다.

프로젝트를 진행하며 실제로 작업한 내용은 ★ 프로젝트 + 트러블 슈팅 ★

에 올려두었다.

 

 

작업내용


GCP 서버 디스크에 존재하는 이미지 파일을 AWS S3로 이관

 

구성도


 

 

1. Cloudfront 구성을 의도하고 설계한 이유


기존 GCP 설계구조 상, 서버 Scale-Out의 어려움

 

기존 GCP설계구조상, 이미지를 저장하고 있는 Disk는 단일 서버에 종속적이였음.

이로 인해 추후 이용자가 증가하여 Scale-Out을 고려해야하는 상황이 왔을 때, 이를 시행하기에 까다로운 환경임

그리고, 이미지 조회 및 업로드에 서버 리소스가 온전히 사용되고 있음. 이를 다른 쪽으로 우회시키는 게 운영상 좋다고 판단이 되었음

⇒ 위 이유로, 이미지 서빙 속도개선 및 추후 서버 Scale-Out 시 편리한 환경을 구성시키기 위해 이미지 저장소를 Disk방식이 아닌, AWS S3로 이전시키는 설계를 구상

 

2. CloudFront 도입으로 얻게된 이점


  1. 캐시를 통한 이미지 서빙 속도 개선
  2. signed url을 통한 보안 강화
  3. scale-out에 유리한 환경 구성
  4. 유연한 대응이 가능한 이미지 리사이징 환경 구성

 

3. 버킷 3개로 분리한 이유


 

  • private 버킷
    • 특정 사용자에게만 보여지는 보안이 필요한 컨텐츠 이미지 (ex. 회차 컨텐츠 이미지)
  • public 버킷
    • 위 경우를 제외한 나머지 이미지 (ex. 썸네일, 배너, 이벤트 이미지 등)
  • temporary 버킷
    • 대량업로드 기능의 경우, 서버를 거치지않고 클라이언트에서 바로 s3로 이미지를 업로드 하고있음. 하지만 업로드 중 작업 중단 등의 이슈가 발생할 경우, 해당 데이터를 그대로 사용하는 것은 서비스 운영상 적합하지 않다고 판단. 이를 방지하기 위해 임시 버킷인 temporary에 저장한 후, 정상적으로 업로드가 확인되면 위의 두 버킷으로 이미지를 최종 전달해주기 위한 용도로 사용함 이미지 저장 만료기간 1 day설정

 

4. Lambda@Edge 기능 및 관련 내용 (함수호출 이벤트 , 메모리 관련 팁, 배포 리전, 동작 별 세팅 이유)


Lambda@Edge 구성 내용

 

각 Lambda@Edge 연결 동작 및 연결 이벤트 설정 이유

  • 복호화 람다
    • 연결 동작
      • 보안상 비밀
        • Private 버킷 조회 시, 이미지의 Path 경로를 사용자에게 노출하지 않는 방향을 의도하였음. ⇒ 암호화된 Path를 복호화하는 과정이 필요하여, Private 버킷에 접근하는 동작에 Path 복호화를 하는 해당 Lambda 연결
    • 연결 이벤트
      • Viewer-request
        • 사용자의 응답을 수신하기 전, Path 복호화 작업이 필요하기에 해당 Lambda 연결
  • 리사이징 & 확장자 변환 람다
    • 연결 동작
      • 보안상 비밀
        • S3에는 jpg 확장자로 된 이미지 원본이 존재하고 있음. 그로 인해 이미지를 화면에 맞게 리사이징 해주는 기능이 필요했으며, 파일 크기를 더욱 압축할 수 있는 webp로 확장자를 변환함으로써 데이터를 더욱 빠르게 전송하고자 해당 Lambda 연결
      • 보안상 비밀
        • 위와 동일한 사유로 해당 Lambda 연결
    • 연결 이벤트
      • Origin_response
        • Origin에서 오는 응답을 수신할 때, 이미지 리사이징 및 확장자 변환된 데이터를 받을 수 있게끔 해당 Lambda 연결

 

  • Viewer-request : CloudFront가 최종 사용자의 요청을 수신할 때
  • Origin-request : CloudFront가 오리진에 요청을 전달하기 전
  • Origin-response : CloudFront가 오리진의 응답을 수신할 때
  • Viewer-response : CloudFront가 최종 사용자에게 응답을 반환하기 전

 

리사이징 & 확장자 변환 람다 구성관련 설정

  • 이미지 리사이징 & 확장자 변환 구조를 구성 후, 특정 파라미터로 호출하였을 때 503 ERROR 발생하였음
    • 확인 결과
      • 요청 이미지 용량이 커,Lambda 할당 메모리 초과 OR 제한시간 초과로 인해 발생한 에러

 

  • 해결 내용
    • 요청 처리 시 메모리 및 제한시간 초과 방지를 위해 아래와 같이 메모리 증설 및 제한시간 재설정

 

 

5. Signed Url & pre-signed url


초기 구상은 하나의 s3 버킷에 대해 Cloudfront url을 통해 get과 put을 모두 수행하는 방향으로 진행하였으나

이 경우,

s3:getobject s3:putobject

위 두 정책이 한 버킷에 포함되어 get을 위해 발급된 Cloudfront url로 put도 가능해져버리는 보안 이슈가 발생

따라서 버킷정책에서 s3:putobject를 제외시키고 Cloudfront url은 get을 하기위한 용도로만 사용하도록 수정

pre-signed url

위 보안 이슈를 해결하기 위해, 기존 버킷 정책에 있는 s3:putobject를 삭제 후, Cloudfront를 거치지 않고 안전하게 put 기능을 수행하기위해 pre_signed_url을 사용

→ 만료시간이 설정되어 있고 S3 클라이언트에 미리 인증된 url을 발급받아 파일 업로드 요청

Signed url

  • 보안에 중점을 둔 회차 컨텐츠 이미지 파일들은 url path를 암호화함과 동시에, Cloudfront 퍼블릭키를 사용한 signed url을 생성하여 호출
  • 일반 이미지(썸네일, 배너 이미지 등)는 오버스펙이 될 것을 우려하여 signed url을 사용하지않고 그냥 cloudfront url을 통해 호출

 

 

6. 캐시 쿼리문자열 / 캐시 무효화 설정 / 캐시 기간


캐시 쿼리 문자열 설정내용

 

  • 캐시 무효화 설정
    • 관련 이슈
      • 이미지 업로드 시, 기존에 캐싱되어있는 이미지가 계속 불러와짐으로써 컨텐츠 최신화가 수행되지 않는 문제가 발생함
    • 해결 방법
      • 이미지 업로드 시, 해당 이미지에 관련된 DB 테이블의 수정시간이 최신화 되고 있었음 → 해당 값을 캐시 쿼리스트링인 t에 삽입 이미지 업로드 시 캐시 쿼리스트링 t가 수정되니 기존에 캐싱된 이미지가 아닌 최신화된 컨텐츠가 서빙되게 캐시 무효화 설정을 함
  • 캐시 기간
    • 1년 설정
      • 캐시 쿼리 문자열 t를 사용함으로써 캐시 무효화 및 컨텐츠 최신화를 수행시켜둠
      • w, h, q, f와 같은, 리사이징 & 확장자 변환 람다를 거친 데이터를 미리 캐싱함으로써 빠른 이미지 조회를 가능하게 함. (불필요한 람다 실행이 안되게 함)
      ⇒ 위 이유로 캐시기간(TTL)을 1년으로 설정함

댓글