AWS에서 Lambda와 Java 25, API Gateway 및 DynamoDB를 사용한 서버리스 애플리케이션 - 파트 1 샘플 애플리케이션

발행: (2026년 3월 17일 오전 12:31 GMT+9)
8 분 소요
원문: Dev.to

Source: Dev.to

이 시리즈 기사에서는 새로 출시된 Java 25 런타임을 사용한 Lambda로 AWS에서 서버리스 애플리케이션을 구현하는 방법을 설명합니다.
또한 API Gateway, DynamoDB, 그리고 인프라스트럭처‑코드(IaC) 정의를 위한 AWS SAM을 사용할 것입니다.

시리즈는 세 부분으로 나뉩니다:

  1. Baseline – 애플리케이션을 배포하고 최적화 없이 콜드/웜 시작 시간을 측정합니다.
  2. Cold‑start reductionLambda SnapStart, 프라이밍, GraalVM Native Image와 같은 기술을 탐구합니다.
  3. Extended example – DynamoDB를 관계형 서버리스 Amazon Aurora DSQL 데이터베이스로 교체하고 Hibernate ORM을 사용하는 부가 예제 시리즈입니다.

샘플 코드는 GitHub에서 확인할 수 있습니다: aws‑lambda‑java‑25‑dynamodb.

아키텍처 개요

샘플 애플리케이션은 간단한 제품 카탈로그를 제공합니다:

  • Create 제품 생성 (POST)
  • Retrieve 제품을 ID로 조회 (GET)

It uses the following AWS services:

서비스역할
Amazon API GatewayLambda 함수용 REST API를 노출합니다
AWS LambdaJava 25 코드(또는 GraalVM 네이티브 이미지)를 실행합니다
Amazon DynamoDB제품 데이터용 NoSQL 영속성 레이어
AWS SAM전체 스택을 위한 선언형 IaC

Assumption: 위 서비스와 AWS 서버리스 아키텍처에 대한 기본적인 이해가 있다고 가정합니다.

전제 조건

도구버전
Java25
Maven최신
AWS CLI최신
SAM CLI최신
GraalVM (선택 사항, 네이티브 이미지용)native-image 컴포넌트 포함 최신

우선 Java 25 버전을 빌드하고 배포한 뒤, 이후에 GraalVM 네이티브 이미지를 컴파일하고 맞춤 런타임으로 실행합니다.

Source:

AWS SAM 템플릿 – IaC 하이라이트

아래는 template.yaml의 관련 부분입니다. Lambda 함수에 영향을 주는 섹션만 표시했습니다.

전역 함수 설정

Globals:
  Function:
    CodeUri: .
    Runtime: java25
    # SnapStart (uncomment to enable)
    # SnapStart:
    #   ApplyOn: PublishedVersions
    Timeout: 30
    MemorySize: 1024
    Architectures:
      - x86_64
    Environment:
      Variables:
        REGION: !Sub ${AWS::Region}
        PRODUCT_TABLE_NAME: !Ref ProductsTable
        # … other variables …

GetProductById 함수

GetProductByIdFunction:
  Type: AWS::Serverless::Function
  Properties:
    FunctionName: GetProductByIdJava25WithDynamoDB
    AutoPublishAlias: liveVersion
    Handler: software.amazonaws.example.product.handler.GetProductByIdHandler::handleRequest
    Policies:
      - DynamoDBReadPolicy:
          TableName: !Ref ProductsTable
    Events:
      GetRequestById:
        Type: Api
        Properties:
          RestApiId: !Ref MyApi
          Path: /products/{id}
          Method: get

PostProduct 함수

PostProductJava25WithDynamoDB 정의는 동일한 패턴을 따릅니다 (간략히 생략).

Lambda 핸들러 – GetProductByIdHandler

@Override
public APIGatewayProxyResponseEvent handleRequest(
        APIGatewayProxyRequestEvent requestEvent,
        Context context) throws JsonProcessingException {

    var id = requestEvent.getPathParameters().get("id");
    var optionalProduct = productDao.getProduct(id);

    if (optionalProduct.isEmpty()) {
        return new APIGatewayProxyResponseEvent()
                .withStatusCode(HttpStatusCode.NOT_FOUND)
                .withBody("Product with id = " + id + " not found");
    }

    return new APIGatewayProxyResponseEvent()
            .withStatusCode(HttpStatusCode.OK)
            .withBody(objectMapper.writeValueAsString(optionalProduct.get()));
}
  • 이 메서드는 APIGatewayProxyRequestEvent를 받습니다 (API Gateway에 의해 호출됨).
  • id 경로 파라미터를 추출하고, productDao.getProduct(id)를 통해 DynamoDB를 조회한 뒤, 404 또는 200 응답을 JSON 페이로드와 함께 반환합니다.

CreateProductHandler(POST에 사용)는 동일한 구조를 따릅니다.

