Java의 DynamoDB Query (AWS SDK v2)

AWS SDK for Java 2.x의 queryPaginator는 컬렉션처럼 보이지만 컬렉션이 아닙니다. 지연 평가되는 재순회 가능 객체이며, 그 차이는 두 번째로 순회하는 순간 청구서에 드러납니다. 애초에 Query가 맞는 읽기인지에 대해서는 Query vs. Scan을 보세요.

코드

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;

public class QueryExample {
    public static void main(String[] args) {
        try (DynamoDbClient ddb = DynamoDbClient.builder()
                .region(Region.US_EAST_1)
                .build()) {

            Map<String, String> names = new HashMap<>();
            names.put("#hashKey", "Artist");
            names.put("#rangeKey", "SongTitle");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":hashKeyValue", AttributeValue.builder().s("Arturo Sandoval").build());
            values.put(":rangeKeyValue", AttributeValue.builder().s("C").build());

            QueryRequest request = QueryRequest.builder()
                    .tableName("Music")
                    .keyConditionExpression(
                            "#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)")
                    .expressionAttributeNames(names)
                    .expressionAttributeValues(values)
                    .build();

            List<Map<String, AttributeValue>> items = new ArrayList<>();
            for (QueryResponse page : ddb.queryPaginator(request)) {
                items.addAll(page.items());
            }
            System.out.println("Found " + items.size() + " items");
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
        }
    }
}

QueryIterable은 순회할 때마다 쿼리를 다시 실행합니다

곡마다 약 3.9 KB이고 모두 Artist = "Arturo Sandoval" 아래에 있는 600곡짜리 픽스처에 대해, ddb.queryPaginator(request)는 2.6 ms 만에 반환되었고 아무것도 보내지 않았습니다. 그런 다음 동일한 QueryIterable 객체를 두 번 순회했습니다:

queryPaginator(request) returned in 2.60 ms   (class QueryIterable, 0 requests)
iteration 1: pages=3  items=600  capacity=284.5
iteration 2: pages=3  items=600  capacity=284.5   <- same object

변수 하나에 대한 for 루프 두 개, 읽기 단위 569. 페이지는 전혀 캐시되지 않았고, 순회할 때마다 LastEvaluatedKey를 처음부터 다시 따라갑니다. 항목이 두 번 필요하다면 예제처럼 순회 가능 객체를 한 번만 List로 비워 담으세요.

같은 지연 평가의 이면은 오류가 드러나는 지점입니다. 키 조건에서 파티션 키를 빠뜨린 요청을 만들어도 queryPaginator는 불평 없이 받아들입니다. 아직 아무 호출도 일어나지 않았기 때문입니다:

queryPaginator(bad) constructed without throwing
threw on iteration: DynamoDbException / ValidationException /
Query condition missed key schema element / http 400

빌더를 감싼 try-catch는 아무것도 잡지 못합니다. 루프를 감싸야 하며, 그래서 예제는 전체 블록을 하나의 try 안에 넣습니다.

2026-07-28에 OpenJDK 26.0.1의 software.amazon.awssdk:dynamodb 2.49.4로 DynamoDB Local(amazon/dynamodb-local)에 대해 측정했습니다.

설명

  • ddb.queryPaginator(request).items() 는 페이지를 Iterable<Map<String, AttributeValue>>로 펼치고 뒤에서 페이지네이션을 처리하므로, 항목만 필요할 때는 예제의 2단계 루프가 하나로 줄어듭니다. SdkIterable이기도 하므로 .stream()도 동작합니다.
  • 빌더에서 숫자는 String입니다. AttributeValue.builder().n("1994").n(1994)의 오타가 아닙니다. n() 설정자는 java.lang.String을 받는데, DynamoDB가 이진 부동소수점 반올림을 피하려고 숫자를 십진 텍스트로 전송하기 때문입니다. Java int를 넘기면 컴파일되지 않습니다.
  • keyConditionExpression 은 파티션 키에 대한 등호와 정렬 키 조건을 최대 하나(=, <, <=, >, >=, BETWEEN, begins_with) 받습니다. .scanIndexForward(false)는 순서를 뒤집고, .indexName("...")은 보조 인덱스로 대상을 바꿉니다.
  • Enhanced Client는 또 다른 사용성 선택지입니다. software.amazon.awssdk.enhanced.dynamodbMap<String, AttributeValue> 대신 애너테이션이 붙은 빈을 매핑하며, 그 query는 위에서 측정한 것과 동일한 지연 재순회 의미론을 가진 PageIterable<T>를 반환합니다.

시각적으로 해보기

이 예제의 #hashKey#rangeKey는 어느 것도 강제되지 않은 별칭입니다. ArtistSongTitle도 AWS의 573개 예약어 목록에 없습니다. 예약어 검사기는 여러분의 속성 이름 중 정말로 # 처리가 필요한 것이 무엇인지 알려 주므로, 별칭 맵이 관행적 흉내에 그치지 않게 해 줍니다.

QueryRequest를 만들기 전에 실제 테이블에 키 조건을 시험해 보려면 DynoTable을 다운로드해서 결과를 그리드에서 페이지로 넘겨 보세요.

관련 예제

참고 자료

이 요청을 시각적으로 만들기

무료 DynamoDB 쿼리 빌더에서 이 작업을 구성하세요 — 키 조건, 필터, 인덱스, Limit, 정렬 순서, 페이지네이션 루프 — 그리고 실행 가능한 SDK v3, CLI, boto3 프로그램으로 다시 복사하세요.

DynamoDB 쿼리 빌더 열기

Console 없이 DynamoDB 작업하기

DynamoDB로는 실행할 수 없는 진짜 SQL(JOINs, GROUP BY, 집계)을 실행하는 빠른 DynamoDB 데스크톱 클라이언트. 시각적 편집과 여러분 자신의 Bedrock 키로 동작하는 AI 에이전트를 제공합니다.

30일 무료 체험, 신용카드 불필요 — 이후 기간 제한 없는 무료 요금제.