

# DynamoDB에서 테이블 쿼리
<a name="Query"></a>

Amazon DynamoDB에서 `Query` API 작업을 사용하여 프라이머리 키 값을 기반으로 항목을 찾을 수 있습니다.

파티션 키 속성의 이름과 해당 속성의 단일 값을 제공해야 합니다. `Query`는 해당 파티션 키 값을 갖는 모든 항목을 반환합니다. 선택에 따라 정렬 키 속성을 제공하고 비교 연산자를 사용하여 검색 결과의 범위를 좁힐 수 있습니다.

요청 구문, 응답 파라미터 및 추가 예제와 같은 `Query` 사용 방법에 대한 자세한 내용은 *Amazon DynamoDB API 참조*의 [쿼리](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)를 참조하세요.

**Topics**
+ [DynamoDB에서의 쿼리 작업에 대한 키 조건 표현식](Query.KeyConditionExpressions.md)
+ [DynamoDB에서의 쿼리 작업에 대한 필터 표현식](Query.FilterExpression.md)
+ [DynamoDB의 테이블 쿼리 결과 페이지 매김](Query.Pagination.md)
+ [DynamoDB에서의 쿼리 작업에 대한 기타 측면](Query.Other.md)

# DynamoDB에서의 쿼리 작업에 대한 키 조건 표현식
<a name="Query.KeyConditionExpressions"></a>

키 조건 표현식에서는 첫 번째 문자가 `a-z` 또는 `A-Z`이고 나머지 문자(두 번째 문자부터 시작, 있는 경우)가 `a-z`, `A-Z` 또는 `0-9`인 경우에 한해 속성 이름은 아무거나 사용할 수 있습니다. 또한 속성 이름이 DynamoDB 예약어가 되어서는 안 됩니다. (예약어 전체 목록은 [DynamoDB의 예약어](ReservedWords.md) 단원을 참조하세요.) 속성 이름이 이러한 요건을 만족하지 않으면 표현식 속성 이름을 자리 표시자로 정의해야 합니다. 자세한 내용은 [DynamoDB의 표현식 속성 이름(별칭)](Expressions.ExpressionAttributeNames.md) 섹션을 참조하세요.

일정한 파티션 키 값을 갖는 항목들에 대해서는 DynamoDB가 정렬 키 값을 기준으로 순서를 정렬하여 모두 함께 저장합니다. `Query` 작업을 할 때는 DynamoDB는 정렬된 순서대로 항목을 가져온 다음 `FilterExpression`과 모든 `KeyConditionExpression`(있는 경우)을 사용해 항목을 처리합니다. 그러면 클라이언트에게는 `Query` 결과만 다시 보내집니다.

`Query` 작업은 항상 결과 집합을 반환합니다. 일치하는 항목이 없다면 결과 집합은 비어 있습니다.

`Query` 결과는 항상 정렬 키 값을 기준으로 정렬됩니다. 정렬 키의 데이터 형식이 `Number`이면 결과가 숫자 순서대로 반환됩니다. 그렇지 않으면 결과가 UTF-8 바이트 순서로 반환됩니다. 기본적으로 정렬 순서는 오름차순입니다. 오름차순을 역순으로 바꾸려면 `ScanIndexForward` 파라미터를 `false`로 설정하면 됩니다.

단일 `Query` 작업은 최대 1MB의 데이터를 가져올 수 있습니다. 이러한 크기 제한은 `FilterExpression` 또는 `ProjectionExpression`이 결과에 반영되기 전에 적용됩니다. 응답에 `LastEvaluatedKey`가 존재하고 null이 아니라면 결과 집합을 페이지 매김해야 합니다([DynamoDB의 테이블 쿼리 결과 페이지 매김](Query.Pagination.md) 참조).

## 키 조건 표현식 예제
<a name="Query.KeyConditionExpressions-example"></a>

검색 기준을 지정하려면 테이블 또는 인덱스에서 읽을 항목을 결정하는 문자열인 *키 조건 표현식*을 사용합니다.

파티션 키 이름 및 값은 등식 조건으로 지정해야 합니다. 키 조건 표현식에는 키가 아닌 속성을 사용할 수 없습니다.

