Java Lambda 함수를 .zip 또는 JAR 파일 아카이브로 배포하기
Java Lambda 함수를 .zip 또는 JAR 파일 아카이브로 배포하기 (Deploy Java Lambda functions with .zip or JAR file archives)
AWS Lambda 함수의 코드는 스크립트나 컴파일된 프로그램, 그리고 그 의존성으로 구성돼요. 함수 코드를 Lambda에 배포하려면 *배포 패키지(deployment package)*를 사용해요. Lambda는 컨테이너 이미지와 .zip 파일 아카이브 두 가지 유형의 배포 패키지를 지원해요.
이 페이지에서는 배포 패키지를 .zip 파일이나 JAR 파일로 만든 다음, AWS Command Line Interface(AWS CLI)로 배포 패키지를 사용해 함수 코드를 AWS Lambda에 배포하는 방법을 설명해요.
중요 Java 25는 AOT(Ahead-of-Time) 캐시를 도입했어요. 함수를
.zip이나 JAR 파일 아카이브로 배포할 때는 AOT 캐시를 사용하지 않는 걸 강력히 권장해요. Lambda가 관리형 런타임을 업데이트할 때 캐시가 예기치 않은 동작을 일으킬 수 있기 때문이에요. 자세한 내용은 AOT(Ahead-of-Time) 및 CDS 캐시를 참고하세요.
섹션
- 전제 조건
- 도구와 라이브러리
- Gradle로 배포 패키지 빌드하기
- 의존성에 레이어 사용하기
- Maven으로 배포 패키지 빌드하기
- Lambda 콘솔로 배포 패키지 업로드하기
- AWS CLI로 배포 패키지 업로드하기
- AWS SAM으로 배포 패키지 업로드하기
본문
전제 조건
AWS CLI는 명령줄 셸에서 명령으로 AWS 서비스와 상호작용하는 데 쓸 수 있는 오픈소스 도구예요. 이 섹션의 단계를 완료하려면 AWS CLI version 2가 필요해요.
도구와 라이브러리
AWS는 Java 함수용 라이브러리를 다음과 같이 제공해요. 이 라이브러리들은 Maven Central Repository에서 구할 수 있어요.
- com.amazonaws:aws-lambda-java-core(필수) — 핸들러 메서드 인터페이스와 런타임이 핸들러에 전달하는 context 객체를 정의해요. 여러분이 직접 입력 타입을 정의한다면 필요한 라이브러리는 이것뿐이에요.
- com.amazonaws:aws-lambda-java-events — Lambda 함수를 호출하는 서비스에서 오는 이벤트용 입력 타입.
- com.amazonaws:aws-lambda-java-log4j2 — Apache Log4j 2용 appender 라이브러리로, 현재 호출의 요청 ID를 함수 로그에 추가하는 데 쓸 수 있어요.
- AWS SDK for Java 2.0 — Java 프로그래밍 언어용 공식 AWS SDK.
- AWS Lambda Durable Execution SDK for Java — 진행 상황을 체크포인트하고 실패에서 자동 복구하며 실행을 일시 중지하는 신뢰할 수 있는 다단계 애플리케이션과 AI 워크플로를 구축해요. 자세한 내용은 Lambda durable functions을 참고하세요.
이 라이브러리들을 빌드 정의에 다음과 같이 추가해요.
Gradle:
dependencies {
implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1'
implementation 'software.amazon.lambda.durable:aws-durable-execution-sdk-java:1.0.1'
}
Maven:
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>3.11.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-log4j2</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>software.amazon.lambda.durable</groupId>
<artifactId>aws-durable-execution-sdk-java</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
배포 패키지를 만들려면 함수 코드와 의존성을 단일 .zip 파일이나 Java Archive(JAR) 파일로 컴파일해요. Gradle은 Zip 빌드 타입을, Apache Maven은 Maven Shade 플러그인을 사용해요. 배포 패키지를 업로드하려면 Lambda 콘솔, Lambda API, 또는 AWS Serverless Application Model(AWS SAM)을 사용해요.
참고 배포 패키지 크기를 작게 유지하려면 함수의 의존성을 레이어에 패키징하세요. 레이어를 쓰면 의존성을 독립적으로 관리할 수 있고, 여러 함수가 쓸 수 있으며, 다른 계정과 공유할 수도 있어요. 자세한 내용은 레이어로 Lambda 의존성 관리하기를 참고하세요.
Gradle로 배포 패키지 빌드하기
Gradle에서 함수의 코드와 의존성으로 배포 패키지를 만들려면 Zip 빌드 타입을 사용해요. 전체 샘플 build.gradle 파일의 예시가 있어요.
예시 build.gradle — 빌드 태스크
task buildZip(type: Zip) {
into('lib') {
from(jar)
from(configurations.runtimeClasspath)
}
}
이 빌드 구성은 build/distributions 디렉터리에 배포 패키지를 만들어요. into('lib') 문 내부에서 jar 태스크는 메인 클래스가 담긴 jar 아카이브를 lib 폴더에 조립해요. 또한 configurations.runtimeClassPath 태스크가 빌드 클래스패스의 의존성 라이브러리를 같은 lib 폴더에 복사해요.
예시 build.gradle — 의존성
dependencies {
...
implementation 'com.amazonaws:aws-lambda-java-core:1.2.2'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.1'
implementation 'org.apache.logging.log4j:log4j-api:2.17.1'
implementation 'org.apache.logging.log4j:log4j-core:2.17.1'
runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.1'
runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1'
...
}
Lambda는 JAR 파일을 유니코드 알파벳 순서로 로드해요. lib 디렉터리의 여러 JAR 파일에 같은 클래스가 있다면 첫 번째 파일이 사용돼요. 다음 셸 스크립트로 중복 클래스를 식별할 수 있어요.
예시 test-zip.sh
mkdir -p expanded
unzip path/to/my/function.zip -d expanded
find ./expanded/lib -name '*.jar' | xargs -n1 zipinfo -1 | grep '.*.class' | sort | uniq -c | sort
의존성에 레이어 사용하기
함수의 의존성을 레이어에 패키징하면 배포 패키지를 작게 유지하고 의존성을 독립적으로 관리할 수 있어요. 자세한 내용은 Java Lambda 함수용 레이어 작업하기를 참고하세요.
Maven으로 배포 패키지 빌드하기
Maven으로 배포 패키지를 빌드하려면 Maven Shade 플러그인을 사용해요. 이 플러그인은 컴파일된 함수 코드와 모든 의존성을 포함하는 JAR 파일을 만들어요.
예시 pom.xml — 플러그인 구성
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
배포 패키지를 빌드하려면 mvn package 명령을 사용해요.
[INFO] Scanning for projects...
[INFO] -----------------------< com.example:java-maven >-----------------------
[INFO] Building java-maven-function 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
...
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ java-maven ---
[INFO] Building jar: target/java-maven-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-shade-plugin:3.2.2:shade (default) @ java-maven ---
[INFO] Including com.amazonaws:aws-lambda-java-core:jar:1.2.2 in the shaded jar.
[INFO] Including com.amazonaws:aws-lambda-java-events:jar:3.11.1 in the shaded jar.
[INFO] Including joda-time:joda-time:jar:2.6 in the shaded jar.
[INFO] Including com.google.code.gson:gson:jar:2.8.6 in the shaded jar.
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing target/java-maven-1.0-SNAPSHOT.jar with target/java-maven-1.0-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.321 s
[INFO] Finished at: 2020-03-03T09:07:19Z
[INFO] ------------------------------------------------------------------------
이 명령은 target 디렉터리에 JAR 파일을 만들어요.
참고 다중 릴리스 JAR(MRJAR)로 작업 중이라면 배포 패키지를 Lambda에 업로드하기 전에 MRJAR(즉, Maven Shade 플러그인이 만든 shaded JAR)를
lib디렉터리에 포함하고 zip으로 압축해야 해요. 그렇지 않으면 Lambda가 JAR 파일을 제대로 풀지 못해MANIFEST.MF파일이 무시될 수 있어요.
appender 라이브러리(aws-lambda-java-log4j2)를 쓴다면 Maven Shade 플러그인용 transformer도 구성해야 해요. 이 transformer 라이브러리는 appender 라이브러리와 Log4j 양쪽에 나오는 캐시 파일 버전을 결합해요.
예시 pom.xml — Log4j 2 appender가 있는 플러그인 구성
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="com.github.edwgiz.maven_shade_plugin.log4j2_cache_transformer.PluginsCacheFileTransformer">
</transformer>
</transformers>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.github.edwgiz</groupId>
<artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
</plugin>
Lambda 콘솔로 배포 패키지 업로드하기
새 함수를 만들려면 먼저 콘솔에서 함수를 만든 다음 .zip이나 JAR 파일을 업로드해야 해요. 기존 함수를 업데이트하려면 함수 페이지를 연 다음 같은 절차로 업데이트된 .zip이나 JAR 파일을 추가하면 돼요.
배포 패키지 파일이 50MB 미만이면 로컬 머신에서 직접 파일을 업로드해 함수를 만들거나 업데이트할 수 있어요. 50MB보다 큰 .zip이나 JAR 파일은 먼저 패키지를 Amazon S3 버킷에 업로드해야 해요. AWS Management Console로 파일을 Amazon S3 버킷에 업로드하는 방법은 Amazon S3 시작하기를 참고하고, AWS CLI로 업로드하는 방법은 AWS CLI User Guide의 Move objects를 참고하세요.
참고 기존 함수의 배포 패키지 유형(.zip 또는 컨테이너 이미지)은 바꿀 수 없어요. 예를 들어 컨테이너 이미지 함수를
.zip파일 아카이브로 변환할 수 없어요. 새 함수를 만들어야 해요.
새 함수를 만들려면 (콘솔)
- Lambda 콘솔의 Functions 페이지를 열고 Create Function을 선택해요.
- Author from scratch를 선택해요.
- Basic information에서 다음을 수행해요. Function name에 함수 이름을 입력하고, Runtime에서 사용할 런타임을 선택해요. (선택 사항) Architecture에서 함수의 명령어 집합 아키텍처를 선택해요. 기본 아키텍처는 x86_64예요. 함수의
.zip배포 패키지가 선택한 아키텍처와 호환되는지 확인하세요. - (선택 사항) Permissions에서 Change default execution role을 펼쳐 새 Execution role을 만들거나 기존 역할을 사용할 수 있어요.
- Create function을 선택해요. Lambda가 선택한 런타임으로 기본 'Hello world' 함수를 만들어요.
로컬 머신에서 .zip 또는 JAR 아카이브 업로드하기 (콘솔)
- Lambda 콘솔의 Functions 페이지에서
.zip또는 JAR 파일을 업로드할 함수를 선택해요. - Code 탭을 선택해요.
- Code source 창에서 Upload from을 선택해요.
- .zip or .jar file을 선택해요.
.zip또는 JAR 파일을 업로드하려면 다음을 수행해요. Upload를 선택하고 파일 선택기에서.zip또는 JAR 파일을 고른 다음, Open, Save를 선택해요.
Amazon S3 버킷에서 .zip 또는 JAR 아카이브 업로드하기 (콘솔)
- Lambda 콘솔의 Functions 페이지에서 새
.zip또는 JAR 파일을 업로드할 함수를 선택해요. - Code 탭을 선택해요.
- Code source 창에서 Upload from을 선택해요.
- Amazon S3 location을 선택해요.
.zip파일의 Amazon S3 링크 URL을 붙여넣고 Save를 선택해요.
AWS CLI로 배포 패키지 업로드하기
AWS CLI로 .zip 또는 JAR 파일을 사용해 새 함수를 만들거나 기존 함수를 업데이트할 수 있어요. create-function과 update-function-code 명령으로 .zip 또는 JAR 패키지를 배포해요. 파일이 50MB 미만이면 로컬 빌드 머신의 파일 위치에서 패키지를 업로드할 수 있어요. 더 큰 파일은 Amazon S3 버킷에서 .zip 또는 JAR 패키지를 업로드해야 해요. AWS CLI로 파일을 Amazon S3 버킷에 업로드하는 방법은 AWS CLI User Guide의 Move objects를 참고하세요.
참고 AWS CLI로 Amazon S3 버킷에서
.zip또는 JAR 파일을 업로드할 때는 버킷이 함수와 같은 AWS 리전에 있어야 해요.
AWS CLI로 .zip 또는 JAR 파일로 새 함수를 만들려면 다음을 지정해야 해요.
- 함수 이름(
--function-name) - 함수의 런타임(
--runtime) - 함수 실행 역할(execution role)의 Amazon Resource Name(ARN)(
--role) - 함수 코드의 핸들러 메서드 이름(
--handler)
또한 .zip 또는 JAR 파일의 위치를 지정해야 해요. .zip 또는 JAR 파일이 로컬 빌드 머신의 폴더에 있다면 --zip-file 옵션으로 파일 경로를 지정해요.
aws lambda create-function --function-name myFunction \
--runtime java25 --handler example.handler \
--role arn:aws:iam::123456789012:role/service-role/my-lambda-role \
--zip-file fileb://myFunction.zip
Amazon S3 버킷의 .zip 파일 위치를 지정하려면 다음 예시 명령처럼 --code 옵션을 사용해요. 버전 관리되는 객체에서만 S3ObjectVersion 파라미터를 쓰면 돼요.
aws lambda create-function --function-name myFunction \
--runtime java25 --handler example.handler \
--role arn:aws:iam::123456789012:role/service-role/my-lambda-role \
--code S3Bucket=amzn-s3-demo-bucket,S3Key=myFileName.zip,S3ObjectVersion=myObjectVersion
CLI로 기존 함수를 업데이트하려면 --function-name 파라미터로 함수 이름을 지정해요. 함수 코드 업데이트에 쓸 .zip 파일의 위치도 지정해야 해요. .zip 파일이 로컬 빌드 머신의 폴더에 있다면 --zip-file 옵션으로 파일 경로를 지정해요.
aws lambda update-function-code --function-name myFunction \
--zip-file fileb://myFunction.zip
Amazon S3 버킷의 .zip 파일 위치를 지정하려면 다음 예시 명령처럼 --s3-bucket과 --s3-key 옵션을 사용해요. 버전 관리되는 객체에서만 --s3-object-version 파라미터를 쓰면 돼요.
aws lambda update-function-code --function-name myFunction \
--s3-bucket amzn-s3-demo-bucket --s3-key myFileName.zip --s3-object-version myObjectVersion
AWS SAM으로 배포 패키지 업로드하기
AWS SAM으로 함수 코드, 구성, 의존성의 배포를 자동화할 수 있어요. AWS SAM은 서버리스 애플리케이션 정의를 위한 단순화된 문법을 제공하는 CloudFormation의 확장이에요. 다음 예시 템플릿은 Gradle이 쓰는 build/distributions 디렉터리에 배포 패키지가 있는 함수를 정의해요.
예시 template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Lambda application that calls the Lambda API.
Resources:
function:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/distributions/java-basic.zip
Handler: example.Handler
Runtime: java25
Description: Java function
MemorySize: 512
Timeout: 10
# Function's execution role
Policies:
- AWSLambdaBasicExecutionRole
- AWSLambda_ReadOnlyAccess
- AWSXrayWriteOnlyAccess
- AWSLambdaVPCAccessExecutionRole
Tracing: Active
함수를 만들려면 package와 deploy 명령을 사용해요. 이 명령들은 AWS CLI에 대한 사용자화로, 배포 패키지를 Amazon S3에 업로드하고 템플릿을 객체 URI로 다시 쓰며 함수 코드를 업데이트하는 다른 명령들을 감싸요.
다음 예시 스크립트는 Gradle 빌드를 실행하고 그 결과물인 배포 패키지를 업로드해요. 첫 실행 시 CloudFormation 스택을 만들고, 스택이 이미 있으면 스크립트가 스택을 업데이트해요.
예시 deploy.sh
#!/bin/bash
set -eo pipefail
aws cloudformation package --template-file template.yml --s3-bucket MY_BUCKET --output-template-file out.yml
aws cloudformation deploy --template-file out.yml --stack-name java-basic --capabilities CAPABILITY_NAMED_IAM
전체 동작 예시는 다음 샘플 애플리케이션을 참고하세요.
Java 샘플 Lambda 애플리케이션
- example-java — Lambda로 주문을 처리하는 방법을 보여주는 Java 함수. 커스텀 입력 이벤트 객체를 정의하고 역직렬화하며, AWS SDK를 사용하고, 로깅을 출력하는 방법을 보여줘요.
- java-basic — 단위 테스트와 가변 로깅 구성이 있는 최소 Java 함수 모음.
- java-events — Amazon API Gateway, Amazon SQS, Amazon Kinesis 같은 다양한 서비스의 이벤트를 처리하는 골격 코드가 있는 Java 함수 모음. 이 함수들은 최신 버전의 aws-lambda-java-events 라이브러리(3.0.0 이상)를 사용해요. 이 예시들은 AWS SDK를 의존성으로 요구하지 않아요.
- s3-java — Amazon S3의 알림 이벤트를 처리하고 Java Class Library(JCL)로 업로드된 이미지 파일에서 썸네일을 만드는 Java 함수.
- layer-java — Lambda 레이어로 의존성을 핵심 함수 코드와 분리해 패키징하는 방법을 보여주는 Java 함수.