ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AWS] Lambda로 Thumbnail 이미지 자동 생성하기
    Cloud/AWS 2021. 5. 11. 13:12
    728x90
    반응형

    AWS Lambda로 Thumbnail 자동 생성하기

    특정 앱 또는 웹을 사용하다 보면 아래와 같이 썸네일 이미지를 본 적이 있을 것입니다. 아래와 같은 작은 화면을 제공하는 이미지가 리스트로 나열되는데 고품질의 이미지 파일이라던지 큰 사이즈의 파일이 제공된다면 로딩 속도에서 차이가 발생할 것입니다.

     

    스크린샷 2021-05-11 오후 1 09 01

     

    그래서 원본 이미지를 썸네일 이미지로 제작해서 사용합니다. 이 때 썸네일 이미지를 직접 제작해서 업로드 하고 사용할 수도 있지만, 매 번 그럴 수는 없기 때문에 이를 자동화해서 사용하는 것이 좋습니다. 이러한 자동화를 아래와 같은 Flow로 진행해보려 합니다.

     

    스크린샷 2021-05-10 오후 2 51 53

     

    위의 그림 처럼 원본 이미지를 S3에 업로드하면 Lambda에 Trigger를 걸고, Labmda가 S3에 썸네일 이미지를 만들어서(이미지 리사이징) 업로드 하는 식입니다.

     

    바로 한번 어떻게 Lambda를 통해서 썸네일 이미지를 만드는지에 대해서 알아보겠습니다.

     

     

     

    IAM 역할 생성

    스크린샷 2021-05-10 오후 2 54 05스크린샷 2021-05-10 오후 3 00 06스크린샷 2021-05-10 오후 3 00 15

    S3FullAccesslambdaFullAccess를 체크하고 아래의 것도 같이 체크하겠습니다.

     

     

    스크린샷 2021-05-11 오전 10 58 40

    처음엔 안만들었는데 Lambda가 CloudWatch에 Log를 쓰기 위해서는 위의 권한이 필요합니다. 그래서 총 3개의 권한을 역할에 추가해야합니다.

     

     

    스크린샷 2021-05-10 오후 3 02 12

    그리고 이름을 적은 후에 역할을 만들겠습니다. (역할을 만들 때는 2개의 권한이었고, 나중에 CloudWatch에 Log를 쓰기 위해서 위의 권한이 필요하다는 것을 알고 다시 권한을 추가해서 총 3개의 권한을 가지고 있습니다.)

     

     

    Lambda 생성하기

    스크린샷 2021-05-10 오후 3 08 32스크린샷 2021-05-10 오후 3 08 39

     

    S3 Bucket 2개 생성

    스크린샷 2021-05-10 오후 3 16 29스크린샷 2021-05-10 오후 3 17 40스크린샷 2021-05-10 오후 3 22 27스크린샷 2021-05-10 오후 3 23 30스크린샷 2021-05-10 오후 3 23 23스크린샷 2021-05-10 오후 3 28 17

     

     

    S3에 사진 업로드 하기

    스크린샷 2021-05-10 오후 3 32 31

    위와 같이 S3에 사진 업로드를 하면 아래와 같이  CloudWatch에도 log가 출력되는 것을 볼 수 있습니다.

     

     

    스크린샷 2021-05-11 오전 11 05 50

     

     

     

    그리고 Python으로 Image Resize 하는 코드를 작성해보겠습니다.(소스코드)

     

    스크린샷 2021-05-11 오전 11 22 14

    import boto3
    import os
    import sys
    import uuid
    from urllib.parse import unquote_plus
    from PIL import Image
    import PIL.Image
    
    s3_client = boto3.client('s3')
    
    def resize_image(image_path, resized_path):
      with Image.open(image_path) as image:
          image.thumbnail(tuple(x / 2 for x in image.size))
          image.save(resized_path)
    
    def lambda_handler(event, context):
      for record in event['Records']:
          bucket = record['s3']['bucket']['name']
          key = unquote_plus(record['s3']['object']['key'])
          tmpkey = key.replace('/', '')
          download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
          upload_path = '/tmp/resized-{}'.format(tmpkey)
          s3_client.download_file(bucket, key, download_path)
          resize_image(download_path, upload_path)
          s3_client.upload_file(upload_path, '{}-resized'.format(bucket), key)

    그리고 한번 더 사진 업로드를 해보겠습니다. 그러면 아래와 같은 오류를 만날 수 있는데요.

     

    스크린샷 2021-05-11 오전 11 08 04

     

    에러를 보면 PIL module을 찾을 수 없다고 나옵니다. 그래서 해당 모듈을 Docker를 이용해서 설치해보겠습니다.

     

    PIL Module 설치

    docker run --name lambda-img -it lambci/lambda:build-python3.8 bash

    스크린샷 2021-05-10 오후 4 04 20

    mkdir -p opt/python
    pip install pillow -t opt/python
    pip install boto3 -t opt/python
    cd opt
    ls
    exit

    스크린샷 2021-05-10 오후 4 07 08

    docker container cp lambda-img:/var/task/opt/python ./dockerfiledown

    위와 같이 Docker를 사용해서 필요한 모듈을 설치하고 해당 컨테이너의 디렉토리를 로컬로 복사하겠습니다. 그리고 복사한 디렉토리를 zip으로 압축하겠습니다. 이제 설치한 PIL 모듈을 Lambda 계층으로 올려보겠습니다. 

     

     

     

    Lambda 계층 만들기

    스크린샷 2021-05-10 오후 4 24 15스크린샷 2021-05-10 오후 4 25 57

    그리고 Lambda에서 계층 생성을 누르고 zip 파일(PIL 모듈)을 위와 같이 업로드하겠습니다.

     

     

     

    스크린샷 2021-05-11 오전 11 17 04

    그러면 위와 같이 계층이 잘 생성된 것을 확인할 수 있습니다.

     

    그리고 Lambda 함수 아래에 보면 Add Layer라고 있는데 그것을 누르고 Layer 추가를 위와 같이 하겠습니다.

     

    스크린샷 2021-05-11 오전 11 20 45스크린샷 2021-05-11 오전 11 24 13

    그러면 위와 같이 계층이 잘 추가된 것을 확인할 수 있습니다.

     

     

     

    S3 파일 업로드 리사이징 확인

    모든 세팅이 끝났기 때문에 다시 S3 파일 업로드를 했을 때 람다 함수가 작동해서 S3 버킷에 리사이징 된 파일이 잘 저장되는지 확인해보겠습니다.

    스크린샷 2021-05-11 오전 11 58 16

    위와 같이 429.4KB 크기의 사진 업로드를 하였습니다.

     

     

    스크린샷 2021-05-11 오전 11 59 33

    그러면 위와 같이 이미지 사이즈가 129.6KB로 줄어든 것을 확인할 수 있습니다.

     

     

     

    에러 정리

    [ERROR] ClientError: An error occurred (404) when calling the HeadObject operation: Not Found Traceback (most recent call last):  

    중간에 진행하다가 위와 같은 에러를 만났는데요. 원인은.. 버킷 이름이 잘못되어 있었습니다! 그래서 혹시나 진행하다가 위와 같은 에러를 만난다면 버킷 이름이 잘 되어 있는지 확인해보시면 될 것 같습니다!

    반응형

    댓글

Designed by Tistory.