현재 진행중인 프로젝트 Shoe-Auction에 상품 및 브랜드 이미지 업로드 기능을 구현하였다. 업로드한 이미지는 AWS S3의 버킷 내에 저장되며 해당 이미지 경로는 각 도메인의 imagePath 필드에 저장되어 클라이언트가 원할 때 이미지를 불러올 수 있다.
하지만 뷰에서 해당 이미지를 썸네일 등의 작은 사이즈로 보여주려 할 때 불필요하게 큰 원본 이미지 파일을 계속하여 요청하는 것은 전송 효율 측면에서 매우 떨어지며 이러한 요청이 늘어날 수록 어플리케이션의 응답속도는 느려질 수 밖에 없다.
따라서 S3에 이미지를 저장할 때 원본 이외에 필요한 사이즈로 리사이징한 이미지를 함께 저장하고 작은 사이즈의 이미지가 필요할 때에는 리사이즈된 이미지를 요청한다면 전송효율을 증가 시킬 수 있다.
🤔 그렇다면 왜 Lambda인가?
AWS Lambda 는 이벤트에 응답하여 코드를 실행 하고 해당 코드에 필요한 컴퓨터 리소스를 자동으로 관리하는 컴퓨터 이다.
이미지 업로드 시 리사이징 작업을 서버의 역할에서 제외하고, AWS Lambda를 통해 처리하게 되면 그만큼 개발자가 서버에 대한 걱정없이 비즈니스 로직에만 집중이 가능하다.
또한 서버에서 한 번의 요청만으로 다양한 사이즈의 이미지를 처리 할 수 있기 때문에 간편하게 이미지를 처리할 수 있다.
💻 AWS 콘솔을 이용해 Lambda 적용해보기!
AWS 콘솔을 이용하여 Lambda를 적용하는 방법을 간단하게 적어보고자 한다.
정책 생성
우선 원본 이미지 버켓과 리사이즈 이미지 버켓의 접근 권한을 포함한 정책을 생성해야 한다.
IAM Management 콘솔의 정책 페이지로 들어가서 정책 생성 버튼을 누른 후 JSON 편집기에 아래의 예시처럼 원본 이미지 버켓에 s3:getObject, 리사이즈 이미지 버킷에 s3:PutObject, s3:PutObjectAcl 그리고 CloudWatch 로그와 관련된 권한을 포함한다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:PutLogEvents",
"logs:CreateLogGroup",
"logs:CreateLogStream"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::shoeauction-brands-origin/*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::shoeauction-brands-thumbnail/*"
}
]
}
역할 생성
그 후 함수에 AWS 리소스에 액세스할 수 있는 권한을 제공하는 실행 역할을 만들어야 한다.
IAM 콘솔에서 역할 페이지를 열고 역할 생성을 선택한다. 신뢰할 수 있는 개체로 Lambda를 선택한 후 이미 만들어 둔 권한 정책을 연결한다.
함수 생성
Amazon S3에 이미지가 업로드 되었을 때 이벤트를 수신하고 이미지를 리사이즈하여 추가로 저장하는 람다함수를 만들어야 한다. Node, Java, Python 등 여러 언어로 람다함수 작성이 가능하며 본 어플리케이션은 자바11로 작성하여 사용하였다.
샘플 Amazon S3 함수 코드 페이지에서 언어별 리사이즈 샘플 코드를 참고할 수 있다. 조금은 장황한 부분들이 있기 때문에 필요한 부분들만 참고하여 작성하면 된다. 진행중인 프로젝트에 적용한 람다 함수는 브랜드 썸네일은 세로 길이 60에 기존 비율 유지로 변경하였으며, 상품 이미즈는 상세 이미지, 썸네일 이미지를 각각 320*200, 560*350 사이즈로 변경하였다.
자바로 작성할 경우 콘솔의 코드 편집기로는 작성이 불가능 하기 때문에 로컬에서 함수를 작성하고 zip으로 빌드하여 따로 업로드 해야한다. 빌드 툴로 gradle을 사용한다면 build.gradle에 아래 내용을 작성해주고 빌드하면 build -distributions 디렉토리에 zip 파일이 생성된다.
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from configurations.runtimeClasspath
}
}
build.dependsOn buildZip
AWS Lambda 콘솔에서 함수 생성을 누르고 함수 이름과 함수 작성시 사용할 언어를 선택한다. 권한은 기존 역할 사용을 체크하고 위에서 생성했던 역할을 선택하여 적용한다. 생성된 함수의 페이지에 들어가서 코드 소스에 빌드된 zip 파일을 등록해야 한다. zip 파일이 10MB를 초과한다면 함수에 직접 업로드가 불가능하므로 S3 버킷에 업로드 후 'Amazon S3 위치'로 지정해주어야 한다. 그리고 마지막으로 런타임 함수의 핸들러를 "[패키지명].[클래스명]::[함수명]"으로 수정해주면 된다.
버킷에 이벤트 알림 등록
마지막으로 원본 이미지가 저장되는 버킷 콘솔에 접속하여 속성-이벤트 알림-이벤트 알림 생성 을 선택한다. 이벤트 이름을 입력하고 이벤트 유형의 '모든 객체 생성 이벤트'를 체크한다. 그리고 가장 아래의 'Lambda 함수'에서 위에서 생성한 함수를 선택하고 저장한다.
❗ 적용 확인하기!
람다 함수 작동을 확인하기 위해 브랜드 이미지를 업로드 해보면 썸네일 버킷에도 리사이즈된 이미지가 저장된 것을 확인할 수 있으며, 아래와 같이 지정한 크기로 이미지가 리사이즈되었다.
람다 함수 작동 시 로깅된 로그들을 확인하고 싶다면 AWS CloudWatch 콘솔의 로그 그룹에서 확인할 수 있으며, 문제가 생겨 정상적으로 작동하지 않을 시에도 로그를 찍어보며 문제가 발생한 원인을 알아낼 수 있다.
원본 이미지 삭제시에 리사이징된 이미지를 함께 삭제하는 경우에도 위와 같은 순서로 권한과 람다 함수, 이벤트 유형을 변경하여 설정하면 쉽게 적용할 수 있다.
💻 참조
docs.aws.amazon.com/ko_kr/lambda/latest/dg/with-s3-example.html