정렬 키의 두 번째 조건(있는 경우)은 옵션으로 입력할 수 있습니다. 단, 정렬 키 조건은 다음 중 한 가지 비교 연산자를 사용해야 합니다.
+ `a = b` - 속성 *a*가 값 *b*와 같은 경우 true
+ `a < b` - *a*가 *b*보다 작은 경우 true
+ `a <= b` - *a*가 *b*보다 작거나 같은 경우 true
+ `a > b` - *a*가 *b*보다 큰 경우 true
+ `a >= b` - *a*가 *b*보다 크거나 같은 경우 true
+ `a BETWEEN b AND c` - *a*가 *b*보다 크거나 같고 *c*보다 작거나 같은 경우 true

다음 함수도 지원됩니다.
+ `begins_with (a, substr)` - `a` 속성 값이 특정 하위 문자열로 시작하는 경우 true

다음 AWS Command Line Interface(AWS CLI) 예제는 키 조건 표현식의 사용을 보여 줍니다. 이 표현식들은 실제 값이 아닌 자리 표시자(`:name` 및 `:sub`)를 사용합니다. 자세한 내용은 [DynamoDB의 표현식 속성 이름(별칭)](Expressions.ExpressionAttributeNames.md) 및 [DynamoDB에서 표현식 속성 값 사용](Expressions.ExpressionAttributeValues.md) 단원을 참조하세요.

**Example**  
`Thread` 테이블에 대한 쿼리를 실행하여 특정 `ForumName`(파티션 키)을 찾습니다. 쿼리 결과에 따라 `ForumName` 값을 갖는 항목을 모두 읽어옵니다. 정렬 키(`Subject`)가 `KeyConditionExpression`에 추가되지 않았기 때문입니다.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name" \
    --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
```

**Example**  
`Thread` 테이블에 대한 쿼리를 실행하여 특정 `ForumName`(파티션 키)을 찾습니다. 하지만 이번에는 `Subject`(정렬 키)를 갖는 항목만 반환됩니다.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name and Subject = :sub" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":name":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"}
}
```

**Example**  
`Reply` 테이블에 대해 쿼리를 실행하여 특정 `Id`(파티션 키)를 찾습니다. 하지만 `ReplyDateTime`(정렬 키)이 몇 가지 문자로 시작되는 항목만 반환됩니다.  

```
aws dynamodb query \
    --table-name Reply \
    --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
    ":dt":{"S":"2015-09"}
}
```

# DynamoDB에서의 쿼리 작업에 대한 필터 표현식
<a name="Query.FilterExpression"></a>

`Query` 결과를 한층 더 좁혀야 하는 경우 선택적으로 필터 표현식을 제공할 수 있습니다. *필터 표현식*은 `Query` 결과 내에서 어떤 항목을 반환할지를 결정합니다. 다른 모든 결과는 폐기됩니다.

필터 표현식은 `Query`이 완료된 후 결과가 반환되기 전에 적용됩니다. 따라서 필터 표현식이 있는지 여부와 상관없이 `Query`은 동일한 양의 읽기 용량을 사용합니다.

`Query` 작업은 최대 1MB의 데이터를 가져올 수 있습니다. 이 제한은 필터 표현식이 평가되기 전에 적용됩니다.

필터 표현식에는 파티션 키 또는 정렬 키 속성이 포함될 수 없습니다. 필터 표현식이 아닌 키 조건 표현식에 있는 속성을 지정해야 합니다.

필터 표현식의 구문은 키 조건 표현식의 구문과 유사합니다. 필터 표현식에는 키 조건 표현식과 동일한 비교기, 함수 및 논리적 연산자를 사용할 수 있습니다. 또한 필터 표현식에는 같지 않음 연산자(`<>`), `OR` 연산자, `CONTAINS` 연산자, `IN` 연산자, `BEGINS_WITH` 연산자, `BETWEEN` 연산자, `EXISTS` 연산자 및 `SIZE` 연산자를 사용할 수 있습니다. 자세한 내용은 [DynamoDB에서의 쿼리 작업에 대한 키 조건 표현식](Query.KeyConditionExpressions.md) 및 [필터 및 조건 표현식 구문](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Syntax) 단원을 참조하세요.

