

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# DynamoDB 향상된 클라이언트 API를 사용하여 시작하기
<a name="ddb-en-client-getting-started"></a>

다음 자습서에서는 DynamoDB 향상된 클라이언트 API를 사용하는 데 필요한 기본 사항을 소개합니다.

## 종속성 추가
<a name="ddb-en-client-gs-dep"></a>

프로젝트에서 DynamoDB 향상된 클라이언트 API로 작업을 시작하려면 `dynamodb-enhanced` Maven 아티팩트에 종속성을 추가하세요. 방법은 다음 예제와 같습니다.

------
#### [ Maven ]

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version><VERSION></version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb-enhanced</artifactId>
    </dependency>
  </dependencies>
  ...
</project>
```

Maven 중앙 리포지토리에서 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)을 검색하고 *<VERSION>*을 이 값으로 바꾸세요.

------
#### [ Gradle ]

```
repositories {
    mavenCentral()
}
dependencies {
    implementation(platform("software.amazon.awssdk:bom:<VERSION>"))
    implementation("software.amazon.awssdk:dynamodb-enhanced")
    ...
}
```

Maven 중앙 리포지토리에서 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)을 검색하고 *<VERSION>*을 이 값으로 바꾸세요.

------

# 데이터 클래스에서 `TableSchema` 생성
<a name="ddb-en-client-gs-tableschema"></a>

`[TableSchema](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/TableSchema.html)`를 사용하면 향상된 클라이언트가 DynamoDB 속성 값을 클라이언트 측 클래스와 매핑하거나 클라이언트 측 클래스에서 가져올 수 있습니다. 이 자습서에서는 정적 데이터 클래스에서 파생되고 빌더를 사용하여 코드에서 생성되는 `TableSchema`에 대해 알아봅니다.

## 주석이 달린 데이터 클래스 사용하기
<a name="ddb-en-client-gs-tableschema-anno-bean"></a>

Java 2.x용 SDK에는 데이터 클래스와 함께 신속하게 `TableSchema`를 생성하는 데 사용할 수 있는 [일련의 주석](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/package-summary.html)이 포함되어 있습니다.

먼저 [JavaBean 사양](https://download.oracle.com/otn-pub/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/beans.101.pdf)을 준수하는 데이터 클래스를 만드세요. 이 사양에서는 클래스에 인수가 없는 공용 생성자가 있어야 하고 클래스의 각 속성에 대한 접근자와 설정자가 있어야 합니다. 데이터 클래스가 `DynamoDbBean`임을 나타내는 클래스 수준 주석을 포함하세요. 또한 최소한 접근자 또는 설정자에 기본 키 속성에 대한 `DynamoDbPartitionKey` 주석을 포함해야 합니다.

[속성 수준 주석](ddb-en-client-anno-index.md)을 getter 또는 setter에 적용할 수 있지만 둘 다 적용할 수는 없습니다.

**참고**  
용어 `property`는 일반적으로 JavaBean에서 캡슐화된 값에 사용됩니다. 하지만 이 가이드에서는 DynamoDB에서 사용하는 용어와의 일관성을 위해 용어 `attribute`를 대신 사용합니다.

다음 `Customer` 클래스는 클래스 정의를 DynamoDB 테이블에 연결하는 주석을 보여줍니다.

### `Customer` 클래스
<a name="ddb-en-client-gs-tableschema-anno-bean-cust"></a>

```
package org.example.tests.model;

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey;

import java.time.Instant;

@DynamoDbBean
public class Customer {

    private String id;
    private String name;
    private String email;
    private Instant regDate;

    @DynamoDbPartitionKey
    public String getId() { return this.id; }

    public void setId(String id) { this.id = id; }

    public String getCustName() { return this.name; }

    public void setCustName(String name) { this.name = name; }

    @DynamoDbSortKey
    public String getEmail() { return this.email; }

    public void setEmail(String email) { this.email = email; }

    public Instant getRegistrationDate() { return this.regDate; }

