화면에 여러 장의 이미지를 렌더링 해야하는 상황에서 이미지들의 로딩 속도가 느려질 수 있다.
그럴 때 사용할 수 있는 솔루션으로는 썸네일을 만들어서 사용하는 방법이 있다.
여러 이미지의 목록을 보여주어야하는 상황에서는 보통 원본 사이즈의 이미지가 필요하지 않다.
따라서 이미지 크기를 줄여서 사용할 수 있는 것!
썸네일은 여러가지 방법으로 만들 수 있지만,
오늘 알아볼 방법은 S3와 Lambda를 이용하는 방법이다!
Lambda & S3
Lambda
서버리스의 핵심 기능으로 서버를 프로비저닝하지 않고도 그저 코드(함수)만으로 원하는 동작을 작동시킬 수 있는 컴퓨팅 서비스이다.
람다는 이벤트 기반으로 동작한다.
람다함수를 작동시키는 이벤트가 발생하면 등록된 코드를 실행시킨다.
S3
가장 오래된 AWS 서비스 중 하나. 객체 스토리지 서비스로 파일 서버와 같은 역할을 한다. 파일, 이미지를 저장할 수 있고 html 파일을 퍼블릭으로 배포하는데 사용할 수도 있다.
두 서비스를 이용해서 썸네일 이미지를 만드는 과정은 다음과 같다.
1. S3에 이미지 업로드 (put obejct)
2. Lambda 함수 트리거
3. Lambda 함수가 이미지 리사이즈 후 다시 S3에 저장
꽤 간단하다.
서버리스는 간단하지만 획기적인 아이디어같다.
구현 과정
1. 이미지들을 렌더링할 프론트엔드 화면 구성
렌더링 속도를 확인하기 위해서는 이미지를 볼 화면이 필요하다.
람다 실습에 프론트가 굳이 필요하겠냐 싶지만 사실 프론트엔드를 공부해보자는 목적이 더 컸다.
React, Tailwind, Vite를 사용해서 화면을 구현했다.
React 한 줄 후기
간단한 구현이지만 useState, useEffect 리액트 훅을 사용해보고 전역상태 관리에 대해서 이해할 수 있었다.
Tailwind 한 줄 후기
Utility-First CSS 프레임워크이다. 사용하면서 Bootstrap과 유사하다고 느꼈다.
스타일들이 클래스로 정의되어있어서 클래스명을 추가해주어서 css 작성없이 간편하게 스타일을 적용할 수 있었다.
Bootstrap vs Tailwind
Bootstrap은 미리 정의된 스타일 (ex. 버튼 스타일)이 있어 빠르게 디자인을 적용하기 편하다.
Tailwind는 미리 정의된 스타일이 없지만 사용자가 원하는대로 커스텀하는게 더 용이해서 사용자 커스텀 디자인에 더 적합하다.
프론트엔드 소스코드 : https://github.com/HKLeeeee/Front/tree/main/image-resize
2. S3 이미지 업로드를 처리할 백엔드 서버 구성
간단한 작업이기 때문에 S3에 이미지 업로드 하는 작업을 프론트에서 담당하고 서버까지는 만들 생각이 없었다.
하지만 배포까지 해보는 것이 목표였는데, Node 기반 라이브러리(aws-sdk)는 배포용 빌드에서 작동하지 않아 서버를 구성했다.
프론트에서 multipart로 이미지를 받아 S3로 전달하고, S3에서 이미지 목록을 불러오는 두 가지 역할만 담당하면 되기 때문에 가벼운 express로 서버를 구현했다.
(이제 배보다 배꼽이 커지는...)
백엔드 소스 코드 : https://github.com/HKLeeeee/Front/tree/main/image-resize-server
3. Lambda 함수 등록 ⭐️
경험해보고자 했던 핵심 파트이다!
모든 과정은 AWS 문서를 토대로 진행했다.
자습서: Amazon S3 트리거를 사용하여 썸네일 이미지 생성 - AWS Lambda
Amazon S3 버킷 이름은 전역적으로 고유하지만 리소스 기반 정책을 사용할 때는 버킷이 반드시 계정에 속하도록 지정하는 것이 가장 좋습니다. 버킷을 삭제하면 다른 AWS 계정가 동일한 Amazon 리소
docs.aws.amazon.com
먼저 람다 함수를 생성해주어야한다.
런타임은 원하는대로 설정해주어도 된다. 위의 문서와 똑같이 하기위해 Node.js 18.x를 선택했다.
기본 실행 역할 변경 설정을 그대로 두고 진행했다. (기본 Lambda 권한을 가진 새 역할 생성)
기본 권한은 CloudWatch Logs만 포함되어있어 새로 생성된 역할에 LambdaS3Policy 정책을 추가해주어야한다.
다음으로 함수 배포 패키지를 생성하는 단계이다.
로컬에 폴더하나를 만들고
mkdir lambda-s3
cd lambda-s3
index.mjs 파일을 하나 만들어 AWS 문서에 있는 코드를 작성해주었다.
자습서의 코드를 그대로 사용해서는 바로 실행에 실패할 수 있다.
사용할 버킷의 region으로 설정해주고, 추가로 lambda 설정에서 런타임 설정을 확인해주자!
핸들러 정보는 파일의 이름과 핸들러모듈의 이름으로 되어있어야한다.
파일명은 index.mjs로 설정했고, 코드에서 핸들러 함수가 아래처럼 정의했기 때문에 올바른 핸들러 정보는 index.handler가 된다
export const handler = async (event, context) => {
실습할 때 핸들러 정보 default가 index가 아니라 다른 값이 되어있어서 변경해주었다.
(그런데 글을 작성할 때 다시 생성해보니 기본값이 index로 되어있어 당황스럽다. 덕분에 더 자세히 배우긴했다...)
예시 코드는 A bucket에 putObject 이벤트가 발생하면 B bucket에 리사이즈 이미지를 저장하는 코드이다.
권장되는 방법은 아니지만 나는 A bucket에 /images 경로에 pubObejct가 발생하면 /resize 경로에 저장하고 싶었기 때문에 코드를 수정해주었다.
트리거에 prefix를 설정하지 않고 같은 S3 버킷에 저장하게 된다면 lambda가 무한 실행 될 수 있기 때문에 조심해야한다!
또 jpg와 png 확장자가 아닐경우 예외를 발생하는 로직이 있어 더 많은 확장자를 지원하게 수정해주었다.
변경한 코드 : https://github.com/HKLeeeee/Front/blob/main/lambda-s3/index.mjs
이어서 npm 모듈을 설치해주고 zip 파일로 만들어 코드 소스에 업로드해주었다.
npm init
npm install sharp@0.32.6
zip -r function.zip .
마지막으로 트리거를 추가하여 설정을 마무리했다.
잘 설정되었는지 확인하기 위해 테스트를 이용할 수 있다.
s3-put 템플릿을 선택하고 region, bucket-name, arn 등을 바꾸어 테스트를 저장했다.
저장 후 테스트 버튼을 눌러 간편하게 테스트를 진행해볼 수 있고 CloudWatch에서 실행 로그를 확인할 수 있다.
실제로 이미지를 업로드하고 결과를 확인해보았을때 동일한 파일명이지만 images 경로에는 80.6KB, resized 경로에는 12.1KB로 이미지가 저장되어 더 작은 크기의 이미지가 생성되어 저장되는 것을 확인했다.
4. 배포
만든 프로젝트를 배포까지 시도해보았다.
배포url : http://hkfirstbucket.s3-website.ap-northeast-2.amazonaws.com
(사진이 나오지 않는다면 백엔드 서버를 종료한 것...)
프론트엔드는 S3를 이용해서 배포했다. S3 버킷의 정적 웹사이트 호스팅을 이용했다. 간단히 배포를 테스트하는 것이라 CDN까지는 붙이지 않았다.
백엔드는 아래 글을 참고하여 배포했다. webpack, docker를 이용했다.
How to make build for express js (node js) using Webpack and deployment on Docker
A step by step guide with an example
its-amit.medium.com
NestJS를 사용했을때는 nest에서 build를 제공하고 있어 이번에 처음으로 webpack을 사용하여 빌드를 하게된 점이 흥미로웠다.
웹팩은 웹에서 사용되는 모든 자원(assets)을 번들링 해주는 도구입니다. 번들링의 개념은 여러개의 파일 중에 종속성이 존재하는 파일을 하나의 파일로 묶어 패키징을 시키는 과정을 의미합니다.
출처 : https://steemit.com/javascript/@noreco/webpack
람다와 리액트에 꽂혀서 갑자기 시작하게 된 실습이지만 리액트 훅, 웹팩, 서버리스 등 꽤 많은 것을 배울 수 있었다.
(뿌듯 - )
그 중 서버리스 개념이 가장 신기하고 더 활용해보고 싶다!!!!!!
'Programming' 카테고리의 다른 글
Vue.js - data, computed, watch, methods 정리 (0) | 2024.02.25 |
---|---|
20220425 코딩테스트&AI 공부일기 (0) | 2022.04.26 |
conda install error : Retrying with flexible solve. (0) | 2022.03.18 |
remote: Internal Server Error (0) | 2022.03.18 |
객체지향프로그래밍 OOP(object oriented programming) - 1 (0) | 2022.01.21 |