Lambda Function URL을 활용한 개선된 아키텍처

Lambda Function URL을 활용한 개선된 아키텍처

상황

<aside> 🚫

초 단위의 변환 소요 시간으로 인해 이미지 업로드 직후에는 조회 불가한 경우 발생

</aside>

어드민 메뉴 사진 업로드

어드민 메뉴 사진 업로드

해결 방안 모색

변환 작업 속도를 개선하는 방안을 찾지 못해 임시 방편으로 변환이 완료되기 전까지는 원본을 조회하는 방법을 구현하기 위해 삽질하다가, 이미지 사이즈(폭, 높이)를 줄인 이후 포맷을 변환했을 때 획기적으로 시간이 줄어듦을 확인했다

변환 완료 전에 원본 조회

  1. cloudfront function에서 반환할 이미지 데이터 없는 경우 원본 s3 presigned URL 발급 → aws sdk 사용 불가

  2. 람다 함수 맨 처음에 원본을 webp 버킷에 COPY하는 로직 추가

  3. CloudFront 원본으로 Lambda Function URL 지정

    <aside> 💡

    S3 트리거를 사용한 기존 람다는 그대로 유지하고, 변환 완료 전에 원본을 조회하는 로직을 담은 신규 람다 배포

    </aside>


변환 작업 속도 개선 ✅

  1. 원본 사진 용량 제한을 더 낮게 → 사용자 경험을 위해 하는 작업인데, 더 큰 제약을 가하는 역설적인 방안

  2. 람다 메모리 할당량 증가 → 현재 더 이상 높일 수 없음

  3. 변환 품질을 더 낮게 → 속도는 비슷하고, 결과물의 용량만 더 낮아졌다

  4. nodejs + sharp로 구현 → 성능 비슷, 익숙하지 않은 언어로 유지보수 불편

  5. 포맷 변환 전에 리사이징 ✅

    <aside> 🛠

    원본 8.5MB 이미지 기준 500X500px로 줄였을 때 약 3s → 약 500ms

    대부분의 경우 원래 사이즈보다 훨씬 작은 형태로 노출되기 때문에 좋은 방법

    </aside>

    from io import BytesIO
    
    from PIL import Image
    
    image = Image.open(BytesIO(image_data))
    output_buffer = BytesIO()
    image.convert("RGB").save(output_buffer, format="WEBP", quality=80)
    output_buffer.seek(0)
    
    from io import BytesIO
    
    from PIL import Image
    
    image = Image.open(BytesIO(image_data))
    image.thumbnail((500, 500))          <------------------------------------------
    output_buffer = BytesIO()
    image.convert("RGB").save(output_buffer, format="WEBP", quality=80)
    output_buffer.seek(0)
    

속도 개선에 따른 On Demand 변환 도입

<aside>

변환본을 S3에 저장하지 않고, CloudFront로 컨텐츠 조회 요청이 왔을 때 On Demand로 이미지 변환 후 Edge Location에 캐싱

구현 방안