**Example**  
다음 AWS CLI 예제에서는 `Thread` 테이블에 대해 쿼리를 실행하여 특정 `ForumName`(파티션 키)과 `Subject`(정렬 키)를 찾아봅니다. 찾은 항목 중에서 가장 인기 있는 토론 스레드가 반환됩니다. 즉, 일정 수 이상의 `Views`가 있는 스레드만 반환됩니다.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :fn and Subject begins_with :sub" \
    --filter-expression "#v >= :num" \
    --expression-attribute-names '{"#v": "Views"}' \
    --expression-attribute-values file://values.json
```
`--expression-attribute-values`의 인수는 `values.json` 파일에 저장됩니다.  

```
{
    ":fn":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"},
    ":num":{"N":"3"}
}
```
`Views`는 DynamoDB에서 예약어이므로([DynamoDB의 예약어](ReservedWords.md) 참조) 이 예제에서는 `#v`를 자리 표시자로 사용합니다. 자세한 내용은 [DynamoDB의 표현식 속성 이름(별칭)](Expressions.ExpressionAttributeNames.md) 섹션을 참조하세요.

**참고**  
필터 표현식은 `Query` 결과 집합에서 항목을 제거합니다. 많은 수의 항목을 반환할 것으로 예상되지만 해당 항목 중 대부분을 폐기해야 하는 경우 가능하다면 `Query`를 사용하지 마세요.

# DynamoDB의 테이블 쿼리 결과 페이지 매김
<a name="Query.Pagination"></a>

DynamoDB는 `Query` 작업 결과의 *페이지를 매깁니다*. 페이지를 매기면 `Query` 결과는 크기가 1MB 이하인 데이터 ‘페이지’로 분리됩니다. 애플리케이션은 결과의 첫 번째 페이지를 처리한 다음 두 번째 페이지를 처리하고 이런 식으로 계속할 수 있습니다.

단일 `Query`는 1MB 크기 한도 내에 맞는 결과 집합만 반환합니다. 추가 결과가 있는지 확인하고 이러한 결과를 한번에 한 페이지에 가져오려면 애플리케이션에서 다음을 수행해야 합니다.

1. 하위 수준 `Query` 결과를 확인합니다.
   + 결과가 `LastEvaluatedKey` 요소를 포함하고 null이 아닌 경우 2단계로 계속합니다.
   + 결과에 `LastEvaluatedKey`가 *없는* 경우 더 이상 가져올 항목이 없습니다.

1. 동일한 `KeyConditionExpression`을 사용하여 `Query`를 구성합니다. 그러나 이번에는 1단계에서 `LastEvaluatedKey` 값을 가져와서 새로운 `ExclusiveStartKey` 요청의 `Query` 파라미터로 사용합니다.

1. 새로운 `Query` 요청을 실행합니다.

1. 1단계로 이동합니다.

다시 말해서, `LastEvaluatedKey` 응답의 `Query`를 다음 `ExclusiveStartKey` 요청에 대한 `Query`로 사용해야 합니다. `LastEvaluatedKey` 응답에 `Query` 요소가 없는 경우 결과의 최종 페이지를 검색한 것입니다. `LastEvaluatedKey`가 비어 있지 않는 경우 결과 집합에 데이터가 더 있음을 의미하는 것은 아닙니다. 결과 집합의 마지막 페이지를 알 수 있는 유일한 방법은 `LastEvaluatedKey`가 비어 있을 때입니다.

AWS CLI를 사용하여 이 동작을 볼 수 있습니다. AWS CLI는 `LastEvaluatedKey`가 결과에 더 이상 없을 때까지 하위 수준 `Query` 요청을 DynamoDB에 반복적으로 보냅니다. 특정 연도의 영화 제목을 검색하는 다음 AWS CLI 예제를 살펴보세요.

