Spring

[Spring / AWS] Spring Boot 3 + AWS Lambda 사용하기

Woong이 2024. 4. 26. 22:27
반응형

 

개요


개인 프로젝트에서 serverless에 배포를 고민하고 있다. 대표적인 클라우드 serverless 서비스인 AWS Lambda를 통해 프로젝트를 배포하는 것을 고려하고 있기 때문에 현재 프로젝트에 사용 중인 Spring과 AWS Lambda를 어떻게 연동하는지 알아보았다.

 

대표적으로 Spring Boot에 직접 연동하여 배포하는 방법과 Spring Clound Function을 사용해 연동하는 방법이 있다. 이 글에서는 먼저 Spring Boot에서 직접 연동하여 배포하는 방법을 적어본다.

 

 

1. 프로젝트 설정


Pre-requisites

 

build.gradle 설정

의존성 추가

dependencies {
    implementation ('org.springframework.boot:spring-boot-starter-web') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
    }

    implementation 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.1'
    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'

    // 생략
}

 

프로젝트 패키지 빌드

zip 파일 아카이브를 사용하여 직접 함수를 배포할 때 사용한다.

task buildZip(type: Zip) {
    from compileJava
    from processResources
    dependencies {
        exclude(group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat')
    }
    into('lib') {
        from(configurations.compileClasspath) {
            exclude 'tomcat-embed-*'
        }
    }
}

build.dependsOn buildZip

 

참고사항

의존성 추가와 빌드 설정에 내장 Tomcat을 제외했다. AWS Lambda에 배포 시, 내장 Tomcat은 필요하지 않기 때문에 제외했다.

내장 Tomcat을 제외하지 않아도 잘 작동하는 것을 확인했다. 따라서, 제외하는 것이 필수는 아닌 듯하다.

 

 

 

2. 예제 코드 작성


RequestStreamHandler 구현

implementation 'com.amazonaws.serverless:aws-serverless-java-container-springboot3:2.0.1'

build.gradle에 이 의존성을 추가하면 RequestStreamHandler라는 인터페이스를 제공받는다.

 

public interface RequestStreamHandler {

    void handleRequest(InputStream input, OutputStream output, Context context) throws IOException;
}

RequestStreamHandler는 handleRequest라는 추상 메서드를 갖고 있다. Spring Boot에서 AWS Lambda를 통해 들어오는 요청을 받기 위해서는 해당 인터페이스를 구현한 클래스를 따로 만들어야 한다.

 

public class StreamLambdaHandler implements RequestStreamHandler {

    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;

    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(SpringLambdaApplication.class);
        } catch (ContainerInitializationException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        handler.proxyStream(input, output, context);
    }
}

 

Controller

API 요청을 받는 역할은 보통 Spring 프로젝트에 사용하는 controller가 그대로 진행한다.

@RestController
public class ApiController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello! This is Spring Boot + AWS Lambda demo project.";
    }
}

 

여기서는 간단하게 "/hello"라는 경로로 요청이 들어오면 문자열을 응답으로 반환하는 간단한 API controller를 생성했다.

 

 

3. 빌드 및 배포


template.yml 생성

AWS SAM CLI을 통해 빌드 및 배포를 위해 template.yml을 작성해야 한다.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Spring Boot + AWS Lambda demo project

Globals:
  Api:
    # API Gateway regional endpoints
    EndpointConfiguration: REGIONAL

Resources:
  DemoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: demo.springlambda.handler.StreamLambdaHandler::handleRequest
      Runtime: java17
      CodeUri: .
      Architectures:
        - x86_64
      MemorySize: 2048
      Policies: AWSLambdaBasicExecutionRole
      Timeout: 60
      SnapStart:
        ApplyOn: PublishedVersions
      AutoPublishAlias: prod
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /{proxy+}
            Method: ANY

Outputs:
  DemoApplicationApi:
    Description: URL for application
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com'
    Export:
      Name: DemoApplicationApi

 

빌드 및 배포

빌드

sam build

 

Local에 함수 호출 테스트

sam local start-api
  • Local 사용 시, Docker 설치 및 실행 필수
  • Docker를 실행했는데도 오류가 생긴다면? --> 해결 방법

 

AWS Lambda에 배포

sam deploy --guided

 

 

 

References


 

Quick start Spring Boot3

A Java wrapper to run Spring, Spring Boot, Jersey, and other apps inside AWS Lambda. - aws/serverless-java-container

github.com

 

serverless-java-container/samples/springboot3 at main · aws/serverless-java-container

A Java wrapper to run Spring, Spring Boot, Jersey, and other apps inside AWS Lambda. - aws/serverless-java-container

github.com

 

반응형