[AWS] Lambda로 Thumbnail 이미지 자동 생성하기
AWS Lambda로 Thumbnail 자동 생성하기
특정 앱 또는 웹을 사용하다 보면 아래와 같이 썸네일 이미지
를 본 적이 있을 것입니다. 아래와 같은 작은 화면을 제공하는 이미지가 리스트로 나열되는데 고품질의 이미지 파일이라던지 큰 사이즈의 파일이 제공된다면 로딩 속도에서 차이가 발생할 것입니다.
그래서 원본 이미지를 썸네일 이미지로 제작해서 사용합니다. 이 때 썸네일 이미지를 직접 제작해서 업로드 하고 사용할 수도 있지만, 매 번 그럴 수는 없기 때문에 이를 자동화해서 사용하는 것이 좋습니다. 이러한 자동화를 아래와 같은 Flow로 진행해보려 합니다.
위의 그림 처럼 원본 이미지를 S3에 업로드하면 Lambda
에 Trigger를 걸고, Labmda
가 S3에 썸네일 이미지를 만들어서(이미지 리사이징
) 업로드 하는 식입니다.
바로 한번 어떻게 Lambda를 통해서 썸네일 이미지를 만드는지
에 대해서 알아보겠습니다.
IAM 역할 생성
S3FullAccess
와 lambdaFullAccess
를 체크하고 아래의 것도 같이 체크하겠습니다.
처음엔 안만들었는데 Lambda
가 CloudWatch에 Log를 쓰기 위해서는 위의 권한이 필요합니다. 그래서 총 3개의 권한을 역할에 추가해야합니다.
그리고 이름을 적은 후에 역할을 만들겠습니다. (역할을 만들 때는 2개의 권한이었고, 나중에 CloudWatch에 Log를 쓰기 위해서 위의 권한이 필요하다는 것을 알고 다시 권한을 추가해서 총 3개의 권한을 가지고 있습니다.)
Lambda 생성하기
S3 Bucket 2개 생성
S3에 사진 업로드 하기
위와 같이 S3에 사진 업로드를 하면 아래와 같이 CloudWatch
에도 log가 출력되는 것을 볼 수 있습니다.
그리고 Python
으로 Image Resize
하는 코드를 작성해보겠습니다.(소스코드)
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)
그리고 한번 더 사진 업로드를 해보겠습니다. 그러면 아래와 같은 오류를 만날 수 있는데요.
에러를 보면 PIL
module을 찾을 수 없다고 나옵니다. 그래서 해당 모듈을 Docker를 이용해서 설치해보겠습니다.
PIL Module 설치
docker run --name lambda-img -it lambci/lambda:build-python3.8 bash
mkdir -p opt/python
pip install pillow -t opt/python
pip install boto3 -t opt/python
cd opt
ls
exit
docker container cp lambda-img:/var/task/opt/python ./dockerfiledown
위와 같이 Docker를 사용해서 필요한 모듈을 설치하고 해당 컨테이너의 디렉토리를 로컬로 복사하겠습니다. 그리고 복사한 디렉토리를 zip
으로 압축하겠습니다. 이제 설치한 PIL 모듈을 Lambda 계층으로 올려보겠습니다.
Lambda 계층 만들기
그리고 Lambda
에서 계층 생성
을 누르고 zip 파일(PIL 모듈)을 위와 같이 업로드하겠습니다.
그러면 위와 같이 계층이 잘 생성된 것을 확인할 수 있습니다.
그리고 Lambda 함수 아래에 보면 Add Layer
라고 있는데 그것을 누르고 Layer 추가
를 위와 같이 하겠습니다.
그러면 위와 같이 계층이 잘 추가된 것을 확인할 수 있습니다.
S3 파일 업로드 리사이징 확인
모든 세팅이 끝났기 때문에 다시 S3 파일 업로드를 했을 때 람다 함수가 작동해서 S3 버킷에 리사이징 된 파일이 잘 저장되는지 확인해보겠습니다.
위와 같이 429.4KB
크기의 사진 업로드를 하였습니다.
그러면 위와 같이 이미지 사이즈가 129.6KB
로 줄어든 것을 확인할 수 있습니다.
에러 정리
[ERROR] ClientError: An error occurred (404) when calling the HeadObject operation: Not Found Traceback (most recent call last):
중간에 진행하다가 위와 같은 에러를 만났는데요. 원인은.. 버킷 이름이 잘못되어 있었습니다! 그래서 혹시나 진행하다가 위와 같은 에러를 만난다면 버킷 이름이 잘 되어 있는지 확인해보시면 될 것 같습니다!