    public void setRegistrationDate(Instant registrationDate) { this.regDate = registrationDate; }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", email=" + email
                + ", regDate=" + regDate + "]";
    }
}
```

주석이 달린 데이터 클래스를 만든 후 다음 코드 조각에 표시된 것처럼 이 클래스를 사용하여 `TableSchema`를 생성합니다.

```
static final TableSchema<Customer> customerTableSchema = TableSchema.fromBean(Customer.class);
```

`TableSchema`는 정적이고 변경할 수 없도록 설계되었습니다. 일반적으로 클래스 로드 시 인스턴스화할 수 있습니다.

정적 `TableSchema.fromBean()` 팩토리 메서드는 bean을 검사하여 DynamoDB 속성과 데이터 클래스 속성 간의 매핑을 생성합니다.

여러 데이터 클래스로 구성된 데이터 모델을 사용하는 예제는 [bean, 맵, 목록 및 세트로 구성된 속성으로 작업](ddb-en-client-adv-features-nested.md) 단원의 `Person` 클래스를 참조하세요.

## 빌더 사용
<a name="ddb-en-client-gs-tableschema-builder"></a>

코드에 테이블 스키마를 정의하면 Bean 인트로스펙션 비용을 건너뛸 수 있습니다. 스키마를 코딩하면 클래스가 JavaBean 이름 지정 표준을 따르지 않아도 되며 주석을 달 필요도 없습니다. 다음 예제는 빌더를 사용하며 주석을 사용하는 `Customer` 클래스 예제와 동일합니다.

```
static final TableSchema<Customer> customerTableSchema =
                TableSchema.builder(Customer.class)
                        .newItemSupplier(Customer::new)
                        .addAttribute(String.class, a -> a.name("id")
                                .getter(Customer::getId)
                                .setter(Customer::setId)
                                .tags(StaticAttributeTags.primaryPartitionKey()))
                        .addAttribute(String.class, a -> a.name("email")
                                .getter(Customer::getEmail)
                                .setter(Customer::setEmail)
                                .tags(StaticAttributeTags.primarySortKey()))
                        .addAttribute(String.class, a -> a.name("name")
                                .getter(Customer::getCustName)
                                .setter(Customer::setCustName))
                        .addAttribute(Instant.class, a -> a.name("registrationDate")
                                .getter(Customer::getRegistrationDate)
                                .setter(Customer::setRegistrationDate))
                        .build();
```

# 향상된 클라이언트를 만들고 `DynamoDbTable`
<a name="ddb-en-client-getting-started-dynamodbTable"></a>

## 확장 클라이언트 생성
<a name="ddb-en-client-getting-started-dynamodbTable-eclient"></a>

[DynamoDB 향상된 클라이언트](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedClient.html) 클래스 또는 이에 상응하는 비동기식 [DynamoDbEnhancedAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbEnhancedAsyncClient.html)는 DynamoDB 향상된 클라이언트 API 사용을 위한 시작점입니다.

향상된 클라이언트에는 작업을 수행하기 위한 표준 `[DynamoDbClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/DynamoDbClient.html)`이 필요합니다. API는 `DynamoDbEnhancedClient` 인스턴스를 생성하는 두 가지 방법을 제공합니다. 다음 코드 조각에 표시된 첫 번째 옵션은 구성 설정에서 기본 설정을 선택하여 표준 `DynamoDbClient`을 생성합니다.

```
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();
```

기본 표준 클라이언트를 구성하려는 경우 다음 코드 조각과 같이 확장 클라이언트의 빌더 메서드에 제공할 수 있습니다.

```
// Configure an instance of the standard DynamoDbClient.
DynamoDbClient standardClient = DynamoDbClient.builder()
    .region(Region.US_EAST_1)
    .credentialsProvider(ProfileCredentialsProvider.create())
    .build();

// Use the configured standard client with the enhanced client.
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
    .dynamoDbClient(standardClient)
    .build();
```

## `DynamoDbTable` 인스턴스 생성
<a name="ddb-en-client-getting-started-dynamodbTable-table"></a>

[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.html)를 `TableSchema`에서 제공하는 매핑 기능을 사용하는 DynamoDB 테이블의 클라이언트 측 표현이라고 생각하면 됩니다. `DynamoDbTable` 클래스는 단일 DynamoDB 테이블과 상호 작용할 수 있는 CRUD 작업을 위한 메서드를 제공합니다.

`DynamoDbTable<T>`는 문서 유형 항목으로 작업할 때 사용자 정의 클래스이든 `EnhancedDocument`이든 관계없이 단일 형식 인수를 사용하는 제네릭 클래스입니다. 이 인수 유형은 사용하는 클래스와 단일 DynamoDB 테이블 간의 관계를 설정합니다.

`DynamoDbEnhancedClient`의 `table()` 팩토리 메서드를 사용하여 다음 코드 조각과 같이 `DynamoDbTable` 인스턴스를 생성합니다.

```
static final DynamoDbTable<Customer> customerTable = 
        enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

