Lambda
•
코드를 실행하여 동작하는 서버리스 컴퓨팅 서비스
•
FaaS (Function as a Service)
•
다양한 런타임을 지원 (Node.js, Python, Java, C#, Ruby, Go 등)
•
필요 시에만 코드 실행
•
사용한 만큼 비용을 지불 (코드를 실행한 횟수와 실행 시간으로 과금)
•
사용량이 늘어나면 자동으로 용량이 확장됨
•
실행당 최대 15분 동안 하도록 구성 (1초에서 15분 사이의 값으로 제한 시간을 설정)
•
동시에 처리가능한 실행 수는 1000건이며 요청을 통해 한도 증가 가능
•
실시간 파일처리 지원
특징
•
독립적으로 사용하지 않고 다른 서비스와 결합하여 사용됨
•
결합 서비스
◦
API Gateway, Kinesis, DynamoDB, SNS, SQS, S3, CloudFront 등
Handler
Handler 실행순서
1. Download your code
Lambda Handler가 실행될 동안 AWS의 내부 인스턴스에 개발자가 작성하고 업로드한 Code를 다운받습니다.
2. Start New Execution Environment
새로운 Execution environment를 생성하는 단계입니다.
execution environment
3. Execute initialization code
Lambda Handler바깥의 전역 코드를 실행하는 단계입니다.
4. Execute handler code
Lambda Handler의 내부 함수 코드를 실행하는 단계입니다.
Lambda Life Cycle
Lambda Life Cycle
1. init 단계
•
Cold Start가 해당 부분에 속합니다. 새로운 실행환경(컨테이너)를 요청하여 준비된 실행환경(컨테이너)가 람다 함수 코드를 다운로드 받고, 사용자가 람다 함수를 생성했을 때 지정해둔 Runtime, Memory, Configuration 등을 세팅하는 과정입니다. 또한, 람다 함수 코드에서 init code부분(라이브러리 및 global 변수 세팅)을 실행합니다.
2. invoke 단계
•
실제 람다 함수 핸들러가 호출되어, 코드가 실행되는 단계입니다. 하나의 Request(Event)에 대한 처리가 완료되면, 람다는 다음 Request(Event)를 처리할 준비를 합니다.
3. shutdown 단계
•
람다 함수 실행을 위해 세팅되어 있던 실행환경(컨테이너)가 죽는 단계입니다. 람다 함수는 일정 기간동안 호출을 받지 않으면 런타임을 종료하고 실행환경(컨테이너)을 제거합니다.
Lambda 통신 과정
Lambda 통신 과정
1. Sequential
•
외부에서 어떠한 요청이 들어오면, Lambda는 새로운 실행환경(컨테이너)을 띄우고, 해당 실행환경에서 람다 함수의 코드를 실행할 수 있도록 이벤트를 발생시킵니다. 이 때, 하나의 컨테이너는 하나의 이벤트만 처리할 수 있으며, 해당 컨테이너가 이벤트를 처리하는 동안 freeze 상태가 됩니다.
이벤트 처리가 완료되면, 해당 컨테이너는 idle 상태가 됩니다.
이때, 아래 2개의 상태가 오래 지속되면 해당 컨테이너는 Shutdown 됩니다.
•
컨테이너가 idle 상태가 오래 지속되면 Shutdown됩니다.
•
요청받은 Request(이벤트)가 오래 지속되면 폐기 후 Shutdown됩니다.
2. concurrent
위에서 언급한 바와 같이, 하나의 실행환경(컨테이너)은 한 번에 하나의 Request(Event)만 처리합니다. 따라서 Request(Event)를 처리하는 동안 해당 실행환경(컨테이너)은 freeze 상태가 됩니다.
•
이 때, 만약 실행환경(컨테이너)들이 전부 freeze상태임에도 불구하고 새로운 Request(Event)가 계속해서 들어오는 경우, 람다는 새로운 실행환경(컨테이너)을 가져오도록 트리거합니다. (즉, 새로운 인스턴스를 생성합니다.)
•
concurrent하게 처리할 Request(Event)들에 대해 실행환경(컨테이너)는 계속해서 생성됩니다.
Lambda의 event와 context 오브젝트
Lambda의 event와 context 오브젝트
•
Lambda 함수를 작성할 때 event와 context객체를 사용할 수 있다.
•
Lambda가 호출될 때 제공하는 기본 파라미터
event 객체 – 다른 AWS 서비스의 데이터
•
event객체는 Lambda 함수에 전달되는 input 데이터이다.
•
이는 다른 AWS 서비스(예: API Gateway, S3, DynamoDB 등)에서 Lambda로 전달되는 정보를 담고 있다.
•
예시
◦
API Gateway에서의 HTTP 요청 정보 (HTTP 메서드 (예: GET, POST))
◦
S3에서의 객체 정보 (S3에 업로드 된 파일 이름, 업로드된 객체의 경로(uploads/file.txt) 등)
◦
DynamoDB Streams 이벤트 (DynamoDB에서 수행된 작업 (INSERT, MODIFY, REMOVE))
[event 예시]
•
API Gateway로 다음과 같은 JSON 형식의 데이터가 들어와서 Lambda에 전달했다
{
"httpMethod": "GET",
"queryStringParameters": {
"name": "elon musk"
},
"body": null
}
JSON
복사
•
API Gateway로 가져온 정보를 event 객체를 통해 Lambda 함수(Python 코드)에서 활용 할 수 있다.
def lambda_handler(event, context):
name = event["queryStringParameters"]["name"] # "elon musk" 추출하여 name 변수에 저장
return {
"statusCode": 200,
"body": f"Hello, {name}!"
}
Python
복사
•
실행 결과 (Output)
{
"statusCode": 200,
"body": "Hello, elon musk!"
}
JSON
복사
context 객체 – lambda의 메타데이터
•
context 객체는 실행하는 Lambda 함수의 자신의 메타데이터(metadata)를 제공한다.
•
메타데이터는 예를 들어, "람다 함수의 이름", "람다의 최대 메모리 사이즈", "람다의 timeout 시간" 등이 포함된다.
•
예시
◦
context.function_name : Lambda 함수의 이름
◦
context.function_version : 함수의 버전
◦
invoked_function_arn : 호출된 Lambda 함수의 ARN
[context예시]
•
Lambda 함수의 실행 정보("함수 이름", "메모리 크기", "요청 ID")를 확인하기
def lambda_handler(event, context):
function_name = context.function_name # 함수 이름 가져오기
memory_limit = context.memory_limit_in_mb # 메모리 제한 가져오기
request_id = context.aws_request_id # 요청 ID 가져오기
return {
"statusCode": 200,
"body": f"Function '{function_name}' with {memory_limit}MB is handling request {request_id}"
}
Python
복사
•
실행 결과 (Output)
{
"statusCode": 200,
"body": "Function 'my_lambda_function' with 128MB is handling request 1234-5678-91011"
}
JSON
복사
Lambda Function URL과 API Gateay 차이점
Lambda Function URL과 API Gateay 차이점
1. 보안
•
API Gateway : 인증, 권한 부여 등 다양한 보안 기능을 제공하여 엑세스 제어를 강화합니다.
•
Lambda Function URL : 직접 호출 가능한 URL이며, 인증과 권한 부여를 추가로 구현하지 않는 한 누구나 접근이 가능합니다.
2. 유연성과 기능
•
API Gateway : 다양한 AWS Resource들을 통하여 다양한 API 키 관리, 요청 및 응답을 반환할 수 있습니다.
•
Lambda Function URL : 단순히 특정 함수를 호출하는 데에만 사용됩니다.
3. 메타데이터 및 분석
•
API Gateway : 요청과 응답에 대한 메타데이터를 추적하고 분석할 수 있습니다. API Gateway는 CloudWatch Logs와 통합되어 API 호출 로그를 수집하고 모니터링할 수 있습니다.
•
Lambda Function URL : 별도의 로깅 설정이나 메타데이터 수집이 이루어지지 않습니다. 따라서 함수 호출 및 성능에 대한 분석이 API Gateway에 비해 어려울 수 있습니다.
Lambda의 로그
Lambda의 로그
•
Lambda 함수를 작성하면 자동으로 Lambda의 특정 항목을 모니터링하여 CloudWatch에 Metrics(로그)로서 기록된다.
•
특정 항목
◦
Request (요청)
◦
Request당 Latency
◦
에러가 된 Request
◦
함수 코드 내 로그 출력: console.log(Node.js), print(Python), System.out.println(Java)
Lambda 실행에 따른 문제점
Lambda 실행에 따른 문제점
1. 새로운 실행환경(컨테이너)을 트리거하고 준비할 때마다 Cold Start를 겪어야 합니다.
•
Lambda 함수마다 concurrent 인스턴스 용량을 할당할 수 있도록 Reserved Concurrency와 Provisioned Concurrency를 설정할 수 있도록 되어있습니다.
2. concurrent하게 띄울 수 있는 실행환경(컨테이너) 수에 Limit이 존재합니다.
•
Region 별 Concurrent Instance 할당량은 1000개에서 시작합니다.
•
AWS Service Quotas을 통해 해당 Limit을 증가시킬 수 있습니다.)
Cold Start
Cold Start
•
AWS Lambda가 요청을 처리하기 위해 인스턴스를 가동해야하는 행위
Colde Start 생기는 이유
Cold Start 생기는 이유
•
Lambda는 5분 동안 사용하지 않을 시 Lambda가 멈추게 됩니다.
•
그 후 Client가 함수 요청 시 Lambda 서버가 가동하는 시간동안 Cold Start 현상이 일어납니다.
Cold Start 해결방법
Cold Start 해결방법
1. Lambda 메모리 늘리기
•
Lambda에 적용되는 메모리를 늘리면 인스턴스의 사양이 올라가면서 처리 속도가 향상됩니다.
•
메모리를 올리면 비용이 증가 할 수 있습니다.
2. Lambda 컨테이너 재사용하기
•
Lambda는 다음 호출이 5분 내에 일어날 경우 원래 사용하던 컨테이너를 재사용합니다.
•
CloudWatch를 통해 5분마다 호출을 하거나 Route53에서 Health Check를 람다 함수 API Gateway Endpoint 로드 설정하는 식으로 다양하게 설정이 가능합니다.
•
5분마다 호출을 한다는건 비용이 증가 할 수 있습니다.
3. 프로비저닝된 동기성 기능 활성화
•
EC2 처럼 람다 함수를 계속 켜둡니다.
•
서버를 계속 켜두고 있으므로 비용이 증가 할 수 있습니다.
프로비저닝된 동시성(Provisioned Concurrency)
4. 프로비저닝 오토스케일
AWS Docs
5. 적절한 런타임을 선택
•
언어마다 처리속도가 다르므로, 가능한 빠른 환경을 실행하는 것이 좋습니다. / Python, Node.js 등
6. 코드를 최적화
7. 초기화 코드를 최소화
•
초기화 시 필요한 작업만 수행하도록 코드 구조를 최적화합니다.
•
불필요한 글로벌 변수나 라이브러리 로딩을 피합니다.
8. 테스트 및 모니터링
•
Lambda 함수의 성능을 지속적으로 모니터링하여, Cold Start가 발생 패턴을 파악하고 이를 기반으로 최적화합니다.
•
AWS CloudWatch를 통해 지연 시간 및 Cold Start 빈도를 확인할 수 있습니다.
9. 여러 리전을 사용
•
트래픽이 높은 Application의 경우, 여러 AWS Region에서 Lambda 함수를 운영하여 부하분산시키고 Cold Start 빈도를 줄입니다.
Lambda Concurrency
Lambda Concurrency
•
함수가 동시에 처리하는 전송 중인 요청의 수
Lambda Concurrency 동작방식
Lambda Concurrency 동작방식
•
각 계정의 Region 단위로 기본 Concurrency 제한값이 있습니다.
•
그 값은 리전별로 다르며, 필요시 별도 요청을 통해 상향(조정)할 수 있습니다.
•
해당 수치를 초과하는 요청은 원칙적으로 Throttling Error(응답코드:429)가 발생합니다.
•
특정 Function(모든 Version의 합) 단위로 설정하는 값입니다.
•
해당 함수는 위 설정값 이상의 동시 요청이 발생하면, 초과분은 수행하지 않습니다.
•
설정한 즉시 적용됩니다.
Lambda Concurrency Practice
Lambda Concurrency Practice
Provisioned Concurrency
•
AWS Lambda 함수를 지속적으로 초기화하며, 런타임 환경을 준비함으로써, 사용자의 요청에 바로 응답할 수 있는 상태로 만들어주는 기술
Invocation Model 종류
Invocation Model 종류
1. Synchronous (Push)
Synchronous
•
트리거를 통해 실행되고 응답을 기다립니다.
•
해당 모델은 Lambda 함수가 즉시 실행됩니다.
•
함수를 실행하면 Lambda Inovoke로 API를 호출합니다.
해당 모델의 대표적인 예로는 API Gateway → Lambda → DynamoDB가 있습니다.
•
CRUD API Gateway에서 API를 노출시켜 DynamoDB 테이블에 데이터를 저장합니다.
•
해당 매개변수를 “RequestResponse”로 지정해야합니다.
2. Asynchronous (Event)
Asynchronous
•
이벤트 모델에 의해 트리거가 실행되며 즉각적인 응답을 기다리지않고 실행됩니다.
•
해당 모델은 Lambda 함수와 이벤트가 함께 동작하여 호출됩니다.
해당 모델의 대표적인 예로는 S3/SNS → Lambda → DynamoDB가 있습니다.
•
S3 Bucket에 데이터가 저장될 때 호출하여 DynamoDB에 저장합니다.
•
해당 매개변수를 “Event”로 지정해야합니다.
Stream (Poll-based)
Stream
•
풀 기반으로 트리거가 동작합니다.
•
해당 모델을 사용하면 AWS Kinesis Data Stream 및 대기열 기반 서비스에 Lambda를 직접 호출하지 않습니다.
•
AWS SQS, Kinesis Data Stream등을 통하여 Lambda 함수를 호출할 수 있습니다.
해당 모델의 예로는 SQS + Lambda가 있습니다.
•
대기열에 레코드가 존재하면 이 대기열 레코드는 Event Bridge, SNS 등을 통하여 lambda 함수를 호출합니다. 호출된 Lambda는 AWS SQS와 같은 서비스를 호출합니다.
Lambda Proxy in VPC
import axios from "axios";
export const handler = async (event) => {
try {
const url = event.requestContext?.http?.path;
const method = event.requestContext?.http?.method;
const query = event.rawQueryString;
const body = event.body;
const headers = event.headers;
if (headers?.host) {
delete headers?.host;
}
if (headers?.["x-forwarded-for"]) {
delete headers["x-forwarded-for"];
}
let routed_url = "";
if (url.startsWith("/proxy_test")) {
routed_url = url.replace("/proxy_test", "https://checkip.amazonaws.com");
} else if (url.startsWith("/naver")) {
routed_url = url.replace("/naver", "https://naver.com");
} else {
return {
statusCode: 403,
body: JSON.stringify({
response: {
body: "NOT ALLOWED",
statusCode: 403,
},
}),
};
}
console.log("routed_url", routed_url);
if (query !== "") {
routed_url = routed_url + "?" + query;
}
const response = await axios({
method: method,
url: routed_url,
headers: headers,
data: body,
validateStatus: function (status) {
return status < 500; // 오직 5xx 상태 코드만 실패 처리
},
});
let statusCode = 200;
if (response) {
statusCode = response?.status;
}
let responseBody = response.data;
if (typeof responseBody === 'object') {
responseBody = JSON.stringify(responseBody);
} else if (typeof responseBody !== 'string') {
responseBody = String(responseBody);
}
return {
statusCode,
headers: {
"Content-Type": response.headers?.["content-type"] || "application/json",
...response.headers
},
body: responseBody,
};
} catch (error) {
console.error("Error in proxy handler:", error);
return {
statusCode: 500,
body: JSON.stringify({
error: error.message || String(error),
stack: error.stack
}),
};
}
};
JavaScript
복사
Lambda boto3 Create Specific EC2 Instance
import boto3
aws = boto3.Session()
ec2 = aws.resource('ec2', region_name="<>") # 현재 리전 이름
tags = [{'Key':'Name','Value': '<bastion-ec2>'}]
ec2_user_data = '''
#!/bin/bash
'''
instance = ec2.create_instances(
IamInstanceProfile={'Name': "IAM 역할 이름"}, # IAM 역할 이름
ImageId='<AMI Image ID>', # AMI Image ID
InstanceType='t2.micro', # 인스턴스 타입
UserData = f"{ec2_user_data}", # 사용자 데이터
TagSpecifications = [{'ResourceType': 'instance', 'Tags': tags}], # 태그
MinCount=1, # 최소
MaxCount=1, # 최대
NetworkInterfaces=[{
'SubnetId': "<>", # 서브넷 ID
'DeviceIndex': 0,
'Groups':["<>"] # 보안그룹 ID
}]
)
print(instance)
Python
복사
Lambda boto3 Delete Specific EC2 Instance
import boto3
region = "" # 리전 이름
key = "" # 태그 KEY
value = "" # 태그 VALUE
instances = []
ec2_r = boto3.resource('ec2', region_name=region)
ec2 = boto3.client('ec2', region_name=region)
for instance in ec2_r.instances.all(): # 특정 태그가 있는 인스턴스 id 가져오기
for tag in instance.tags:
if tag['Key'] == f'{key}': # Key
if tag['Value'] == f'{value}': # Value
instances.append(instance.id)
ec2.terminate_instances(InstanceIds = instances) # 인스턴스 id를 이용하여 인스터스 종료
print('stopped your instances: ' + str(instances))
Python
복사


































