AWS를 이용한 이미지 리사이징(Cloud front, Lambda)

imzzuu·2024년 7월 9일
0

작업 진행 계기

당시, 회사 프로젝트의 경우, 프론트가 S3 버켓에 원본을 직접 올리는 방식으로 진행하고 있었다.
우리 앱의 경우, 핸드폰에서 찍은 원본 사진을 그대로 올리는 경우가 많았고, 고용량 파일을 그대로 저장하고, 게시판, 피드를 볼 때마다 가져오다보니, Data Transfer 비용이 높아졌다.
이 비용을 줄여보고자 이미지 리사이징 작업을 시작하게 되었다.

고민했던 부분들

- 프론트 리사이징 라이브러리에 대한 고찰
프론트에서 저용량 확장자로 변경하거나, 리사이징 등 라이브러리를 사용하는 것도 고려해봤지만, 당시 프론트에서 리사이징 라이브러리를 사용할 때, 간헐적으로 이미지가 돌아가는 이슈가 있었고, 유명한 라이브러리의 issue들을 둘러보았을 때, 안정성을 갖춘 라이브러리를 찾지 못했다.

- Cloud 서비스를 활용하자
프론트에서 리사이징을 진행하지 않는다면, 두가지의 선택지가 있었다.
백엔드 서버를 사용하는 방식과 클라우드 서비스를 활용하는 방식!
결과적으로, 백엔드 측 서버를 띄우지 않고도 리사이징을 할 수 있는 장점이 크다고 생각하여 람다함수를 이용하여 severless하게 동작하도록 결정했다.

- 람다함수를 호출하는 타이밍
처음엔 데이터 동기화 측면에서 프론트에서 람다함수를 직접 호출하여 리사이징 버켓에 저장하고, 응답받은 리사이징 이미지를 사용하는 것으로 진행하였다.
(데이터 동기화 측면에서 안정성이 있다고 판단)

하지만, 어째서인지 람다함수를 직접 호출하여 폼데이터로 이미지를 전달할 경우, 6mb를 넘는 이미지에서 오류가 발생하였다.
기획 측에서 기존의 10mb 제한을 유지하고 싶다는 의견으로 인해 현재 진행방향으로 변경하였다.

리사이징 동작 방식

최종적으로 결정된 리사이징 흐름 방향은 아래와 같다.

  1. 프론트가 S3 원본 버켓에 원본을 업로드
  2. 해당 트리거로 AWS Lambda 함수 호출
  3. 람다함수를 통해 리사이징 후, 리사이징 버켓에 업로드
  4. 이미지를 get 하는 경우, CloudFront로 요청
  5. CloudFront 원본 그룹을 통해 리사이징 버켓 우선 참조, Error의 경우 원본 버켓 참조

원본 그룹 설정 방법

1. CloudFront에서 원본을 2가지 이상 생성
원본 생성 버튼을 클릭해 사용할 S3 객체들을 가져온다.

2. 원본 그룹 생성

  • 원본: 원본들을 추가 후, 원본들을 우선순위 별로 정렬한다.
  • 이름 : 이 원본 그룹에 이름을 설정
  • 장애 조지 기준 : 1순위 원본에서 어떤 error를 받았을 때, 다음 순위 원본을 참조할지 기준을 정한다.

3. Cloud front 동작 편집
Cloud front 동작 편집에서 실제로 동작할 원본 또는 원본 그룹을 위에서 설정한 원본 그룹으로 변경해준다.

람다함수 작성 및 연결

해당 S3 버켓 설정에서 람다함수 트리거를 객체 생성 이벤트로 지정해두고, sharp를 활용해 리사이징을 진행하는 람다함수를 작성 및 생성한다.
warm start로 돌리면, 더욱 빠르게 동작한다!

참고

개선 필요 사항

  • 사진 업로드 후, 리사이징 시간보다 조회가 빠를 경우, CloudFront에서 원본을 먼저 캐싱하면, CloudFront의 기본 캐싱 시간인 24시간동안 원본의 Data를 Transfer한다는 문제가 있다.

    고민했던 해결방식
    가장 빠르게 적용할 수 있던 부분이었던 3번으로 임시 처리를 해두었다.

    1. CloudFront 2개 사용 (이미지 태그의 onError일 경우에만 원본 버켓 CloudFront 사용)
      → 비용적으로 효율적이지 않다고 판단
    2. CloudFront 무효화
      → 프론트에서 원본/리사이징 여부 판단이 어려워 어떤 부분을 무효화 할지가 애매
    3. 이미지 업로드 시, 평균적으로 리사이징이 소요되는 시간만큼 스피너 뷰 추가
  • Data Transfer 비용이 줄어들었지만, CloudFront 비용이 늘어서 앞으로 추이 확인 필요

  • 작업 기간 상, 기존 프론트에서 S3객체에 직접 접근하는 방식을 유지하였지만, S3key 유출 우려 등 보안 문제를 위해서라도 프론트에서 file 객체를 보내고, 백엔드에서 S3에 접근하여 리사이징된 url을 받아 사용하는 것이 좋을 것 같다.

0개의 댓글