`DynamoDbTable` 인스턴스는 변경이 불가능하고 애플리케이션 전체에서 사용할 수 있기 때문에 싱글톤에 적합합니다.

이제 코드에 `Customer` 인스턴스로 작업할 수 있는 DynamoDB 테이블의 인메모리 표현이 생겼습니다. 실제 DynamoDB 테이블은 존재할 수도 있고 존재하지 않을 수도 있습니다. 이름이 `Customer`로 지정된 테이블이 이미 있는 경우 해당 테이블에 대해 CRUD 작업을 시작할 수 있습니다. 테이블이 존재하지 않는 경우 다음 단원에서 설명하는 대로 `DynamoDbTable` 인스턴스를 사용하여 테이블을 생성하세요.

# 필요한 경우 DynamoDB 테이블 생성
<a name="ddb-en-client-gs-ddbtable"></a>

`DynamoDbTable` 인스턴스를 생성한 후 이를 사용하여 DynamoDB에서 테이블을 *일회성*으로 생성합니다.

## 테이블 생성 예제 코드
<a name="ddb-en-client-gs-ddbtable-createex"></a>

다음 예제는 `Customer` 데이터 클래스를 기반으로 DynamoDB 테이블을 생성합니다.

이 예제는 클래스 이름과 동일한 이름 `Customer`을 가진 DynamoDB 테이블을 생성하지만 테이블 이름은 다른 이름일 수 있습니다. 테이블 이름을 무엇으로 지정하든 테이블 작업을 하려면 추가 애플리케이션에서 이 이름을 사용해야 합니다. 기본 DynamoDB 테이블을 사용하기 위해 다른 `DynamoDbTable` 객체를 생성할 때마다 이 이름을 `table()` 메서드에 제공하세요.

`createTable` 메서드에 전달된 Java Lambda 파라미터 `builder`를 사용하면 [테이블을 사용자 지정](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.Builder.html)할 수 있습니다. 이 예시에서는 [프로비저닝된 처리량](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual)을 구성합니다. 테이블을 생성할 때 기본 설정을 사용하려면 다음 코드 조각과 같이 빌더를 건너뛰세요.

```
customerTable.createTable();
```

기본 설정을 사용하는 경우 프로비저닝된 처리량 값은 설정되지 않습니다. 대신 테이블의 청구 모드가 [온디맨드](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand)로 설정됩니다.

또한 이 예제에서는 응답에서 받은 테이블 이름을 출력하려고 시도하기 전에 `[DynamoDbWaiter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/waiters/DynamoDbWaiter.html)`를 사용합니다. 테이블을 만드는 데 시간이 좀 걸립니다. 따라서 웨이터를 사용하면 테이블을 사용하기 전에 DynamoDB 서비스를 폴링하여 테이블이 존재하는지 확인하는 로직을 작성할 필요가 없습니다.

### 가져오기
<a name="ddb-en-client-gs-ddbtable-imports"></a>

```
import com.example.dynamodb.Customer;
import software.amazon.awssdk.core.internal.waiters.ResponseOrException;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;
```

### 코드
<a name="ddb-en-client-gs-ddbtable-code"></a>

```
 public static void createCustomerTable(DynamoDbTable<Customer> customerTable, DynamoDbClient standardClient) {
     // Create the DynamoDB table using the 'customerTable' DynamoDbTable instance.
     customerTable.createTable(builder -> builder
             .provisionedThroughput(b -> b
                     .readCapacityUnits(10L)
                     .writeCapacityUnits(10L)
                     .build())
     );
     // The DynamoDbClient instance (named 'standardClient') passed to the builder for the DynamoDbWaiter is the same instance
     // that was passed to the builder of the DynamoDbEnhancedClient instance that we created previously.
     // By using the same instance, it ensures that the same Region that was configured on the standard DynamoDbClient 
     // instance is used for other service clients that accept a DynamoDbClient during construction.
     try (DynamoDbWaiter waiter = DynamoDbWaiter.builder().client(standardClient).build()) { // DynamoDbWaiter is Autocloseable
         ResponseOrException<DescribeTableResponse> response = waiter
                 .waitUntilTableExists(builder -> builder.tableName("Customer").build())
                 .matched();
         DescribeTableResponse tableDescription = response.response().orElseThrow(
                 () -> new RuntimeException("Customer table was not created."));
         // The actual error can be inspected in response.exception()
         logger.info("Customer table was created.");
     }
 }
```