```
aws dynamodb query --table-name Movies \
    --projection-expression "title" \
    --key-condition-expression "#y = :yyyy" \
    --expression-attribute-names '{"#y":"year"}' \
    --expression-attribute-values '{":yyyy":{"N":"1993"}}' \
    --page-size 5 \
    --debug
```

일반적으로 AWS CLI에서는 페이지 매김이 자동으로 처리됩니다. 그러나 이 예제에서는 AWS CLI `--page-size` 파라미터가 페이지당 항목 수를 제한합니다. `--debug` 파라미터는 요청 및 응답에 대한 하위 수준 정보를 출력합니다.

예제를 실행하면 DynamoDB의 첫 응답이 다음과 유사합니다.

```
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'
```

응답의 `LastEvaluatedKey`는 가져온 항목이 전부가 아님을 나타냅니다. 그러면 AWS CLI는 DynamoDB에 다른 `Query` 요청을 보냅니다. 이 요청과 응답 패턴은 마지막 응답이 반환될 때까지 계속됩니다.

```
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'
```

`LastEvaluatedKey`가 없으면 가져올 항목이 더 이상 없음을 나타냅니다.

**참고**  
AWS SDK는 하위 수준 DynamoDB 응답(`LastEvaluatedKey`의 유무 포함)을 처리하여 `Query` 결과 페이지 매김에 대해 다양한 추상을 제공합니다. 예를 들어, SDK for Java 문서 인터페이스는 `java.util.Iterator` 지원을 제공하므로 한 번에 하나씩 결과를 볼 수 있습니다.  
다양한 프로그래밍 언어의 코드 예제를 보려면 [Amazon DynamoDB 시작 안내서](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/) 및 해당 언어의 AWS SDK 설명서를 참조하세요.

`Query` 작업의 `Limit` 파라미터를 사용하여 결과 세트의 항목 수를 제한하여 페이지 크기를 줄일 수도 있습니다.

DynamoDB를 사용한 쿼리 방법에 대한 자세한 내용은 [DynamoDB에서 테이블 쿼리](Query.md) 단원을 참조하세요.

# DynamoDB에서의 쿼리 작업에 대한 기타 측면
<a name="Query.Other"></a>

이 섹션에서는 결과 크기 제한, 스캔된 항목과 반환된 항목 수 계산 비교, 읽기 용량 소비 모니터링, 읽기 일관성 제어 등 DynamoDB 쿼리 작업의 추가 측면을 다룹니다.

## 결과 세트의 항목 수 제한
<a name="Query.Limit"></a>

`Query` 작업을 사용하여 읽는 항목 수를 제한할 수 있습니다. 이렇게 하려면 `Limit` 파라미터를 원하는 최대 항목 수로 설정합니다.

예를 들어 `Query` 값이 `Limit`이고 필터 표현식이 없는 상태에서 테이블을 `6`한다고 가정합니다. `Query` 결과에는 테이블에서 요청의 키 조건 표현식과 일치하는 처음 6개의 항목이 포함됩니다.

이제 필터 표현식을 `Query`에 추가한다고 가정합니다. 이 경우 DynamoDB는 최대 6개의 항목을 읽은 다음 필터 표현식과 일치하는 항목만 반환합니다. DynamoDB에서 더 많은 항목을 계속 읽은 경우 필터 표현식과 일치하는 항목이 더 많더라도 최종 `Query` 결과에는 여섯 개 이하의 항목이 포함됩니다.

## 결과 내 항목 수 계산
<a name="Query.Count"></a>

`Query` 응답에는 기준과 일치하는 항목 외에도 다음 요소가 포함됩니다.
+ `ScannedCount` - 필터 표현식(있는 경우)을 적용하기 *전*에 키 조건 표현식과 일치한 항목 수입니다.
+ `Count` - 필터 표현식(있는 경우)을 적용한 *후*에 남아 있는 항목 수입니다.

**참고**  
필터 표현식을 사용하지 않으면 `ScannedCount`와 `Count`는 동일한 값을 갖습니다.

