서버리스 파일 처리 앱 만들기
서버리스 파일 처리 앱 만들기
Lambda의 가장 일반적인 사용 사례 중 하나는 파일 처리 작업을 수행하는 거예요. 예를 들어 Lambda 함수를 사용해서 HTML 파일이나 이미지에서 PDF 파일을 자동으로 만들거나, 사용자가 이미지를 업로드할 때 썸네일을 만들 수 있어요.
이 예시에서는 PDF 파일이 Amazon Simple Storage Service(Amazon S3) 버킷에 업로드될 때 자동으로 암호화하는 앱을 만들어요. 이 앱을 구현하려면 다음 리소스를 만들어요:
- 사용자가 PDF 파일을 업로드할 S3 버킷
- 업로드된 파일을 읽고 암호화되고 비밀번호로 보호된 버전을 만드는 Python Lambda 함수
- Lambda가 암호화된 파일을 저장할 두 번째 S3 버킷
또한 Lambda 함수가 S3 버킷에서 읽기·쓰기 작업을 수행할 수 있는 권한을 부여하는 AWS Identity and Access Management(IAM) 정책도 만들어요.
팁 Lambda가 처음이라면 이 예시 앱을 만들기 전에 첫 Lambda 함수 만들기 튜토리얼부터 시작하는 것을 권장해요.
AWS Management Console이나 AWS Command Line Interface(AWS CLI)로 리소스를 만들고 구성해서 앱을 수동으로 배포할 수 있어요. AWS Serverless Application Model(AWS SAM)을 사용해서 앱을 배포할 수도 있어요. AWS SAM은 인프라스트럭처 코드(IaC) 도구예요. IaC를 사용하면 리소스를 수동으로 만들지 않고 코드로 정의한 다음 자동으로 배포해요.
이 예시 앱을 배포하기 전에 Lambda와 IaC 사용에 대해 더 자세히 알고 싶다면 인프라스트럭처 코드(IaC)와 함께 Lambda 사용을 참고하세요.
본문
Lambda 함수 소스 코드 파일 만들기
프로젝트 디렉터리에 다음 파일을 만들어요:
lambda_function.py– 파일 암호화를 수행하는 Lambda 함수용 Python 함수 코드requirements.txt– Python 함수 코드가 필요로 하는 종속성을 정의하는 매니페스트 파일
다음 섹션을 펼쳐서 코드를 확인하고 각 파일의 역할에 대해 자세히 알아보세요. 로컬 머신에서 파일을 만들려면 아래 코드를 복사·붙여넣거나, aws-lambda-developer-guide GitHub 저장소에서 파일을 다운로드하세요.
Python 함수 코드
다음 코드를 lambda_function.py라는 파일에 복사·붙여넣으세요.
from pypdf import PdfReader, PdfWriter
import uuid
import os
from urllib.parse import unquote_plus
import boto3
# Create the S3 client to download and upload objects from S3
s3_client = boto3.client('s3')
def lambda_handler(event, context):
# Iterate over the S3 event object and get the key for all uploaded files
for record in event['Records']:
bucket = record['s3']['bucket']['name']
key = unquote_plus(record['s3']['object']['key']) # Decode the S3 object key to remove any URL-encoded characters
download_path = f'/tmp/{uuid.uuid4()}.pdf' # Create a path in the Lambda tmp directory to save the file to
upload_path = f'/tmp/converted-{uuid.uuid4()}.pdf' # Create another path to save the encrypted file to
# If the file is a PDF, encrypt it and upload it to the destination S3 bucket
if key.lower().endswith('.pdf'):
s3_client.download_file(bucket, key, download_path)
encrypt_pdf(download_path, upload_path)
encrypted_key = add_encrypted_suffix(key)
s3_client.upload_file(upload_path, f'{bucket}-encrypted', encrypted_key)
# Define the function to encrypt the PDF file with a password
def encrypt_pdf(file_path, encrypted_file_path):
reader = PdfReader(file_path)
writer = PdfWriter()
for page in reader.pages:
writer.add_page(page)
# Add a password to the new PDF
writer.encrypt("my-secret-password")
# Save the new PDF to a file
with open(encrypted_file_path, "wb") as file:
writer.write(file)
# Define a function to add a suffix to the original filename after encryption
def add_encrypted_suffix(original_key):
filename, extension = original_key.rsplit('.', 1)
return f'{filename}_encrypted.{extension}'
참고
이 예시 코드에서는 암호화된 파일의 비밀번호(my-secret-password)가 함수 코드에 하드코딩되어 있어요. 프로덕션 애플리케이션에서는 비밀번호 같은 민감한 정보를 함수 코드에 포함하지 마세요. 대신 AWS Secrets Manager 시크릿을 만들고 AWS Parameters and Secrets Lambda 확장 프로그램을 사용해서 Lambda 함수에서 자격 증명을 검색하세요.
Python 함수 코드에는 세 가지 함수가 포함돼요 — Lambda가 함수를 호출할 때 실행하는 핸들러 함수와, 핸들러가 PDF 암호화를 수행하기 위해 호출하는 add_encrypted_suffix와 encrypt_pdf라는 두 개의 별도 함수예요.
Amazon S3가 함수를 호출하면 Lambda는 호출을 일으킨 이벤트에 대한 세부 정보가 포함된 JSON 형식의 이벤트 인수를 함수에 전달해요. 이 경우 정보에는 S3 버킷 이름과 업로드된 파일의 객체 키가 포함돼요. Amazon S3의 이벤트 객체 형식에 대해 자세히 알아보려면 Lambda로 Amazon S3 이벤트 알림 처리를 참고하세요.
그런 다음 함수는 AWS SDK for Python(Boto3)을 사용해서 이벤트 객체에 지정된 PDF 파일을 로컬 임시 스토리지 디렉터리로 다운로드하고, pypdf 라이브러리를 사용해 암호화해요.
마지막으로 함수는 Boto3 SDK를 사용해서 암호화된 파일을 S3 대상 버킷에 저장해요.
requirements.txt 매니페스트 파일
다음 코드를 requirements.txt라는 파일에 복사·붙여넣으세요.
boto3
pypdf
이 예시에서 함수 코드에는 표준 Python 라이브러리의 일부가 아닌 종속성이 두 개뿐이에요 — SDK for Python(Boto3)과 함수가 PDF 암호화를 수행하는 데 사용하는 pypdf 패키지예요.
참고 SDK for Python(Boto3) 버전은 Lambda 런타임의 일부로 포함되어 있으므로 코드는 Boto3를 함수의 배포 패키지에 추가하지 않아도 실행돼요. 하지만 함수의 종속성을 완전히 제어하고 버전 불일치로 인한 잠재적 문제를 피하려면 Python의 모범 사례는 모든 함수 종속성을 함수의 배포 패키지에 포함하는 거예요. 자세한 내용은 Python 런타임 종속성을 참고하세요.
앱 배포
이 예시 앱의 리소스를 수동으로 또는 AWS SAM을 사용해서 만들고 배포할 수 있어요. 프로덕션 환경에서는 AWS SAM 같은 IaC 도구를 사용해서 수동 프로세스 없이 전체 서버리스 애플리케이션을 빠르고 반복 가능하게 배포하는 것을 권장해요.
리소스 수동 배포
앱을 수동으로 배포하려면:
- 소스 및 대상 Amazon S3 버킷 만들기
- PDF 파일을 암호화하고 암호화된 버전을 S3 버킷에 저장하는 Lambda 함수 만들기
- 소스 버킷에 객체가 업로드될 때 함수를 호출하는 Lambda 트리거 구성
시작하기 전에 빌드 머신에 Python이 설치되어 있는지 확인하세요.
두 개의 S3 버킷 만들기
먼저 두 개의 S3 버킷을 만들어요. 첫 번째 버킷은 PDF 파일을 업로드하는 소스 버킷이에요. 두 번째 버킷은 함수를 호출할 때 Lambda가 암호화된 파일을 저장하는 데 사용해요.
콘솔
S3 버킷을 만들려면(콘솔)
-
Amazon S3 콘솔의 범용 버킷 페이지를 엽니다.
-
지리적 위치에 가장 가까운 AWS 리전을 선택합니다. 화면 상단의 드롭다운 목록을 사용해서 리전을 변경할 수 있어요.
-
버킷 만들기(Create bucket)를 선택합니다.
-
일반 구성(General configuration)에서 다음을 수행합니다.
-
버킷 유형(Bucket type)에서 범용(General purpose)이 선택되었는지 확인합니다.
-
버킷 이름(Bucket name)에 Amazon S3 버킷 명명 규칙을 충족하는 전역적으로 고유한 이름을 입력합니다. 버킷 이름에는 소문자, 숫자, 점(.), 하이픈(-)만 포함할 수 있어요.
-
-
다른 모든 옵션은 기본값으로 두고 버킷 만들기(Create bucket)를 선택합니다.
-
1~4단계를 반복해서 대상 버킷을 만듭니다. 버킷 이름(Bucket name)에
amzn-s3-demo-bucket-encrypted를 입력합니다. 여기서amzn-s3-demo-bucket은 방금 만든 소스 버킷의 이름이에요.
AWS CLI
시작하기 전에 빌드 머신에 AWS CLI가 설치되어 있는지 확인하세요.
Amazon S3 버킷을 만들려면(AWS CLI)
-
다음 CLI 명령을 실행해서 소스 버킷을 만듭니다. 선택한 버킷 이름은 전역적으로 고유해야 하고 Amazon S3 버킷 명명 규칙을 따라야 해요. 이름에는 소문자, 숫자, 점(.), 하이픈(-)만 포함할 수 있어요.
region과LocationConstraint에는 지리적 위치에 가장 가까운 AWS 리전을 선택하세요.aws s3api create-bucket --bucket {{amzn-s3-demo-bucket}} --region {{us-east-2}} \ --create-bucket-configuration LocationConstraint={{us-east-2}}나중에 튜토리얼에서 Lambda 함수를 소스 버킷과 동일한 AWS 리전에 만들어야 하므로 선택한 리전을 기록해 두세요.
-
다음 명령을 실행해서 대상 버킷을 만듭니다. 버킷 이름에는
amzn-s3-demo-bucket-encrypted를 사용해야 하며, 여기서amzn-s3-demo-bucket은 1단계에서 만든 소스 버킷의 이름이에요.region과LocationConstraint에는 소스 버킷을 만드는 데 사용한 동일한 AWS 리전을 선택하세요.aws s3api create-bucket --bucket {{amzn-s3-demo-bucket-encrypted}} --region {{us-east-2}} \ --create-bucket-configuration LocationConstraint={{us-east-2}}
실행 역할 만들기
실행 역할은 Lambda 함수에 AWS 서비스와 리소스에 액세스할 권한을 부여하는 IAM 역할이에요. 함수에 Amazon S3에 대한 읽기·쓰기 액세스 권한을 부여하려면 AWS 관리형 정책 AmazonS3FullAccess를 연결하세요.
콘솔
실행 역할을 만들고 AmazonS3FullAccess 관리형 정책을 연결하려면(콘솔)
-
IAM 콘솔의 역할 페이지를 엽니다.
-
역할 만들기(Create role)를 선택합니다.
-
신뢰할 수 있는 엔터티 유형(Trusted entity type)에서 AWS 서비스(AWS service)를 선택하고 사용 사례(Use case)에서 Lambda를 선택합니다.
-
다음(Next)을 선택합니다.
-
다음을 수행해서
AmazonS3FullAccess관리형 정책을 추가합니다.-
권한 정책(Permissions policies)에서 검색 창에 AmazonS3FullAccess를 입력합니다.
-
정책 옆의 확인란을 선택합니다.
-
다음(Next)을 선택합니다.
-
-
역할 세부 정보(Role details)의 역할 이름(Role name)에 LambdaS3Role을 입력합니다.
-
역할 만들기(Create Role)를 선택합니다.
AWS CLI
실행 역할을 만들고 AmazonS3FullAccess 관리형 정책을 연결하려면(AWS CLI)
-
다음 JSON을
trust-policy.json이라는 파일에 저장합니다. 이 신뢰 정책은 서비스 보안 주체lambda.amazonaws.com에 AWS Security Token Service(AWS STS)AssumeRole작업 호출 권한을 부여함으로써 Lambda가 역할의 권한을 사용할 수 있게 해줘요.{ "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } -
JSON 신뢰 정책 문서를 저장한 디렉터리에서 다음 CLI 명령을 실행해서 실행 역할을 만듭니다.
aws iam create-role --role-name LambdaS3Role --assume-role-policy-document file://trust-policy.json -
AmazonS3FullAccess관리형 정책을 연결하려면 다음 CLI 명령을 실행합니다.aws iam attach-role-policy --role-name LambdaS3Role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
함수 배포 패키지 만들기
함수를 만들려면 함수 코드와 그 종속성을 포함하는 배포 패키지를 만들어요. 이 애플리케이션의 경우 함수 코드는 PDF 암호화에 별도의 라이브러리를 사용해요.
배포 패키지를 만들려면
-
앞서 GitHub에서 만들거나 다운로드한
lambda_function.py와requirements.txt파일이 있는 프로젝트 디렉터리로 이동해서package라는 새 디렉터리를 만듭니다. -
다음 명령을 실행해서
requirements.txt파일에 지정된 종속성을package디렉터리에 설치합니다.pip install -r requirements.txt --target ./package/ -
애플리케이션 코드와 종속성을 포함한 .zip 파일을 만듭니다. Linux 또는 macOS에서는 명령줄 인터페이스에서 다음 명령을 실행합니다.
cd package zip -r ../lambda_function.zip . cd .. zip lambda_function.zip lambda_function.pyWindows에서는 선호하는 zip 도구를 사용해서
lambda_function.zip파일을 만드세요.lambda_function.py파일과 종속성을 포함한 폴더가 모두 .zip 파일 루트에 있는지 확인하세요.
Python 가상 환경을 사용해서 배포 패키지를 만들 수도 있어요. Python Lambda 함수용 .zip 파일 아카이브 작업을 참고하세요.
Lambda 함수 만들기
이제 이전 단계에서 만든 배포 패키지를 사용해서 Lambda 함수를 배포해요.
콘솔
함수를 만들려면(콘솔)
콘솔을 사용해 Lambda 함수를 만들려면 먼저 'Hello world' 코드가 포함된 기본 함수를 만든 다음, 이전 단계에서 만든 .zip 파일을 업로드해서 이 코드를 자신의 함수 코드로 대체해요.
큰 PDF 파일을 암호화할 때 함수가 시간 초과되지 않도록 함수의 메모리와 시간 초과 설정을 구성해요. 또한 함수의 로그 형식을 JSON으로 설정해요. 제공된 테스트 스크립트를 사용할 때 JSON 형식 로그를 구성해야 함수의 호출 상태를 CloudWatch Logs에서 읽고 성공적인 호출을 확인할 수 있어요.
-
Lambda 콘솔의 함수 페이지를 엽니다.
-
S3 버킷을 만든 것과 동일한 AWS 리전에서 작업하고 있는지 확인합니다. 화면 상단의 드롭다운 목록을 사용해서 리전을 변경할 수 있어요.
-
함수 생성(Create function)을 선택합니다.
-
처음부터 작성(Author from scratch)을 선택합니다.
-
기본 정보(Basic information)에서 다음을 수행합니다.
-
함수 이름(Function name)에
EncryptPDF를 입력합니다. -
런타임(Runtime)에서 Python 3.12를 선택합니다.
-
아키텍처(Architecture)에서 x86_64를 선택합니다.
-
-
다음을 수행해서 이전 단계에서 만든 실행 역할을 연결합니다.
-
기본 실행 역할 변경(Change default execution role) 섹션을 펼칩니다.
-
기존 역할 사용(Use an existing role)을 선택합니다.
-
기존 역할(Existing role)에서 역할(
LambdaS3Role)을 선택합니다.
-
-
함수 생성(Create function)을 선택합니다.
함수 코드를 업로드하려면(콘솔)
-
코드 소스(Code source) 창에서 업로드 위치(Upload from)를 선택합니다.
-
.zip 파일(.zip file)을 선택합니다.
-
업로드(Upload)를 선택합니다.
-
파일 선택기에서 .zip 파일을 선택하고 열기(Open)를 선택합니다.
-
저장(Save)을 선택합니다.
함수 메모리와 시간 초과를 구성하려면(콘솔)
-
함수의 구성(Configuration) 탭을 선택합니다.
-
일반 구성(General configuration) 창에서 편집(Edit)을 선택합니다.
-
메모리(Memory)를 256MB로, 시간 초과(Timeout)를 15초로 설정합니다.
-
저장(Save)을 선택합니다.
로그 형식을 구성하려면(콘솔)
-
함수의 구성(Configuration) 탭을 선택합니다.
-
모니터링 및 운영 도구(Monitoring and operations tools)를 선택합니다.
-
로깅 구성(Logging configuration) 창에서 편집(Edit)을 선택합니다.
-
로깅 구성(Logging configuration)에서 JSON을 선택합니다.
-
저장(Save)을 선택합니다.
AWS CLI
함수를 만들려면(AWS CLI)
-
lambda_function.zip파일이 있는 디렉터리에서 다음 명령을 실행합니다.region매개변수의 경우us-east-2를 S3 버킷을 만든 리전으로 바꾸세요.aws lambda create-function --function-name EncryptPDF \ --zip-file fileb://lambda_function.zip --handler lambda_function.lambda_handler \ --runtime python3.12 --timeout 15 --memory-size 256 \ --role arn:aws:iam::{{123456789012}}:role/LambdaS3Role --region {{us-east-2}} \ --logging-config LogFormat=JSON
Amazon S3 트리거를 구성해서 함수 호출
소스 버킷에 파일을 업로드할 때 Lambda 함수가 실행되려면 함수에 대한 트리거를 구성해야 해요. 콘솔이나 AWS CLI를 사용해서 Amazon S3 트리거를 구성할 수 있어요.
중요 이 절차는 버킷에서 객체가 생성될 때마다 함수를 호출하도록 S3 버킷을 구성해요. 소스 버킷에만 구성하세요. Lambda 함수가 자신을 호출하는 동일한 버킷에 객체를 만들면 함수는 연속적으로 반복 호출될 수 있어요. 이로 인해 AWS 계정에 예상치 못한 비용이 청구될 수 있어요.
콘솔
Amazon S3 트리거를 구성하려면(콘솔)
-
Lambda 콘솔의 함수 페이지를 열고 함수(
EncryptPDF)를 선택합니다. -
트리거 추가(Add trigger)를 선택합니다.
-
S3를 선택합니다.
-
버킷(Bucket)에서 소스 버킷을 선택합니다.
-
이벤트 유형(Event types)에서 모든 객체 생성 이벤트(All object create events)를 선택합니다.
-
재귀 호출(Recursive invocation)에서 입력과 출력에 동일한 S3 버킷을 사용하는 것을 권장하지 않는다는 점을 확인하는 확인란을 선택합니다. Serverless Land의 런어웨이 Lambda 함수를 일으키는 재귀 패턴에서 Lambda의 재귀 호출 패턴에 대해 자세히 알아볼 수 있어요.
-
추가(Add)를 선택합니다.
Lambda 콘솔을 사용해서 트리거를 만들면 Lambda가 선택한 서비스에 함수를 호출할 권한을 부여하는 리소스 기반 정책을 자동으로 만들어요.
AWS CLI
Amazon S3 트리거를 구성하려면(AWS CLI)
-
파일을 추가할 때 Amazon S3 소스 버킷이 함수를 호출할 수 있게 하는 리소스 기반 정책을 함수에 추가합니다. 리소스 기반 정책 문은 다른 AWS 서비스에 함수를 호출할 권한을 부여해요. Amazon S3에 함수를 호출할 권한을 부여하려면 다음 CLI 명령을 실행하세요.
source-account매개변수를 자신의 AWS 계정 ID로 바꾸고 자신의 소스 버킷 이름을 사용해야 해요.aws lambda add-permission --function-name EncryptPDF \ --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" \ --source-arn arn:aws:s3:::{{amzn-s3-demo-bucket}} \ --source-account {{123456789012}}이 명령으로 정의한 정책은 소스 버킷에서 작업이 발생할 때만 Amazon S3가 함수를 호출하도록 허용해요. 참고 S3 버킷 이름은 전역적으로 고유하지만 리소스 기반 정책을 사용할 때는 버킷이 자신의 계정에 속해야 한다고 지정하는 것이 모범 사례예요. 버킷을 삭제하면 다른 AWS 계정이 동일한 Amazon 리소스 이름(ARN)으로 버킷을 만들 수 있기 때문이에요.
-
다음 JSON을
notification.json이라는 파일에 저장합니다. 이 JSON을 소스 버킷에 적용하면 새 객체가 추가될 때마다 버킷이 Lambda 함수에 알림을 보내도록 구성돼요. Lambda 함수 ARN의 AWS 계정 번호와 AWS 리전을 자신의 계정 번호와 리전으로 바꾸세요.{ "LambdaFunctionConfigurations": [ { "Id": "EncryptPDFEventConfiguration", "LambdaFunctionArn": "arn:aws:lambda:{{us-east-2:123456789012}}:function:EncryptPDF", "Events": [ "s3:ObjectCreated:Put" ] } ] } -
다음 CLI 명령을 실행해서 만든 JSON 파일의 알림 설정을 소스 버킷에 적용합니다.
amzn-s3-demo-bucket을 자신의 소스 버킷 이름으로 바꾸세요.aws s3api put-bucket-notification-configuration --bucket {{amzn-s3-demo-bucket}} \ --notification-configuration file://notification.jsonput-bucket-notification-configuration명령과notification-configuration옵션에 대한 자세한 내용은 AWS CLI 명령 참조의 put-bucket-notification-configuration을 참고하세요.
AWS SAM을 사용해서 리소스 배포
시작하기 전에 빌드 머신에 Docker와 최신 버전의 AWS SAM CLI가 설치되어 있는지 확인하세요.
-
프로젝트 디렉터리에서 다음 코드를
template.yaml이라는 파일에 복사·붙여넣습니다. 자리 표시자 버킷 이름을 바꾸세요:- 소스 버킷의 경우
amzn-s3-demo-bucket을 S3 버킷 명명 규칙을 준수하는 이름으로 바꾸세요. - 대상 버킷의 경우
amzn-s3-demo-bucket-encrypted를<source-bucket-name>-encrypted로 바꾸세요. 여기서<source-bucket>은 소스 버킷으로 선택한 이름이에요.
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Resources: EncryptPDFFunction: Type: AWS::Serverless::Function Properties: FunctionName: EncryptPDF Architectures: [x86_64] CodeUri: ./ Handler: lambda_function.lambda_handler Runtime: python3.12 Timeout: 15 MemorySize: 256 LoggingConfig: LogFormat: JSON Policies: - AmazonS3FullAccess Events: S3Event: Type: S3 Properties: Bucket: !Ref PDFSourceBucket Events: s3:ObjectCreated:* PDFSourceBucket: Type: AWS::S3::Bucket Properties: BucketName: {{amzn-s3-demo-bucket}} EncryptedPDFBucket: Type: AWS::S3::Bucket Properties: BucketName: {{amzn-s3-demo-bucket-encrypted}}AWS SAM 템플릿은 앱용으로 만드는 리소스를 정의해요. 이 예시에서 템플릿은
AWS::Serverless::Function유형의 Lambda 함수와AWS::S3::Bucket유형의 두 S3 버킷을 정의해요. 템플릿에 지정된 버킷 이름은 자리 표시자예요. AWS SAM을 사용해 앱을 배포하기 전에 S3 버킷 명명 규칙을 충족하는 전역적으로 고유한 이름으로 버킷을 바꾸도록 템플릿을 편집해야 해요. 이 단계는 AWS SAM을 사용해서 리소스 배포에서 자세히 설명돼요.Lambda 함수 리소스의 정의는
S3Event이벤트 속성을 사용해서 함수에 대한 트리거를 구성해요. 이 트리거는 소스 버킷에서 객체가 생성될 때마다 함수가 호출되게 해요.함수 정의는 또한 함수의 실행 역할에 연결할 AWS Identity and Access Management(IAM) 정책을 지정해요. AWS 관리형 정책
AmazonS3FullAccess는 함수가 Amazon S3에서 객체를 읽고 쓰는 데 필요한 권한을 부여해요. - 소스 버킷의 경우
-
template.yaml,lambda_function.py,requirements.txt파일을 저장한 디렉터리에서 다음 명령을 실행합니다.sam build --use-container이 명령은 애플리케이션의 빌드 아티팩트를 수집해서 배포할 수 있는 올바른 형식과 위치에 배치해요.
--use-container옵션을 지정하면 Lambda와 유사한 Docker 컨테이너에서 함수를 빌드해요. 빌드가 작동하도록 로컬 머신에 Python 3.12를 설치할 필요가 없도록 여기서 사용해요.빌드 프로세스 중 AWS SAM은 템플릿의
CodeUri속성에서 지정한 위치에서 Lambda 함수 코드를 찾아요. 이 경우 현재 디렉터리를 위치(./)로 지정했어요.requirements.txt파일이 있으면 AWS SAM은 지정된 종속성을 수집하는 데 사용해요. 기본적으로 AWS SAM은 함수 코드와 종속성으로 .zip 배포 패키지를 만들어요. PackageType 속성을 사용해서 함수를 컨테이너 이미지로 배포하도록 선택할 수도 있어요. -
애플리케이션을 배포하고 AWS SAM 템플릿에 지정된 Lambda 및 Amazon S3 리소스를 만들려면 다음 명령을 실행합니다.
sam deploy --guided--guided플래그를 사용하면 AWS SAM이 배포 프로세스를 안내하는 프롬프트를 보여줘요. 이 배포에서는 Enter를 눌러 기본 옵션을 수락하세요.
배포 프로세스 중 AWS SAM은 AWS 계정에 다음 리소스를 만들어요:
sam-app이라는 이름의 CloudFormation 스택EncryptPDF라는 이름의 Lambda 함수template.yamlAWS SAM 템플릿 파일을 편집할 때 선택한 이름을 가진 두 S3 버킷sam-app-EncryptPDFFunctionRole-{{2qGaapHFWOQ8}}형식의 함수용 IAM 실행 역할
AWS SAM이 리소스 만들기를 마치면 다음 메시지가 표시돼야 해요:
Successfully created/updated stack - sam-app in us-east-2
앱 테스트
앱을 테스트하려면 PDF 파일을 소스 버킷에 업로드하고 Lambda가 대상 버킷에 파일의 암호화된 버전을 만드는지 확인해요. 이 예시에서는 콘솔이나 AWS CLI를 사용해 수동으로 테스트하거나, 제공된 테스트 스크립트를 사용해서 테스트할 수 있어요.
프로덕션 애플리케이션의 경우 단위 테스트 같은 기존 테스트 방법과 기술을 사용해서 Lambda 함수 코드의 올바른 작동을 확인할 수 있어요. 또한 제공된 테스트 스크립트의 테스트처럼 실제 클라우드 기반 리소스로 통합 테스트를 수행하는 것도 모범 사례예요. 클라우드에서의 통합 테스트는 인프라가 올바르게 배포되었고 이벤트가 서비스 간에 예상대로 흐르는지 확인해줘요. 자세한 내용은 서버리스 함수와 애플리케이션 테스트 방법을 참고하세요.
앱 수동 테스트
Amazon S3 소스 버킷에 PDF 파일을 추가해서 함수를 수동으로 테스트할 수 있어요. 소스 버킷에 파일을 추가하면 Lambda 함수가 자동으로 호출되어 대상 버킷에 파일의 암호화된 버전을 저장해야 해요.
콘솔
파일을 업로드해서 앱을 테스트하려면(콘솔)
-
S3 버킷에 PDF 파일을 업로드하려면 다음을 수행합니다.
-
Amazon S3 콘솔의 버킷 페이지를 열고 소스 버킷을 선택합니다.
-
업로드(Upload)를 선택합니다.
-
파일 추가(Add files)를 선택하고 파일 선택기를 사용해 업로드할 PDF 파일을 선택합니다.
-
열기(Open)를 선택한 다음 업로드(Upload)를 선택합니다.
-
-
다음을 수행해서 Lambda가 대상 버킷에 PDF 파일의 암호화된 버전을 저장했는지 확인합니다.
-
Amazon S3 콘솔의 버킷 페이지로 돌아가 대상 버킷을 선택합니다.
-
객체(Objects) 창에서 이제
filename_encrypted.pdf형식의 이름을 가진 파일이 보일 것입니다(여기서filename.pdf는 소스 버킷에 업로드한 파일의 이름이에요). 암호화된 PDF를 다운로드하려면 파일을 선택한 다음 다운로드(Download)를 선택합니다. -
다운로드한 파일을 Lambda 함수가 보호한 비밀번호(
my-secret-password)로 열 수 있는지 확인합니다.
-
AWS CLI
파일을 업로드해서 앱을 테스트하려면(AWS CLI)
-
업로드할 PDF 파일이 있는 디렉터리에서 다음 CLI 명령을 실행합니다.
--bucket매개변수를 소스 버킷의 이름으로 바꾸세요.--key와--body매개변수에는 테스트 파일의 파일 이름을 사용하세요.aws s3api put-object --bucket {{amzn-s3-demo-bucket}} --key {{test.pdf}} --body {{./test.pdf}} -
함수가 파일의 암호화된 버전을 만들어 대상 S3 버킷에 저장했는지 확인합니다. 다음 CLI 명령을 실행하고
amzn-s3-demo-bucket-encrypted를 자신의 대상 버킷 이름으로 바꾸세요.aws s3api list-objects-v2 --bucket {{amzn-s3-demo-bucket-encrypted}}함수가 성공적으로 실행되면 다음 출력과 유사한 출력이 보일 것입니다. 대상 버킷에는
<your_test_file>}_encrypted.pdf형식의 이름을 가진 파일이 있어야 해요. 여기서<your_test_file>은 업로드한 파일의 이름이에요.{ "Contents": [ { "Key": "test_encrypted.pdf", "LastModified": "2023-06-07T00:15:50+00:00", "ETag": "\"7781a43e765a8301713f533d70968a1e\"", "Size": 2763, "StorageClass": "STANDARD" } ] } -
Lambda가 대상 버킷에 저장한 파일을 다운로드하려면 다음 CLI 명령을 실행합니다.
--bucket매개변수를 대상 버킷의 이름으로 바꾸세요.--key매개변수에는 업로드한 테스트 파일의 이름인<your_test_file>}_encrypted.pdf파일 이름을 사용하세요.aws s3api get-object --bucket {{amzn-s3-demo-bucket-encrypted}} --key {{test_encrypted.pdf}} my_encrypted_file.pdf
자동화된 스크립트로 앱 테스트
이 예시 앱에는 앱 구성을 확인하는 Pytest 자동화 테스트가 포함되어 있어요. 자동화된 테스트를 사용하려면 test_pdf_encrypt.py와 pytest.ini라는 두 개의 파일을 추가로 만들어야 해요. 다음 섹션에는 두 파일의 콘텐츠가 포함되어 있지만, 앱을 실행하기 전에 각 파일에서 버킷 이름을 편집해야 해요.
테스트 스크립트
다음 코드를 test_pdf_encrypt.py라는 파일에 복사·붙여넣으세요.
import json
import os
import time
import pytest
import boto3
from botocore.exceptions import ClientError
# Define fixtures for the S3 and CloudWatch Logs clients
@pytest.fixture(scope='session')
def s3_client():
return boto3.client('s3')
@pytest.fixture(scope='session')
def logs_client():
return boto3.client('logs')
@pytest.fixture(scope='session')
def cleanup(s3_client):
yield
# Clean up test files after all tests
# Delete test.pdf from the source bucket
source_bucket = 'amzn-s3-demo-bucket'
source_file_key = 'test.pdf'
try:
s3_client.delete_object(Bucket=source_bucket, Key=source_file_key)
print(f"Deleted {source_file_key} from {source_bucket}")
except Exception as e:
print(f"Error deleting {source_file_key}: {e}")
# Delete test_encrypted.pdf from the destination bucket
destination_bucket = 'amzn-s3-demo-bucket-encrypted'
destination_file_key = 'test_encrypted.pdf'
s3_client.delete_object(Bucket=destination_bucket, Key=destination_file_key)
print(f"Deleted {destination_file_key} from {destination_bucket}")
@pytest.mark.order(1)
def test_source_bucket_available(s3_client):
s3_bucket_name = 'amzn-s3-demo-bucket'
file_name = 'test.pdf'
file_path = os.path.join(os.path.dirname(__file__), file_name)
file_uploaded = False
try:
s3_client.upload_file(file_path, s3_bucket_name, file_name)
file_uploaded = True
except:
print("Error: couldn't upload file")
assert file_uploaded, "Could not upload file to S3 bucket"
@pytest.mark.order(2)
def test_lambda_invoked(logs_client):
# Wait for a few seconds to make sure the logs are available
time.sleep(5)
# Get the latest log stream for the specified log group
log_streams = logs_client.describe_log_streams(
logGroupName='/aws/lambda/EncryptPDF',
orderBy='LastEventTime',
descending=True,
limit=1
)
latest_log_stream_name = log_streams['logStreams'][0]['logStreamName']
# Retrieve the log events from the latest log stream
log_events = logs_client.get_log_events(
logGroupName='/aws/lambda/EncryptPDF',
logStreamName=latest_log_stream_name
)
success_found = False
for event in log_events['events']:
message = json.loads(event['message'])
status = message.get('record', {}).get('status')
if status == 'success':
success_found = True
break
assert success_found, "Lambda function execution did not report 'success' status in logs."
@pytest.mark.order(3)
def test_encrypted_file_in_bucket(s3_client):
# Specify the destination S3 bucket and the expected converted file key
destination_bucket = 'amzn-s3-demo-bucket-encrypted'
converted_file_key = 'test_encrypted.pdf'
try:
# Attempt to retrieve the metadata of the converted file from the destination S3 bucket
s3_client.head_object(Bucket=destination_bucket, Key=converted_file_key)
except s3_client.exceptions.ClientError as e:
# If the file is not found, the test will fail
pytest.fail(f"Converted file '{converted_file_key}' not found in the destination bucket: {str(e)}")
def test_cleanup(cleanup):
# This test uses the cleanup fixture and will be executed last
pass
자동화된 테스트 스크립트는 앱의 올바른 작동을 확인하기 위해 세 가지 테스트 함수를 실행해요:
test_source_bucket_available테스트는 테스트 PDF 파일을 버킷에 업로드해서 소스 버킷이 성공적으로 만들어졌는지 확인해요.test_lambda_invoked테스트는 함수의 최신 CloudWatch Logs 로그 스트림을 조회해서 테스트 파일을 업로드했을 때 Lambda 함수가 실행되고 성공을 보고했는지 확인해요.test_encrypted_file_in_bucket테스트는 대상 버킷에 암호화된test_encrypted.pdf파일이 포함되어 있는지 확인해요.
이 모든 테스트가 실행된 후 스크립트는 소스 및 대상 버킷 모두에서 test.pdf와 test_encrypted.pdf 파일을 삭제하는 추가 정리 단계를 실행해요.
AWS SAM 템플릿과 마찬가지로 이 파일에 지정된 버킷 이름은 자리 표시자예요. 테스트를 실행하기 전에 이 파일을 앱의 실제 버킷 이름으로 편집해야 해요. 이 단계는 자동화된 스크립트로 앱 테스트에서 자세히 설명돼요.
테스트 스크립트 구성 파일
다음 코드를 pytest.ini라는 파일에 복사·붙여넣으세요.
[pytest]
markers =
order: specify test execution order
이 파일은 test_pdf_encrypt.py 스크립트의 테스트가 실행되는 순서를 지정하는 데 필요해요.
테스트를 실행하려면 다음을 수행하세요:
-
로컬 환경에
pytest모듈이 설치되어 있는지 확인합니다. 다음 명령을 실행해서pytest를 설치할 수 있어요:pip install pytest -
test_pdf_encrypt.py와pytest.ini파일이 있는 디렉터리에test.pdf라는 PDF 파일을 저장합니다. -
터미널이나 셸 프로그램을 열고 테스트 파일이 있는 디렉터리에서 다음 명령을 실행합니다.
pytest -s -v테스트가 완료되면 다음과 같은 출력이 보일 것입니다:
============================================================== test session starts ========================================================= platform linux -- Python 3.12.2, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3 cachedir: .pytest_cache hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase('/home/pdf_encrypt_app/.hypothesis/examples') Test order randomisation NOT enabled. Enable with --random-order or --random-order-bucket=<bucket_type> rootdir: /home/pdf_encrypt_app, configfile: pytest.ini plugins: anyio-3.7.1, hypothesis-6.70.0, localserver-0.7.1, random-order-1.1.0 collected 4 items test_pdf_encrypt.py::test_source_bucket_available PASSED test_pdf_encrypt.py::test_lambda_invoked PASSED test_pdf_encrypt.py::test_encrypted_file_in_bucket PASSED test_pdf_encrypt.py::test_cleanup PASSED Deleted test.pdf from amzn-s3-demo-bucket Deleted test_encrypted.pdf from amzn-s3-demo-bucket-encrypted =============================================================== 4 passed in 7.32s ==========================================================
다음 단계
이 예시 앱을 만들었으니 제공된 코드를 기반으로 다른 유형의 파일 처리 애플리케이션을 만들 수 있어요. lambda_function.py 파일의 코드를 수정해서 사용 사례에 맞는 파일 처리 로직을 구현하세요.
많은 일반적인 파일 처리 사용 사례는 이미지 처리를 포함해요. Python을 사용할 때 pillow 같은 가장 인기 있는 이미지 처리 라이브러리에는 보통 C 또는 C++ 구성 요소가 포함돼 있어요. 함수의 배포 패키지가 Lambda 실행 환경과 호환되도록 올바른 소스 배포 바이너리를 사용하는 것이 중요해요.
AWS SAM으로 리소스를 배포할 때 올바른 소스 배포를 배포 패키지에 포함하려면 몇 가지 추가 단계를 수행해야 해요. AWS SAM은 빌드 머신과 다른 플랫폼의 종속성을 설치하지 않으므로, 빌드 머신이 Lambda 실행 환경과 다른 운영 체제나 아키텍처를 사용한다면 requirements.txt 파일에 올바른 소스 배포(.whl 파일)를 지정해도 작동하지 않아요. 대신 다음 중 하나를 수행해야 해요:
sam build실행 시--use-container옵션을 사용하세요. 이 옵션을 지정하면 AWS SAM이 Lambda 실행 환경과 호환되는 컨테이너 기본 이미지를 다운로드하고 Docker 컨테이너에서 해당 이미지를 사용해 함수의 배포 패키지를 빌드해요. 자세한 내용은 제공된 컨테이너 내부에서 Lambda 함수 빌드를 참고하세요.- 올바른 소스 배포 바이너리를 사용해서 함수의 .zip 배포 패키지를 직접 빌드하고 AWS SAM 템플릿에서
CodeUri로 지정한 디렉터리에 .zip 파일을 저장하세요. 바이너리 배포로 Python .zip 배포 패키지를 빌드하는 방법에 대한 자세한 내용은 종속성이 있는 .zip 배포 패키지 만들기와 네이티브 라이브러리가 있는 .zip 배포 패키지 만들기를 참고하세요.
더 알아보기 (Learn more)
이 튜토리얼은 서버리스 파일 처리 앱을 만드는 방법을 설명해요. Lambda 함수 배포와 S3 통합에 대한 자세한 내용은 Lambda 개발자 안내서의 관련 주제를 참고하세요.