티스토리 뷰
반응형
Spring Cloud Function(Spring Boot) 프로젝트를 AWS Lambda에 배포하는 방법에 대해 기록해보겠습니다.
1. 프로젝트 gradle 설정 샘플
ext {
set('springCloudVersion', "2020.0.2")
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-function-adapter-aws'
implementation 'com.amazonaws:aws-lambda-java-core:1.2.1'
implementation 'com.amazonaws:aws-lambda-java-events:3.8.0'
}
- Spring Cloud Function을 위한 의존성, AWS에 Lamda에 배포하기 위한 의존성, AWS Lambda 이벤트를 다루기 위한 의존성이 필요합니다.
2. 예제 코드
- 예제로 사용할 코드는 name과 age를 입력값으로 넣어주고, age값에 따라 성인인지 아닌지를 판단하는 간단한 코드입니다.
- 사용되는 클래스는 스프링 컨테이너에서 다뤄야 하므로 모두 Bean으로 등록되어야 합니다.
- 사용되는 클래스는 Funtion, Consumer, Supplier와 같은 함수형 인터페이스를 구현해야합니다.
@Component // 하나의 함수로써 노출되는 스프링 Bean 객체
public class AdultJudge implements Function<UserRequest, AdultJudgeResponse> {
@Override
public AdultJudgeResponse apply(UserRequest request) {
String name = request.getName();
if (request.getAge() > 20) {
return new AdultJudgeResponse(name + "은(는) 성인입니다.");
}
return new AdultJudgeResponse(name + "은(는) 성인이 아닙니다.");
}
}
//요청 DTO
public class UserRequest {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
//응답 DTO
public class AdultJudgeResponse {
private String result;
public AdultJudgeResponse(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
- 만약 @Component 애노테이션 없이 특정 패키지의 클래스들을 Function으로써 스캔을 하고 싶은 경우 properties에 아래와 같이 패키지명을 설정합니다.
spring.cloud.function.scan.packages=me.siyoon.springbootlambdatest.functions
3. 로컬환경에서 테스트하기
- 로컬에서 테스트 하기 위해서는 spring-cloud-starter-function-web 의존 설정이 추가로 필요합니다.
dependencies {
...
// 로컬테스트를 위한 의존성 설정. aws로 deploy시에는 필요없다.
implementation 'org.springframework.cloud:spring-cloud-starter-function-web'
}
요청 & 응답
POST http://localhost:8080/adultJudge
Content-Type: application/json
{
"name": "siyoon",
"age": 13
}
POST http://localhost:8080/adultJudge
HTTP/1.1 200
scf-func-name: adultJudge
host: localhost:8080
Content-Type: application/json
{
"result": "siyoon은(는) 성인이 아닙니다."
}
- 요청시에 엔드포인트는 Function의 Bean 이름으로 설정합니다.
4. AWS에 배포하기
AWS Handlers 생성
- AWS Lamda가 Spring Cloud Function 프로젝트를 다루기 위해서 Spring Cloud Function AWS에서 제공하는 핸들러를 상속받은 클래스가 필요합니다.
import org.springframework.cloud.function.adapter.aws.SpringBootStreamHandler;
public class LambdaHandlers extends SpringBootStreamHandler {
}
- 해당 클래스는 (HTTP 프로토콜과 같은) 요청정보를 AWS Lamda에서 다룰 수 있도록 하고 프로젝트에 접근할 수 있도록 도와줍니다. 별도로 구현한 사항이 없어 보이지만 상속받은 SpringBootStreamHandler를 살펴보면 InputStream과 OutputStream을 입력받고 적절한 핸들러를 찾아서 실행하는 handlerRequest 메서드를 확인할 수 있습니다.
zip 파일로 만들기 위한 task 추가
- 프로젝트를 zip파일로 압축하기 위한 task를 추가합니다. (jar파일로 만든 경우에 이상하게 잘 안되어서 zip 파일로 만들겠습니다.)
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from configurations.runtimeClasspath
}
}
- gradle buildZip 를 실행하면 ./build/distributions 디렉토리에 생성된 zip 파일을 확인 할 수 있습니다.
AWS Lambda Function 생성하기
- AWS Lambda 대시보드에서 새로운 Function을 생성합니다.
- 생성된 Function에 deploy할 프로젝트를 업로드합니다. (Code source - Upload from)
- 간단한 프로젝트이지만 10MB를 초과하여 S3에 업로드 한 후, 해당 주소를 사용해서 업로드 하였습니다. (플로그인을 사용하여서 파일 사이즈를 줄이는 방법도 있지만 이번 포스팅에서는 다루지 않습니다.)
- 프로젝트내의 Handler 클래스 위치를 입력합니다. (Runtime settings - Edit)
- 환경변수에 FUNCTION_NAME과 MAIN_CLASS를 입력합니다. (Configurtaion - Environment variables - Edit)
- FUNCTION_NAME은 원하는 Bean 이름을, MAIN_CLASS에는 main 메서드가 위치한 클래스명을 입력합니다.
AWS Lambda Function 테스트하기
- Test 탭에서 Json 형식의 입력값을 설정한후 Test를 진행해보겠습니다.
- 응답결과를 확인할 수 있습니다. 다만 초기에 요청은 Spring 컨테이너가 실행되는 시간까지 합쳐져서 거의 10초정도의 시간이 소요되었고, 2번째 요청부터는 1ms로 빠르게 진행되었습니다. 5분이상 요청이 없을 경우 다시 Spring 컨테이너를 실행해야 해서 이런 경우에는 실사용하기 어려울 수 있습니다. (Spring Native가 안정화 되면 이런 문제를 해결 할 수 있을 것으로 기대됩니다.)
- 만약 테스트가 진행되지 않는다면 Lamda의 동시성(Concurrency) 설정을 확인해보세요.
- 다음 포스팅에서는 API Gateway를 트리거로 등록하여 실제 HTTP 요청과 AWS Lambda를 매핑해보도록 하겠습니다.
참고
반응형
'AWS' 카테고리의 다른 글
AWS SAM 시작하기 (0) | 2022.07.24 |
---|---|
AWS Serverless Application Model이란 무엇인가? (AWS SAM) (0) | 2022.07.24 |
AWS 청구비용 환불 신청하기 (2) | 2022.02.06 |
AWS Lambda에서 AWS SQS 실행하기 (Node.js) (0) | 2021.08.16 |
댓글