`Query` 결과 집합의 크기가 1MB보다 크면 `ScannedCount`와 `Count`는 총 항목 수의 일부만 표시합니다. 모든 결과를 검색하려면 여러 `Query` 작업을 수행해야 합니다([DynamoDB의 테이블 쿼리 결과 페이지 매김](Query.Pagination.md) 참조).

각 `Query` 응답에는 해당하는 특정 `ScannedCount` 요청에 따라 처리된 항목의 `Count`와 `Query`가 포함됩니다. 모든 `Query` 요청의 총계를 얻으려면 `ScannedCount`와 `Count`의 누계를 계산할 수 있습니다.

## 쿼리에서 사용된 용량 단위
<a name="Query.CapacityUnits"></a>

파티션 키 속성의 이름과 해당 속성의 단일 값을 제공하기만 하면 모든 테이블 또는 보조 인덱스를 `Query`할 수 있습니다. `Query`는 해당 파티션 키 값을 갖는 모든 항목을 반환합니다. 필요에 따라 정렬 키 속성을 제공하고 비교 연산자를 사용하여 검색 결과의 범위를 좁힐 수 있습니다. `Query` API 작업은 다음과 같은 읽기 용량 단위를 사용합니다.


****  

| 다음을 `Query`하는 경우... | DynamoDB는 다음에서 읽기 용량 단위를 사용합니다... | 
| --- | --- | 
| 표 | 테이블의 할당된 읽기 용량. | 
| 글로벌 보조 인덱스 | 인덱스의 할당된 읽기 용량. | 
| 로컬 보조 인덱스 | 기본 테이블의 프로비저닝된 읽기 용량. | 

기본적으로, `Query` 작업은 얼마나 많은 읽기 용량을 사용하는지에 대한 데이터를 반환하지 않습니다. 하지만 `ReturnConsumedCapacity` 요청에서 `Query` 파라미터를 지정하여 이 정보를 얻을 수 있습니다. 다음은 `ReturnConsumedCapacity`에 대한 유효한 설정입니다.
+ `NONE` - 사용된 용량 데이터가 반환되지 않습니다. (이 값이 기본값입니다.)
+ `TOTAL` - 사용된 읽기 용량 단위의 집계 수가 응답에 포함됩니다.
+ `INDEXES` - 액세스한 각 테이블 및 인덱스에 사용된 용량과 함께 사용된 읽기 용량 단위의 집계 수가 응답에 표시됩니다.

DynamoDB는 애플리케이션에 반환되는 데이터 양이 아닌 항목 개수와 항목 크기를 기준으로 사용된 읽기 용량 단위의 수를 계산합니다. 이러한 이유로, 모든 속성을 요청하든(기본 동작) 또는 일부 속성만 요청하든(프로젝션 표현식 사용) 상관없이 사용된 용량 단위의 수는 동일합니다. 필터 표현식 사용 여부와 관계없이 숫자는 동일합니다. `Query`는 최대 4KB의 항목에 대해 초당 강력히 일관된 읽기 1회 또는 초당 최종적으로 일관된 읽기 2회를 수행하기 위해 최소한의 읽기 용량 단위를 사용합니다. 보다 큰 항목을 읽어야 하는 경우, DynamoDB에 추가 읽기 요청 단위가 필요합니다. 파티션 키의 양이 적은 빈 테이블과 매우 큰 테이블에서는 쿼리된 데이터 양을 초과하여 일부 추가 RCU에 요금이 부과될 수 있습니다. 여기에는 데이터가 없는 경우에도 `Query` 요청을 처리하는 데 드는 비용이 포함됩니다.

## 쿼리에 대한 읽기 정합성
<a name="Query.ReadConsistency"></a>

기본적으로 `Query` 작업은 최종적 일관된 읽기를 수행합니다. 따라서 최근 완료된 `Query` 또는 `PutItem` 작업으로 인해 `UpdateItem` 결과에 변경 사항이 반영되지 않을 수 있습니다. 자세한 내용은 [DynamoDB 읽기 일관성](HowItWorks.ReadConsistency.md) 섹션을 참조하세요.

강력한 일관된 읽기가 필요한 경우 `ConsistentRead` 요청에서 `true` 매개 변수를 `Query`로 설정합니다.