**참고**  
데이터 클래스에서 테이블을 생성할 때 DynamoDB 테이블의 속성 이름은 소문자로 시작합니다. 테이블의 속성 이름을 대문자로 시작하려면 [`@DynamoDbAttribute(NAME)` 주석](ddb-en-client-adv-features-inex-attr.md)을 사용하고 원하는 이름을 파라미터로 제공하세요.

# 작업을 수행
<a name="ddb-en-client-gs-use"></a>

테이블이 생성된 후 `DynamoDbTable` 인스턴스를 사용하여 DynamoDB 테이블에 대한 작업을 수행합니다.

다음 예제에서는 `DynamoDbTable<Customer>` 싱글톤이 [`Customer`데이터 클래스](ddb-en-client-gs-tableschema.md#ddb-en-client-gs-tableschema-anno-bean-cust) 인스턴스와 함께 파라미터로 전달되어 테이블에 새 항목을 추가합니다.

```
    public static void putItemExample(DynamoDbTable<Customer> customerTable, Customer customer){
        logger.info(customer.toString());
        customerTable.putItem(customer);
    }
```

## `Customer` 객체
<a name="perform_ops_create_customer_instatnce"></a>

```
        Customer customer = new Customer();
        customer.setId("1");
        customer.setCustName("Customer Name");
        customer.setEmail("customer@example.com");
        customer.setRegistrationDate(Instant.parse("2023-07-03T10:15:30.00Z"));
```

`customer` 객체를 DynamoDB 서비스에 보내기 전에 객체 `toString()` 메서드의 출력을 기록하여 향상된 클라이언트가 보내는 것과 비교하세요.

```
Customer [id=1, name=Customer Name, email=customer@example.com, regDate=2023-07-03T10:15:30Z]
```

와이어 레벨 로깅은 생성된 요청의 페이로드를 보여줍니다. 향상된 클라이언트는 데이터 클래스에서 저수준 표현을 생성했습니다. Java의 `Instant` 유형인 `regDate` 속성은 DynamoDB 문자열로 표시됩니다.

```
{
  "TableName": "Customer",
  "Item": {
    "registrationDate": {
      "S": "2023-07-03T10:15:30Z"
    },
    "id": {
      "S": "1"
    },
    "custName": {
      "S": "Customer Name"
    },
    "email": {
      "S": "customer@example.com"
    }
  }
}
```

# 기존 테이블로 작업하기
<a name="ddb-en-client-gs-existingtable"></a>

이전 단원에서는 Java 데이터 클래스로 시작하는 DynamoDB 테이블을 생성하는 방법을 살펴보았습니다. 기존 테이블이 이미 있고 향상된 클라이언트의 기능을 사용하려는 경우 해당 테이블과 함께 사용할 Java 데이터 클래스를 생성할 수 있습니다. DynamoDB 테이블을 검사하고 데이터 클래스에 필요한 주석을 추가해야 합니다.

기존 테이블로 작업하기 전에 `DynamoDbEnhanced.table()` 메서드를 호출하세요. 이 작업은 이전 예제에서 다음 명령문을 사용하여 수행되었습니다.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
```

`DynamoDbTable` 인스턴스가 반환되면 기본 테이블을 사용하여 바로 작업을 시작할 수 있습니다. `DynamoDbTable.createTable()` 메서드를 호출하여 테이블을 다시 만들 필요는 없습니다.

다음 예제는 DynamoDB 테이블에서 `Customer` 인스턴스를 즉시 가져와서 이를 보여줍니다.

```
DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer", TableSchema.fromBean(Customer.class));
// The Customer table exists already and has an item with a primary key value of "1" and a sort key value of "customer@example.com".
customerTable.getItem(
        Key.builder().
                partitionValue("1").
                sortValue("customer@example.com").build());
```

**중요**  
`table()` 메서드에 사용된 테이블 이름은 기존 DynamoDB 테이블 이름과 일치해야 합니다.