

# AWS SDK for Java 1.x와 함께 DAX 사용
<a name="DAX.client.java-sdk-v1"></a>

다음 절차를 따라 Amazon EC2 인스턴스에서 Amazon DynamoDB Accelerator(DAX)용 Java 샘플을 실행합니다.

**참고**  
이 지침은 AWS SDK for Java 1.x를 사용하는 애플리케이션에 대한 것입니다. AWS SDK for Java 2.x를 사용하는 애플리케이션의 경우 [Java 및 DAX](DAX.client.run-application-java.md) 단원을 참조하세요.

**DAX에 대한 Java 샘플을 실행하려면**

1. JDK(Java Development Kit)를 설치합니다.

   ```
   sudo yum install -y java-devel
   ```

1. AWS SDK for Java(`.zip` 파일)를 다운로드한 후 압축을 풉니다.

   ```
   wget http://sdk-for-java.amazonwebservices.com/latest/aws-java-sdk.zip
   
   unzip aws-java-sdk.zip
   ```

1. 최신 버전의 DAX Java 클라이언트(`.jar` 파일)를 다운로드합니다.

   ```
   wget http://dax-sdk.s3-website-us-west-2.amazonaws.com/java/DaxJavaClient-latest.jar
   ```
**참고**  
DAX SDK for Java용 클라이언트는 Apache Maven에서 받을 수 있습니다. 자세한 내용은 [클라이언트를 Apache Maven 종속 항목으로 사용](#DAXClient.Maven) 단원을 참조하십시오.

1. `CLASSPATH` 변수를 설정합니다. 이 예제에서는 `sdkVersion`을 AWS SDK for Java의 실제 버전 번호로 바꿉니다(예: `1.11.112`).

   ```
   export SDKVERSION=sdkVersion
   
   export CLASSPATH=$(pwd)/TryDax/java:$(pwd)/DaxJavaClient-latest.jar:$(pwd)/aws-java-sdk-$SDKVERSION/lib/aws-java-sdk-$SDKVERSION.jar:$(pwd)/aws-java-sdk-$SDKVERSION/third-party/lib/*
   ```

1. 샘플 프로그램 소스 코드(`.zip` 파일)를 다운로드합니다.

   ```
   wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/TryDax.zip
   ```

   다운로드가 완료되면 소스 파일의 압축을 풉니다.

   ```
   unzip TryDax.zip
   ```

1. Java 코드 디렉터리로 이동하여 다음과 같이 코드를 컴파일합니다.

   ```
   cd TryDax/java/
   javac TryDax*.java
   ```

1. 프로그램을 실행합니다.

   ```
   java TryDax
   ```

   다음과 유사한 출력 화면이 표시되어야 합니다.

   ```
   Creating a DynamoDB client
   
   Attempting to create table; please wait...
   Successfully created table.  Table status: ACTIVE
   Writing data to the table...
   Writing 10 items for partition key: 1
   Writing 10 items for partition key: 2
   Writing 10 items for partition key: 3
   Writing 10 items for partition key: 4
   Writing 10 items for partition key: 5
   Writing 10 items for partition key: 6
   Writing 10 items for partition key: 7
   Writing 10 items for partition key: 8
   Writing 10 items for partition key: 9
   Writing 10 items for partition key: 10
   
   Running GetItem, Scan, and Query tests...
   First iteration of each test will result in cache misses
   Next iterations are cache hits
   
   GetItem test - partition key 1 and sort keys 1-10
   	Total time: 136.681 ms - Avg time: 13.668 ms
   	Total time: 122.632 ms - Avg time: 12.263 ms
   	Total time: 167.762 ms - Avg time: 16.776 ms
   	Total time: 108.130 ms - Avg time: 10.813 ms
   	Total time: 137.890 ms - Avg time: 13.789 ms
   Query test - partition key 5 and sort keys between 2 and 9
   	Total time: 13.560 ms - Avg time: 2.712 ms
   	Total time: 11.339 ms - Avg time: 2.268 ms
   	Total time: 7.809 ms - Avg time: 1.562 ms
   	Total time: 10.736 ms - Avg time: 2.147 ms
   	Total time: 12.122 ms - Avg time: 2.424 ms
   Scan test - all items in the table
   	Total time: 58.952 ms - Avg time: 11.790 ms
   	Total time: 25.507 ms - Avg time: 5.101 ms
   	Total time: 37.660 ms - Avg time: 7.532 ms
   	Total time: 26.781 ms - Avg time: 5.356 ms
   	Total time: 46.076 ms - Avg time: 9.215 ms
   
   Attempting to delete table; please wait...
   Successfully deleted table.
   ```

   `GetItem`, `Query` 및 `Scan` 테스트에 필요한 시간 정보(밀리초)를 기록해 둡니다.

1. 전 단계에서 DynamoDB 엔드포인트에 대해 프로그램을 실행했습니다. 이제 프로그램을 다시 실행하되, 이번에는 `GetItem`, `Query` 및 `Scan` 작업을 DAX 클러스터에서 처리합니다.

   DAX 클러스터의 엔드포인트를 정의하려면 다음 중 하나를 선택합니다.
   + **Using the DynamoDB console(DynamoDB 콘솔 사용)** - DAX 클러스터를 선택합니다. 다음 예제와 같이 클러스터 엔드포인트가 콘솔에 표시됩니다.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **AWS CLI 사용** - 다음 명령을 입력합니다.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     다음 예제와 같이 클러스터 엔드포인트가 출력에 표시됩니다.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

   이제 프로그램을 다시 실행합니다. 이번에는 클러스터 엔드포인트를 명령줄 파라미터로 지정합니다.

   ```
   java TryDax dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   나머지 출력을 확인하여 시간 정보를 기록해 둡니다. `GetItem`, `Query`, `Scan`에 대한 경과 시간은 DAX가 DynamoDB보다 현저히 적어야 합니다.

이 프로그램에 대한 자세한 내용은 다음 단원을 참조하세요.
+ [TryDax.java](DAX.client.run-application-java.TryDax.md)
+ [TryDaxHelper.java](DAX.client.run-application-java.TryDaxHelper.md)
+ [TryDaxTests.java](DAX.client.run-application-java.TryDaxTests.md)

## 클라이언트를 Apache Maven 종속 항목으로 사용
<a name="DAXClient.Maven"></a>

애플리케이션에서 DAX SDK for Java용 클라이언트를 종속 항목으로 사용하려면 다음 단계를 따릅니다.

**클라이언트를 Maven 종속 항목으로 사용하려면**

1. Apache Maven을 다운로드하고 설치합니다. 자세한 내용은 [Downloading Apache Maven](https://maven.apache.org/download.cgi) 및 [Installing Apache Maven](https://maven.apache.org/install.html)을 참조하세요.

1. 애플리케이션의 POM(Project Object Model) 파일에 클라이언트 Maven 종속 항목을 추가합니다. 이 예제에서는 `x.x.x.x`를 클라이언트의 실제 버전 번호로 바꿉니다(예: `1.0.200704.0`).

   ```
   <!--Dependency:-->
   <dependencies>
       <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>amazon-dax-client</artifactId>
        <version>x.x.x.x</version>
       </dependency>
   </dependencies>
   ```

# TryDax.java
<a name="DAX.client.run-application-java.TryDax"></a>

`TryDax.java` 파일에는 `main` 메서드가 포함되어 있습니다. 명령줄 파라미터 없이 프로그램을 실행하면 Amazon DynamoDB 클라이언트가 생성되며 모든 API 작업에 해당 클라이언트가 사용됩니다. 명령줄에 DynamoDB 액셀러레이터(DAX) 클러스터 엔드포인트를 지정하면 DAX 클라이언트도 생성되며 `GetItem`, `Query` 및 `Scan` 작업에 이 클라이언트가 사용됩니다.

여러 가지 방법으로 프로그램을 수정할 수 있습니다.
+ DAX 클라이언트 대신 DynamoDB 클라이언트를 사용합니다. 자세한 내용은 [Java 및 DAX](DAX.client.run-application-java.md) 단원을 참조하십시오.
+ 테스트 테이블에 다른 이름을 선택합니다.
+ `helper.writeData` 파라미터를 변경하여 기록된 항목 수를 수정합니다. 두 번째 파라미터는 파티션 키 개수이며 세 번째 파라미터는 정렬 키 개수입니다. 기본적으로 프로그램은 파티션 키 값에 1\$110개 항목을, 정렬 키 값에 1\$110개 항목을 사용하여 총 100개의 항목을 테이블에 기록합니다. 자세한 내용은 [TryDaxHelper.java](DAX.client.run-application-java.TryDaxHelper.md) 단원을 참조하십시오.
+ `GetItem`, `Query` 및 `Scan` 테스트 개수를 수정하고 해당 파라미터를 수정합니다.
+ `helper.createTable` 및 `helper.deleteTable`을 포함하는 행을 주석으로 처리합니다(프로그램을 실행할 때마다 테이블을 생성 및 삭제하지 않으려는 경우).

**참고**  
이 프로그램을 실행하려면 DAX SDK for Java 클라이언트와 AWS SDK for Java를 종속 항목으로 사용하도록 Maven을 설정합니다. 자세한 내용은 [클라이언트를 Apache Maven 종속 항목으로 사용](DAX.client.java-sdk-v1.md#DAXClient.Maven) 단원을 참조하십시오.  
또는 DAX Java 클라이언트와 AWS SDK for Java를 다운로드하여 해당 클래스 경로(classpath)에 포함할 수 있습니다. [Java 및 DAX](DAX.client.run-application-java.md) 변수를 설정하는 예제는 `CLASSPATH` 단원을 참조하세요.

```
public class TryDax {

    public static void main(String[] args) throws Exception {

        TryDaxHelper helper = new TryDaxHelper();
        TryDaxTests tests = new TryDaxTests();

        DynamoDB ddbClient = helper.getDynamoDBClient();
        DynamoDB daxClient = null;
        if (args.length >= 1) {
            daxClient = helper.getDaxClient(args[0]);
        }

        String tableName = "TryDaxTable";

        System.out.println("Creating table...");
        helper.createTable(tableName, ddbClient);
        System.out.println("Populating table...");
        helper.writeData(tableName, ddbClient, 10, 10);

        DynamoDB testClient = null;
        if (daxClient != null) {
            testClient = daxClient;
        } else {
            testClient = ddbClient;
        }

        System.out.println("Running GetItem, Scan, and Query tests...");
        System.out.println("First iteration of each test will result in cache misses");
        System.out.println("Next iterations are cache hits\n");

        // GetItem
        tests.getItemTest(tableName, testClient, 1, 10, 5);

        // Query
        tests.queryTest(tableName, testClient, 5, 2, 9, 5);

        // Scan
        tests.scanTest(tableName, testClient, 5);

        helper.deleteTable(tableName, ddbClient);
    }

}
```

# TryDaxHelper.java
<a name="DAX.client.run-application-java.TryDaxHelper"></a>

`TryDaxHelper.java` 파일에는 유틸리티 메서드가 포함되어 있습니다.

`getDynamoDBClient` 및 `getDaxClient` 메서드는 Amazon DynamoDB 및 DynamoDB 액셀러레이터(DAX) 클라이언트를 제공합니다. 제어 플레인 작업(`CreateTable`, `DeleteTable`) 및 쓰기 작업의 경우 프로그램은 DynamoDB 클라이언트를 사용합니다. DAX 클러스터 엔드포인트를 지정하면 기본 프로그램에서 DAX 클라이언트를 생성하여 읽기 작업(`GetItem`, `Query`, `Scan`)을 수행합니다.

다른 `TryDaxHelper` 메서드(`createTable`, `writeData`, `deleteTable`)는 DynamoDB 테이블 및 해당 데이터 설정 및 삭제용입니다.

여러 가지 방법으로 프로그램을 수정할 수 있습니다.
+ 테이블에 다른 할당 처리량 설정을 사용합니다.
+ 기록된 각 항목의 크기를 수정합니다(`writeData` 메서드의 `stringSize` 변수 참조).
+ `GetItem`, `Query` 및 `Scan` 테스트 개수를 수정하고 해당 파라미터를 수정합니다.
+ `helper.CreateTable` 및 `helper.DeleteTable`을 포함하는 행을 주석으로 처리합니다(프로그램을 실행할 때마다 테이블을 생성 및 삭제하지 않으려는 경우).

**참고**  
 이 프로그램을 실행하려면 DAX SDK for Java 클라이언트와 AWS SDK for Java를 종속 항목으로 사용하도록 Maven을 설정합니다. 자세한 내용은 [클라이언트를 Apache Maven 종속 항목으로 사용](DAX.client.java-sdk-v1.md#DAXClient.Maven) 단원을 참조하십시오.  
또는 DAX Java 클라이언트와 AWS SDK for Java를 모두 다운로드하여 클래스 경로(classpath)에 포함할 수 있습니다. [Java 및 DAX](DAX.client.run-application-java.md) 변수를 설정하는 예제는 `CLASSPATH` 단원을 참조하세요.

```
import com.amazon.dax.client.dynamodbv2.AmazonDaxClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.util.EC2MetadataUtils;

public class TryDaxHelper {

    private static final String region = EC2MetadataUtils.getEC2InstanceRegion();

    DynamoDB getDynamoDBClient() {
        System.out.println("Creating a DynamoDB client");
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
                .withRegion(region)
                .build();
        return new DynamoDB(client);
    }

    DynamoDB getDaxClient(String daxEndpoint) {
        System.out.println("Creating a DAX client with cluster endpoint " + daxEndpoint);
        AmazonDaxClientBuilder daxClientBuilder = AmazonDaxClientBuilder.standard();
        daxClientBuilder.withRegion(region).withEndpointConfiguration(daxEndpoint);
        AmazonDynamoDB client = daxClientBuilder.build();
        return new DynamoDB(client);
    }

    void createTable(String tableName, DynamoDB client) {
        Table table = client.getTable(tableName);
        try {
            System.out.println("Attempting to create table; please wait...");

            table = client.createTable(tableName,
                    Arrays.asList(
                            new KeySchemaElement("pk", KeyType.HASH), // Partition key
                            new KeySchemaElement("sk", KeyType.RANGE)), // Sort key
                    Arrays.asList(
                            new AttributeDefinition("pk", ScalarAttributeType.N),
                            new AttributeDefinition("sk", ScalarAttributeType.N)),
                    new ProvisionedThroughput(10L, 10L));
            table.waitForActive();
            System.out.println("Successfully created table.  Table status: " +
                    table.getDescription().getTableStatus());

        } catch (Exception e) {
            System.err.println("Unable to create table: ");
            e.printStackTrace();
        }
    }

    void writeData(String tableName, DynamoDB client, int pkmax, int skmax) {
        Table table = client.getTable(tableName);
        System.out.println("Writing data to the table...");

        int stringSize = 1000;
        StringBuilder sb = new StringBuilder(stringSize);
        for (int i = 0; i < stringSize; i++) {
            sb.append('X');
        }
        String someData = sb.toString();

        try {
            for (Integer ipk = 1; ipk <= pkmax; ipk++) {
                System.out.println(("Writing " + skmax + " items for partition key: " + ipk));
                for (Integer isk = 1; isk <= skmax; isk++) {
                    table.putItem(new Item()
                            .withPrimaryKey("pk", ipk, "sk", isk)
                            .withString("someData", someData));
                }
            }
        } catch (Exception e) {
            System.err.println("Unable to write item:");
            e.printStackTrace();
        }
    }

    void deleteTable(String tableName, DynamoDB client) {
        Table table = client.getTable(tableName);
        try {
            System.out.println("\nAttempting to delete table; please wait...");
            table.delete();
            table.waitForDelete();
            System.out.println("Successfully deleted table.");

        } catch (Exception e) {
            System.err.println("Unable to delete table: ");
            e.printStackTrace();
        }
    }

}
```

# TryDaxTests.java
<a name="DAX.client.run-application-java.TryDaxTests"></a>

`TryDaxTests.java` 파일에는 Amazon DynamoDB의 테스트 테이블에 읽기 작업을 수행하는 메서드가 포함되어 있습니다. 이러한 메서드는 액세스하는 데이터 양에 영향을 받지 않으므로(DynamoDB 클라이언트를 사용하든 DAX 클라이언트를 사용하든) 애플리케이션 로직을 수정할 필요가 없습니다.

여러 가지 방법으로 프로그램을 수정할 수 있습니다.
+ `queryTest` 메서드를 수정하여 다른 `KeyConditionExpression`을 사용하도록 합니다.
+ 일부 항목만 반환되도록 `scanTest` 메서드에 `ScanFilter`를 추가합니다.

**참고**  
 이 프로그램을 실행하려면 DAX SDK for Java 클라이언트와 AWS SDK for Java를 종속 항목으로 사용하도록 Maven을 설정합니다. 자세한 내용은 [클라이언트를 Apache Maven 종속 항목으로 사용](DAX.client.java-sdk-v1.md#DAXClient.Maven) 단원을 참조하십시오.  
또는 DAX Java 클라이언트와 AWS SDK for Java를 모두 다운로드하여 클래스 경로(classpath)에 포함할 수 있습니다. [Java 및 DAX](DAX.client.run-application-java.md) 변수를 설정하는 예제는 `CLASSPATH` 단원을 참조하세요.

```
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;

public class TryDaxTests {

    void getItemTest(String tableName, DynamoDB client, int pk, int sk, int iterations) {
        long startTime, endTime;
        System.out.println("GetItem test - partition key " + pk + " and sort keys 1-" + sk);
        Table table = client.getTable(tableName);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            try {
                for (Integer ipk = 1; ipk <= pk; ipk++) {
                    for (Integer isk = 1; isk <= sk; isk++) {
                        table.getItem("pk", ipk, "sk", isk);
                    }
                }
            } catch (Exception e) {
                System.err.println("Unable to get item:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, pk * sk);
        }
    }

    void queryTest(String tableName, DynamoDB client, int pk, int sk1, int sk2, int iterations) {
        long startTime, endTime;
        System.out.println("Query test - partition key " + pk + " and sort keys between " + sk1 + " and " + sk2);
        Table table = client.getTable(tableName);

        HashMap<String, Object> valueMap = new HashMap<String, Object>();
        valueMap.put(":pkval", pk);
        valueMap.put(":skval1", sk1);
        valueMap.put(":skval2", sk2);

        QuerySpec spec = new QuerySpec()
                .withKeyConditionExpression("pk = :pkval and sk between :skval1 and :skval2")
                .withValueMap(valueMap);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            ItemCollection<QueryOutcome> items = table.query(spec);

            try {
                Iterator<Item> iter = items.iterator();
                while (iter.hasNext()) {
                    iter.next();
                }
            } catch (Exception e) {
                System.err.println("Unable to query table:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, iterations);
        }
    }

    void scanTest(String tableName, DynamoDB client, int iterations) {
        long startTime, endTime;
        System.out.println("Scan test - all items in the table");
        Table table = client.getTable(tableName);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            ItemCollection<ScanOutcome> items = table.scan();
            try {

                Iterator<Item> iter = items.iterator();
                while (iter.hasNext()) {
                    iter.next();
                }
            } catch (Exception e) {
                System.err.println("Unable to scan table:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, iterations);
        }
    }

    public void printTime(long startTime, long endTime, int iterations) {
        System.out.format("\tTotal time: %.3f ms - ", (endTime - startTime) / (1000000.0));
        System.out.format("Avg time: %.3f ms\n", (endTime - startTime) / (iterations * 1000000.0));
    }
}
```