Article
Serverless로 AWS 이미지 최적화 시스템 구축하기
서버리스로 이미지 처리 자동화하기
이미지 최적화는 웹 서비스의 성능과 사용자 경험에 직접적인 영향을 미칩니다. 하지만 대량의 이미지를 처리하는 것은 서버 리소스를 많이 소모합니다.
이 글에서는 AWS 서버리스 아키텍처를 이용해 이미지를 자동으로 최적화하는 시스템을 구축하는 방법을 소개합니다.
프로젝트 목표
이 프로젝트를 통해 배울 수 있는 것들입니다:
- AWS 서버리스 아키텍처 이해: Lambda, S3, API Gateway 등의 서비스 활용
- Serverless Framework 숙달: 인프라를 코드로 관리 (IaC)
- TypeScript 실전 활용: 타입 안정성과 함께 백엔드 개발
- 이미지 처리 파이프라인: 온디멘드 방식의 자동화 시스템
이미지 최적화 아키텍처
3가지 구현 방식
1. 온디멘드 방식 (권장)
사용자 요청 → API Gateway → Lambda → 이미지 처리 → S3 저장 → URL 반환
장점:
- 필요할 때만 처리 (비용 효율)
- 최신 이미지만 처리
- 응답 시간 단축
2. 이벤트 직접 호출
S3 업로드 이벤트가 발생하면 Lambda를 직접 호출합니다.
3. 이벤트 구독 방식
SNS나 SQS를 통해 비동기 처리합니다.
필수 설치 사항
1단계: AWS CLI 설치
# macOS
brew install awscli
# 또는 pip 사용
pip install awscli
2단계: AWS 인증 설정
aws configure
대화형 프롬프트에 다음 정보를 입력합니다:
AWS Access Key ID: [AWS Console IAM에서 발급받은 Key ID]
AWS Secret Access Key: [AWS Console IAM에서 발급받은 Secret Access Key]
Default region name: ap-northeast-2 # 서울 리전
Default output format: json
3단계: Serverless Framework 설치
# 전역 설치
npm install -g serverless
# 또는 프로젝트 로컬 설치
npm install --save-dev serverless
환경 변수 관리 (Optional)
direnv를 사용하면 환경 변수를 편하게 관리할 수 있습니다.
.envrc 파일 생성
export BUCKET_NAME="my-image-bucket"
export ROOT_DOMAIN="example.com"
export SUB_DOMAIN="cdn"
export INFRA_DOMAIN="production"
export AWS_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
export AWS_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
export AWS_DEFAULT_REGION="ap-northeast-2"
export ACM_CERTIFICATE_ARN="arn:aws:acm:..."
direnv 활성화:
direnv allow
이제 이 디렉토리에 들어오면 자동으로 환경 변수가 로드됩니다.
프로젝트 구조
serverless-image-optimizer/
├── src/
│ └── handlers/
│ ├── uploadImage.ts
│ ├── optimizeImage.ts
│ └── getImage.ts
├── serverless.yml
├── tsconfig.json
├── package.json
└── .envrc
Serverless Framework 설정
serverless.yml 예제
service: image-optimizer
provider:
name: aws
runtime: nodejs18.x
region: ${env:AWS_DEFAULT_REGION, 'ap-northeast-2'}
environment:
BUCKET_NAME: ${env:BUCKET_NAME}
functions:
uploadImage:
handler: src/handlers/uploadImage.handler
events:
- http:
path: upload
method: post
optimizeImage:
handler: src/handlers/optimizeImage.handler
events:
- s3:
bucket: ${env:BUCKET_NAME}
event: s3:ObjectCreated:*
rules:
- prefix: uploads/
resources:
Resources:
ImageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${env:BUCKET_NAME}
주요 명령어
패키징
# 배포 전 의존성과 코드를 압축
serverless package
# 또는
npm run package
배포
# AWS에 배포
serverless deploy
# 또는
npm run deploy
배포 완료 후 출력되는 정보:
Service Information
service: image-optimizer
stage: dev
region: ap-northeast-2
endpoints:
POST - https://xxxxx.execute-api.ap-northeast-2.amazonaws.com/dev/upload
functions:
uploadImage: image-optimizer-dev-uploadImage
함수 테스트
serverless invoke local -f uploadImage -d '{"file": "test.jpg"}'
제거
# AWS에서 배포된 리소스 모두 삭제
serverless remove
# 또는
npm run remove
주의사항: sls remove가 안될 때
문제: S3 버킷에 파일이 남아있으면 삭제 실패
해결 방법:
# 1. S3 버킷 비우기
aws s3 rm s3://bucket-name --recursive
# 2. 다시 삭제 시도
serverless remove
실전 예제: 이미지 최적화 Lambda 함수
uploadImage.ts (이미지 업로드 핸들러)
import { APIGatewayProxyHandler } from 'aws-lambda';
import AWS from 'aws-sdk';
import sharp from 'sharp';
const s3 = new AWS.S3();
export const handler: APIGatewayProxyHandler = async (event) => {
try {
const body = JSON.parse(event.body || '{}');
const { filename, base64Data } = body;
// Base64 디코딩
const buffer = Buffer.from(base64Data, 'base64');
// 이미지 최적화 (JPEG로 변환, 품질 80%)
const optimized = await sharp(buffer)
.jpeg({ quality: 80 })
.toBuffer();
// S3에 업로드
const key = `optimized/${Date.now()}-${filename}`;
await s3.putObject({
Bucket: process.env.BUCKET_NAME!,
Key: key,
Body: optimized,
ContentType: 'image/jpeg',
}).promise();
return {
statusCode: 200,
body: JSON.stringify({
success: true,
key,
url: `https://${process.env.BUCKET_NAME}.s3.ap-northeast-2.amazonaws.com/${key}`,
}),
};
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({ error: 'Upload failed' }),
};
}
};
비용 최적화
Serverless를 사용하면:
- 비용: 요청 수와 실행 시간에만 과금
- 스케일링: 자동으로 수평 확장
- 유휴 비용 제로: 실행하지 않으면 비용 없음
비용 예측
- Lambda: 100만 요청당 약 $0.20
- S3: GB당 $0.023 (저장료)
- 데이터 전송: GB당 $0.05
프로젝트 저장소
완전한 예제는 다음 저장소에서 확인할 수 있습니다:
GitHub - serverless-study-image-optimizer
다음 단계
이 기초 위에서 다음과 같이 확장할 수 있습니다:
- 여러 포맷 지원: WebP, AVIF 등 현대적 이미지 포맷
- 이미지 크기별 생성: 썸네일, 중간 크기, 원본 자동 생성
- CDN 통합: CloudFront로 글로벌 캐싱
- 모니터링: CloudWatch 로그와 알람 설정
- 비용 추적: 월별 Lambda 실행 비용 모니터링
마치며
서버리스 아키텍처는 이미지 처리 같은 배치 작업에 최적입니다. 인프라 관리 걱정 없이 비즈니스 로직에만 집중할 수 있습니다.
Serverless Framework를 배우면 AWS의 여러 서비스를 효율적으로 조합할 수 있고, 이는 클라우드 네이티브 개발의 기초가 됩니다.
지금 바로 시작하세요!
댓글