AWS Lambda 완벽 가이드 | Serverless·API Gateway·DynamoDB·S3·EventBridge
이 글의 핵심
AWS Lambda로 서버리스 앱을 구축하는 완벽 가이드입니다. 함수 작성, API Gateway, DynamoDB, S3, EventBridge, Cold Start 최적화까지 실전 예제로 정리했습니다.
실무 경험 공유: 전통적인 서버를 Lambda로 마이그레이션하면서, 인프라 비용을 80% 절감하고 확장성을 무한대로 확보한 경험을 공유합니다.
들어가며: “서버 관리가 부담돼요”
실무 문제 시나리오
시나리오 1: 트래픽이 급증하면 서버가 다운돼요
EC2 인스턴스가 부족합니다. Lambda는 자동으로 확장합니다.
시나리오 2: 서버 비용이 너무 많이 나와요
24시간 실행되는 서버 비용이 큽니다. Lambda는 사용한 만큼만 과금됩니다.
시나리오 3: 서버 관리가 복잡해요
패치, 보안, 모니터링이 번거롭습니다. Lambda는 AWS가 관리합니다.
1. AWS Lambda란?
핵심 특징
AWS Lambda는 서버리스 컴퓨팅 서비스입니다.
주요 장점:
- 서버 관리 불필요: AWS가 관리
- 자동 확장: 무한 확장
- 사용량 기반 과금: 실행 시간만 과금
- 이벤트 기반: S3, DynamoDB 등과 통합
- 빠른 배포: 코드만 업로드
비용:
- 월 100만 요청: 무료
- 이후: $0.20 / 100만 요청
2. 첫 번째 Lambda 함수
Node.js
// index.js
export const handler = async (event) => {
console.log('Event:', JSON.stringify(event));
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from Lambda!',
input: event,
}),
};
};
Python
# lambda_function.py
import json
def lambda_handler(event, context):
print(f'Event: {json.dumps(event)}')
return {
'statusCode': 200,
'body': json.dumps({
'message': 'Hello from Lambda!',
'input': event
})
}
3. API Gateway 통합
REST API
# serverless.yml (Serverless Framework)
service: my-api
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
functions:
getUsers:
handler: handlers/users.getUsers
events:
- http:
path: users
method: get
cors: true
getUser:
handler: handlers/users.getUser
events:
- http:
path: users/{id}
method: get
cors: true
createUser:
handler: handlers/users.createUser
events:
- http:
path: users
method: post
cors: true
Handler
// handlers/users.js
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, ScanCommand, GetCommand, PutCommand } from '@aws-sdk/lib-dynamodb';
const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
export const getUsers = async (event) => {
const command = new ScanCommand({
TableName: 'Users',
});
const result = await docClient.send(command);
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify(result.Items),
};
};
export const getUser = async (event) => {
const { id } = event.pathParameters;
const command = new GetCommand({
TableName: 'Users',
Key: { id },
});
const result = await docClient.send(command);
if (!result.Item) {
return {
statusCode: 404,
body: JSON.stringify({ error: 'User not found' }),
};
}
return {
statusCode: 200,
body: JSON.stringify(result.Item),
};
};
export const createUser = async (event) => {
const body = JSON.parse(event.body);
const command = new PutCommand({
TableName: 'Users',
Item: {
id: Date.now().toString(),
...body,
createdAt: new Date().toISOString(),
},
});
await docClient.send(command);
return {
statusCode: 201,
body: JSON.stringify({ message: 'User created' }),
};
};
4. DynamoDB 통합
테이블 생성
# serverless.yml
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Users
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
5. S3 이벤트
S3 트리거
functions:
processImage:
handler: handlers/images.process
events:
- s3:
bucket: my-images-bucket
event: s3:ObjectCreated:*
rules:
- suffix: .jpg
Handler
// handlers/images.js
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import sharp from 'sharp';
const s3 = new S3Client({});
export const process = async (event) => {
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = record.s3.object.key;
// 원본 이미지 가져오기
const getCommand = new GetObjectCommand({ Bucket: bucket, Key: key });
const { Body } = await s3.send(getCommand);
// 리사이징
const resized = await sharp(Body)
.resize(800, 600)
.toBuffer();
// 저장
const putCommand = new PutObjectCommand({
Bucket: bucket,
Key: `resized/${key}`,
Body: resized,
});
await s3.send(putCommand);
}
return { statusCode: 200, body: 'Processed' };
};
6. EventBridge (스케줄링)
functions:
dailyReport:
handler: handlers/reports.daily
events:
- schedule:
rate: cron(0 9 * * ? *) # 매일 오전 9시
enabled: true
7. Cold Start 최적화
1. 런타임 선택
provider:
runtime: nodejs20.x # 빠른 Cold Start
# runtime: python3.12 # 느린 Cold Start
2. 메모리 증가
functions:
api:
handler: index.handler
memorySize: 1024 # 기본 128MB → 1024MB
3. Provisioned Concurrency
functions:
api:
handler: index.handler
provisionedConcurrency: 2 # 항상 2개 준비
4. 번들 최적화
// webpack.config.js
module.exports = {
target: 'node',
mode: 'production',
externals: ['aws-sdk'], // AWS SDK 제외
optimization: {
minimize: true,
},
};
8. 실전 예제: 이미지 업로드 API
// handlers/upload.js
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const s3 = new S3Client({});
export const getUploadUrl = async (event) => {
const { filename, contentType } = JSON.parse(event.body);
const command = new PutObjectCommand({
Bucket: 'my-uploads-bucket',
Key: `uploads/${Date.now()}-${filename}`,
ContentType: contentType,
});
const uploadUrl = await getSignedUrl(s3, command, { expiresIn: 3600 });
return {
statusCode: 200,
body: JSON.stringify({ uploadUrl }),
};
};
정리 및 체크리스트
핵심 요약
- AWS Lambda: 서버리스 컴퓨팅
- 자동 확장: 무한 확장
- 사용량 기반 과금: 실행 시간만
- API Gateway: REST API 구축
- DynamoDB: NoSQL 데이터베이스
- S3: 파일 저장소
구현 체크리스트
- Lambda 함수 작성
- API Gateway 설정
- DynamoDB 연동
- S3 이벤트 처리
- Cold Start 최적화
- 모니터링 설정
- 배포
같이 보면 좋은 글
- Cloudflare Workers AI 가이드
- Terraform 실전 가이드
- FastAPI 완벽 가이드
이 글에서 다루는 키워드
AWS, Lambda, Serverless, API Gateway, DynamoDB, S3, Cloud
자주 묻는 질문 (FAQ)
Q. Lambda vs EC2, 어떤 게 나은가요?
A. Lambda는 간헐적 트래픽에 유리합니다. EC2는 지속적 트래픽에 유리합니다. 비용과 관리 편의성을 고려하세요.
Q. Cold Start가 얼마나 걸리나요?
A. Node.js는 100-300ms, Python은 200-500ms, Java는 1-3초입니다. Provisioned Concurrency로 제거할 수 있습니다.
Q. 실행 시간 제한이 있나요?
A. 최대 15분입니다. 더 긴 작업은 Step Functions나 ECS를 사용하세요.
Q. 프로덕션에서 사용해도 되나요?
A. 네, Netflix, Coca-Cola 등 많은 기업에서 사용합니다.