도메인 모델 – 제품 엔터티

public record Product(String id, String name, BigDecimal price) {}

제품을 나타내는 간단한 불변 레코드입니다.

영속성 레이어 – ProductDao (발췌)

public class ProductDao {

    private final DynamoDbClient dynamoDb;
    private final String tableName;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public ProductDao(DynamoDbClient dynamoDb, String tableName) {
        this.dynamoDb = dynamoDb;
        this.tableName = tableName;
    }

    public Optional getProduct(String id) {
        GetItemResponse response = dynamoDb.getItem(
                GetItemRequest.builder()
                        .tableName(tableName)
                        .key(Map.of("id", AttributeValue.builder().s(id).build()))
                        .build());

        if (response.hasItem()) {
            var item = response.item();
            var product = objectMapper.convertValue(item, Product.class);
            return Optional.of(product);
        }
        return Optional.empty();
    }

    // … methods for putItem, deleteItem, etc. …
}
  • AWS SDK for Java 2.x를 사용하여 DynamoDB와 상호작용합니다.
  • getProductGetItemRequest를 생성하고 실행한 뒤, 결과를 Product 레코드로 매핑합니다.

다음 단계

  1. 배포 SAM 스택 (sam build && sam deploy).
  2. 호출 API 엔드포인트를 실행하고 콜드/웜 시작 시간을 기록합니다.
  3. SnapStart 활성화 (주석 처리된 SnapStart 블록을 해제)하고 다시 측정합니다.
  4. GraalVM 네이티브 이미지 빌드하고 맞춤 런타임으로 배포하여 콜드 스타트 감소를 추가로 진행합니다.

다음 기사에서는 각 최적화 기술을 더 깊이 파고들 예정이니 기대해 주세요!

DynamoDB에서 제품 조회

GetItemResponse getItemResponse = dynamoDbClient.getItem(
    GetItemRequest.builder()
        .key(Map.of("PK", AttributeValue.builder().s(id).build()))
        .tableName(PRODUCT_TABLE_NAME)
        .build());

if (getItemResponse.hasItem()) {
    return Optional.of(ProductMapper.productFromDynamoDB(getItemResponse.item()));
} else {
    return Optional.empty();
}

여기서는 DynamoDbClient 인스턴스를 사용하여 DynamoDB 테이블을 조회하는 GetItemRequest를 생성합니다.
테이블 이름은 System.getenv("PRODUCT_TABLE_NAME")를 통해 환경 변수( AWS SAM 템플릿에서 설정)에서 가져옵니다.
제품이 존재하면, 사용자 정의 ProductMapper가 DynamoDB 항목을 Product 엔티티로 변환합니다.

빌드 및 배포

# Build the application
mvn clean package

# Deploy with SAM (guided mode)
sam deploy -g

배포가 완료되면 SAM은 맞춤형 Amazon API Gateway URL을 반환합니다. 이 URL은 제품을 생성하고 조회하는 데 사용됩니다. API는 API 키로 보호되며, X-API-Key 헤더에 포함하여 전송해야 합니다(template.yaml에 정의된 MyApiKey를 참조).

API 키: a6ZbcDefQW12BN56WEVDDB25

예시 요청

제품 생성 (ID = 1)

curl -X PUT \
     -d '{ "id": 1, "name": "Print 10x13", "price": 0.15 }' \
     -H "X-API-Key: a6ZbcDefQW12BN56WEVDDB25" \
     https://{API_GATEWAY_URL}/prod/products

제품 조회 (ID = 1)

curl -H "X-API-Key: a6ZbcDefQW12BN56WEVDDB25" \
     https://{API_GATEWAY_URL}/prod/products/1

({API_GATEWAY_URL}sam deploy가 반환한 URL로 교체하십시오.)

다음은?

이 글에서는 샘플 애플리케이션을 소개했습니다. 다음 글에서는 최적화 없이 Lambda 함수의 콜드‑ 및 웜‑시작 시간을 측정합니다.

추후에는 관계형 서버리스 Amazon Aurora (PostgreSQL) 데이터베이스Hibernate ORM을 사용해 동일한 Lambda 성능 측정을 수행할 예정입니다.

내용이 마음에 드신다면:

  • GitHub에서 제 저장소에 Star를 달아 주세요
  • 더 많은 기술 글과 앞으로 있을 공개 강연 소식을 받으려면 팔로우 해 주세요
  • 추가 자료는 제 개인 웹사이트를 방문해 주세요

감사합니다!

0 조회
Back to Blog

관련 글

더 보기 »

트라비고

Gemini와 함께 말하는 속도만큼 빠르게 여행하세요! 라이브 에이전트가 몰입형 스토리텔링 및 3D 내비게이션과 만나는 곳. 이 프로젝트는 Gemini Live Ag...에 진입하기 위해 만들어졌습니다.