

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

# AWS SDK for Java 1.x와 2.x의 차이점
<a name="migration-whats-different"></a>

이 섹션에서는 애플리케이션을 버전 1.x에서 AWS SDK for Java 버전 2.x로 변환할 때 알아야 할 주요 변경 사항에 대해 설명합니다.

## 패키지 이름 변경 사항
<a name="mig-diff-package-name-change"></a>

SDK for Java 1.x에서 SDK for Java 2.x로의 눈에 띄는 변화는 패키지 이름 변경입니다. 패키지 이름은 SDK 2.x에서 `software.amazon.awssdk`로 시작하는 반면 SDK 1.x에서는 `com.amazonaws`를 사용합니다.

이러한 동일한 이름이 Maven 아티팩트를 SDK 1.x에서 SDK 2.x로 구분합니다. SDK 2.x용 Maven 아티팩트는 `software.amazon.awssdk` groupId를 사용하는 반면 SDK 1.x는 `com.amazonaws` groupId를 사용합니다.

SDK 2.x 아티팩트만 사용하는 프로젝트에 대한 `com.amazonaws` 종속성이 코드에 필요한 경우가 몇 번 있습니다. 이에 대한 한 가지 예는 서버 측에서 작업하는 경우입니다. AWS Lambda이 내용은 이 가이드 앞부분의 [Apache Maven 프로젝트 설정](setup-project-maven.md#modules-dependencies) 단원에 나와 있습니다.

**참고**  
SDK 1.x의 여러 패키지 이름에는 다음이 포함됩니다. `v2` 이 `v2` 경우에 를 사용한다는 것은 일반적으로 패키지의 코드가 서비스 버전 2에서 작동하도록 타겟팅되었음을 의미합니다.  
전체 패키지 이름이 로 `com.amazonaws` 시작되므로 SDK 1.x 구성 요소입니다. SDK 1.x에서 이러한 패키지 이름의 예는 다음과 같습니다.  
`com.amazonaws.services.dynamodbv2`
`com.amazonaws.retry.v2`
`com.amazonaws.services.apigatewayv2`
`com.amazonaws.services.simpleemailv2`

## 프로젝트에 버전 2.x 추가
<a name="adding-v2"></a>

Maven은 AWS SDK for Java 2.x를 사용할 때 종속성을 관리하는 권장 방법입니다. 프로젝트에 버전 2.x 구성 요소를 추가하려면 SDK에 대한 종속 항목으로 `pom.xml` 파일을 업데이트합니다.

**Example**  

```
<dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>software.amazon.awssdk</groupId>
          <artifactId>bom</artifactId>
          <version>2.27.21</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb</artifactId>
    </dependency>
</dependencies>
```

또한 프로젝트를 버전 2.x로 마이그레이션할 때 [버전 1.x 및 2.x 단계를 사용](migration-side-by-side.md)할 수 있습니다.

## 변경이 불가능한 POJO
<a name="immutable-classes"></a>

클라이언트와 작업 요청 및 응답 객체는 이제 변경할 수 없으며 생성 후에는 변경할 수 없습니다. 요청 또는 응답 변수를 재사용하려면 새 객체를 만들어 해당 변수에 할당해야 합니다.

**Example 1.x의 요청 객체 업데이트**  

```
DescribeAlarmsRequest request = new DescribeAlarmsRequest();
DescribeAlarmsResult response = cw.describeAlarms(request);

request.setNextToken(response.getNextToken());
```

**Example 2.x의 요청 객체 업데이트**  

```
DescribeAlarmsRequest request = DescribeAlarmsRequest.builder().build();
DescribeAlarmsResponse response = cw.describeAlarms(request);

request = DescribeAlarmsRequest.builder()
        .nextToken(response.nextToken())
        .build();
```

## setter 및 getter 메서드
<a name="setter-getter-methods"></a>

 AWS SDK for Java 2.x에서 설정자 메서드 이름에는 `set` 또는 `with` 접두사가 포함되지 않습니다. 예를 들어 `*.withEndpoint()`은 `*.endpoint()`입니다.

getter 메서드 이름은 `get` 접두사를 사용하지 않습니다.

**Example 1.x에서 setter 메서드 사용**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
        		.withRegion("us-east-1")
        		.build();
```

**Example 2.x에서 setter 메서드 사용**  

```
DynamoDbClient client = DynamoDbClient.builder()
        		.region(Region.US_EAST_1)
        		.build();
```

**Example 1.x에서 getter 메서드 사용**  

```
String token = request.getNextToken();
```

**Example 2.x에서 getter 메서드 사용**  

```
String token = request.nextToken();
```

## 모델 클래스 이름
<a name="model-classname-changes"></a>

서비스 응답을 나타내는 모델 클래스 이름은 v1이 사용하는 `Result` 대신 v2의 `Response`로 끝납니다.

**Example v1에서 응답을 나타내는 클래스 이름**  

```
CreateApiKeyResult
AllocateAddressResult
```

**Example v2에서 응답을 나타내는 클래스 이름**  

```
CreateApiKeyResponse
AllocateAddressResponse
```

## 라이브러리 및 유틸리티의 마이그레이션 상태
<a name="migration-libraries-utilities"></a>

### Java용 SDK 라이브러리 및 유틸리티
<a name="migration-java-sdk-libs-utils"></a>

다음 표에는 SDK for Java에 대한 라이브러리 및 유틸리티의 마이그레이션 상태가 나열되어 있습니다.


| 버전 1.12.x 이름 | 버전 2.x 이름 | 버전 2.x 이상 | 
| --- | --- | --- | 
| DynamoDBMapper | [DynamoDbEnhancedClient](dynamodb-enhanced-client.md) | 2.12.0 | 
| Waiters | [Waiters](waiters.md) | 2.15.0 | 
| CloudFrontUrlSigner와 CloudFrontCookieSigner | [CloudFrontUtilities](https://aws.amazon.com/blogs/developer/amazon-cloudfront-signed-urls-and-cookies-are-now-supported-in-aws-sdk-for-java-2-x/) | 2.18.33 | 
| TransferManager | [S3TransferManager](transfer-manager.md) | 2.19.0 | 
| EC2 Metadata 클라이언트 |  [EC2 Metadata 클라이언트](examples-ec2-IMDS.md)  | 2.19.29 | 
| S3 URI 파서 |  [S3 URI 파서](https://aws.amazon.com/blogs/devops/s3-uri-parsing-is-now-available-in-aws-sdk-for-java-2-x/)  | 2.20.41 | 
| IAM 정책 빌더 | [IAM 정책 빌더](feature-iam-policy-builder.md) | 2.20.126 | 
| S3 이벤트 알림 | [S3 이벤트 알림](examples-s3-event-notifications.md#s3-event-notification-read) | 2.25.11  | 
| Amazon SQS 클라이언트 측 버퍼링 | [Amazon SQS용 자동 요청 배치 처리 API](sqs-auto-batch.md) | 2.28.0 | 
| 진행 상황 리스너 | 진행 상황 리스너 | [아직 릴리스되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/25) | 

### 관련 라이브러리
<a name="migration-other-sdks"></a>

다음 표에는 별도로 출시되었지만 Java용 SDK 2.x와 호환되는 라이브러리가 나열되어 있습니다.


| Java용 SDK 버전 2.x와 함께 사용되는 이름 | 버전 이후 | 
| --- | --- | 
|  [Amazon S3 암호화 클라이언트](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/what-is-s3-encryption-client.html)  |  3.0.01  | 
| [AWS DynamoDB용 Database Encryption SDK](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/ddb-java.html) | 3.0.02 | 

#### 1Amazon S3 암호화 클라이언트
<a name="migration-s3-encryption-sdk"></a>

Amazon S3용 암호화 클라이언트는 다음 Maven 종속성을 사용하여 사용할 수 있습니다.

```
<dependency>
    <groupId>software.amazon.encryption.s3</groupId>
    <artifactId>amazon-s3-encryption-client-java</artifactId>
    <version>3.x</version>
</dependency>
```

#### 2AWS DynamoDB용 데이터베이스 암호화 SDK
<a name="migration-ddb-encryption-sdk"></a>

DynamoDB용 AWS Database Encryption SDK는 다음 Maven 종속성을 사용하여 V2에 사용할 수 있습니다.

```
<dependency> 
    <groupId>software.amazon.cryptography</groupId>
    <artifactId>aws-database-encryption-sdk-dynamodb</artifactId>
    <version>3.x</version>
</dependency>
```

Java SDK의 v1에서 작동하는 DynamoDB용 암호화 라이브러리에 대한 정보는 [AWS Database Encryption SDK 개발자 안내서](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/java.html)(*Java용 Amazon DynamoDB Encryption Client*) 및 [GitHub](https://github.com/aws/aws-dynamodb-encryption-java)에서 확인할 수 있습니다.

Java SDK의 V2와 호환되는 DynamoDB 암호화 라이브러리에 대한 자세한 내용은 [AWS Database Encryption SDK 개발자 안내서](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/ddb-java.html) 및 [GitHub 소스](https://github.com/aws/aws-database-encryption-sdk-dynamodb)를 참조하세요.

암호화 라이브러리에 대한 마이그레이션 정보는 [AWS Database Encryption SDK 개발자 안내서](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/ddb-java-migrate.html)에서 확인할 수 있습니다.

### 라이브러리 및 유틸리티에 대한 마이그레이션 세부 정보
<a name="migrate-libs-utils-details"></a>
+ [Transfer Manager](migration-s3-transfer-manager.md)
+ [EC2 메타데이터 유틸리티](migration-imds.md)
+ [CloudFront 사전 서명](migration-cloudfront-presigning.md)
+ [S3 URI 구문 분석](migration-s3-uri-parser.md)
+ [DynamoDB 매핑/문서 API](migration-ddb-mapper.md) 
+ [IAM 정책 빌더](migration-iam-policy-builder.md)
+ [S3 이벤트 알림](migration-s3-event-notification.md)
+ SDK 지표 게시([1.x 설명서](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/generating-sdk-metrics.html), [2.x 설명서](metrics.md))

# 클라이언트 변경
<a name="migration-clients"></a>

## 클라이언트 빌더
<a name="client-builder"></a>

클라이언트 빌더 메서드를 사용하여 모든 클라이언트를 생성해야 합니다. 생성자를 더 이상 사용할 수 없습니다.

**Example 버전 1.x에서 클라이언트 생성**  

```
AmazonDynamoDB ddbClient = AmazonDynamoDBClientBuilder.defaultClient();
AmazonDynamoDBClient ddbClient = new AmazonDynamoDBClient();
```

**Example 버전 2.x에서 클라이언트 생성**  

```
DynamoDbClient ddbClient = DynamoDbClient.create();
DynamoDbClient ddbClient = DynamoDbClient.builder().build();
```

## 클라이언트 클래스 이름
<a name="class-names"></a>

이제 모든 클라이언트 클래스 이름은 완전히 카멜 대소문자로 표기되며 더 이상 접두사가 붙지 않습니다. `Amazon` 이러한 변경 내용은 에서 사용된 이름과 일치합니다. AWS CLI

**Example 1.x의 클래스 이름**  

```
AmazonDynamoDB
AWSACMPCAAsyncClient
```

**Example 2.x의 클래스 이름**  

```
DynamoDbClient
AcmAsyncClient
```


**리전 클래스 이름 변경 사항**  

| 1.x 클라이언트 | 2.x 클라이언트 | 
| --- | --- | 
| com.amazonaws.services.acmpca.AWSACMPCAAsyncClient | software.amazon.awssdk.services.acm.AcmAsyncClient | 
| com.amazonaws.services.acmpca.AWSACMPCAClient | software.amazon.awssdk.services.acm.AcmClient | 
| com.amazonaws.services.alexaforbusiness.AmazonAlexaForBusinessAsyncClient | software.amazon.awssdk.services.alexaforbusiness.AlexaForBusinessAsyncClient | 
| com.amazonaws.services.alexaforbusiness.AmazonAlexaForBusinessClient | software.amazon.awssdk.services.alexaforbusiness.AlexaForBusinessClient | 
| com.amazonaws.services.apigateway.AmazonApiGatewayAsyncClient | software.amazon.awssdk.services.apigateway.ApiGatewayAsyncClient | 
| com.amazonaws.services.apigateway.AmazonApiGatewayClient | software.amazon.awssdk.services.apigateway.ApiGatewayClient | 
| com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScalingAsyncClient | software.amazon.awssdk.services.applicationautoscaling.ApplicationAutoScalingAsyncClient | 
| com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScalingClient | software.amazon.awssdk.services.applicationautoscaling.ApplicationAutoScalingClient | 
| com.amazonaws.services.applicationdiscovery.AWSApplicationDiscoveryAsyncClient | software.amazon.awssdk.services.applicationdiscovery.ApplicationDiscoveryAsyncClient | 
| com.amazonaws.services.applicationdiscovery.AWSApplicationDiscoveryClient | software.amazon.awssdk.services.applicationdiscovery.ApplicationDiscoveryClient | 
| com.amazonaws.services.appstream.AmazonAppStreamAsyncClient | software.amazon.awssdk.services.appstream.AppStreamAsyncClient | 
| com.amazonaws.services.appstream.AmazonAppStreamClient | software.amazon.awssdk.services.appstream.AppStreamClient | 
| com.amazonaws.services.appsync.AWSAppSyncAsyncClient | software.amazon.awssdk.services.appsync.AppSyncAsyncClient | 
| com.amazonaws.services.appsync.AWSAppSyncClient | software.amazon.awssdk.services.appsync.AppSyncClient | 
| com.amazonaws.services.athena.AmazonAthenaAsyncClient | software.amazon.awssdk.services.athena.AthenaAsyncClient | 
| com.amazonaws.services.athena.AmazonAthenaClient | software.amazon.awssdk.services.athena.AthenaClient | 
| com.amazonaws.services.autoscaling.AmazonAutoScalingAsyncClient | software.amazon.awssdk.services.autoscaling.AutoScalingAsyncClient | 
| com.amazonaws.services.autoscaling.AmazonAutoScalingClient | software.amazon.awssdk.services.autoscaling.AutoScalingClient | 
| com.amazonaws.services.autoscalingplans.AWSAutoScalingPlansAsyncClient | software.amazon.awssdk.services.autoscalingplans.AutoScalingPlansAsyncClient | 
| com.amazonaws.services.autoscalingplans.AWSAutoScalingPlansClient | software.amazon.awssdk.services.autoscalingplans.AutoScalingPlansClient | 
| com.amazonaws.services.batch.AWSBatchAsyncClient | software.amazon.awssdk.services.batch.BatchAsyncClient | 
| com.amazonaws.services.batch.AWSBatchClient | software.amazon.awssdk.services.batch.BatchClient | 
| com.amazonaws.services.budgets.AWSBudgetsAsyncClient | software.amazon.awssdk.services.budgets.BudgetsAsyncClient | 
| com.amazonaws.services.budgets.AWSBudgetsClient | software.amazon.awssdk.services.budgets.BudgetsClient | 
| com.amazonaws.services.certificatemanager.AWSCertificateManagerAsyncClient | software.amazon.awssdk.services.acm.AcmAsyncClient | 
| com.amazonaws.services.certificatemanager.AWSCertificateManagerClient | software.amazon.awssdk.services.acm.AcmClient | 
| com.amazonaws.services.cloud9.AWSCloud9AsyncClient | software.amazon.awssdk.services.cloud9.Cloud9AsyncClient | 
| com.amazonaws.services.cloud9.AWSCloud9Client | software.amazon.awssdk.services.cloud9.Cloud9Client | 
| com.amazonaws.services.clouddirectory.AmazonCloudDirectoryAsyncClient | software.amazon.awssdk.services.clouddirectory.CloudDirectoryAsyncClient | 
| com.amazonaws.services.clouddirectory.AmazonCloudDirectoryClient | software.amazon.awssdk.services.clouddirectory.CloudDirectoryClient | 
| com.amazonaws.services.cloudformation.AmazonCloudFormationAsyncClient | software.amazon.awssdk.services.cloudformation.CloudFormationAsyncClient | 
| com.amazonaws.services.cloudformation.AmazonCloudFormationClient | software.amazon.awssdk.services.cloudformation.CloudFormationClient | 
| com.amazonaws.services.cloudfront.AmazonCloudFrontAsyncClient | software.amazon.awssdk.services.cloudfront.CloudFrontAsyncClient | 
| com.amazonaws.services.cloudfront.AmazonCloudFrontClient | software.amazon.awssdk.services.cloudfront.CloudFrontClient | 
| com.amazonaws.services.cloudhsm.AWSCloudHSMAsyncClient | software.amazon.awssdk.services.cloudhsm.CloudHsmAsyncClient | 
| com.amazonaws.services.cloudhsm.AWSCloudHSMClient | software.amazon.awssdk.services.cloudhsm.CloudHsmClient | 
| com.amazonaws.services.cloudhsmv2.AWSCloudHSMV2AsyncClient | software.amazon.awssdk.services.cloudhsmv2.CloudHsmV2AsyncClient | 
| com.amazonaws.services.cloudhsmv2.AWSCloudHSMV2Client | software.amazon.awssdk.services.cloudhsmv2.CloudHsmV2Client | 
| com.amazonaws.services.cloudsearchdomain.AmazonCloudSearchDomainAsyncClient | software.amazon.awssdk.services.cloudsearchdomain.CloudSearchDomainAsyncClient | 
| com.amazonaws.services.cloudsearchdomain.AmazonCloudSearchDomainClient | software.amazon.awssdk.services.cloudsearchdomain.CloudSearchDomainClient | 
| com.amazonaws.services.cloudsearchv2.AmazonCloudSearchAsyncClient | software.amazon.awssdk.services.cloudsearch.CloudSearchAsyncClient | 
| com.amazonaws.services.cloudsearchv2.AmazonCloudSearchClient | software.amazon.awssdk.services.cloudsearch.CloudSearchClient | 
| com.amazonaws.services.cloudtrail.AWSCloudTrailAsyncClient | software.amazon.awssdk.services.cloudtrail.CloudTrailAsyncClient | 
| com.amazonaws.services.cloudtrail.AWSCloudTrailClient | software.amazon.awssdk.services.cloudtrail.CloudTrailClient | 
| com.amazonaws.services.cloudwatch.AmazonCloudWatchAsyncClient | software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient | 
| com.amazonaws.services.cloudwatch.AmazonCloudWatchClient | software.amazon.awssdk.services.cloudwatch.CloudWatchClient | 
| com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEventsAsyncClient | software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsAsyncClient | 
| com.amazonaws.services.cloudwatchevents.AmazonCloudWatchEventsClient | software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient | 
| com.amazonaws.services.codebuild.AWSCodeBuildAsyncClient | software.amazon.awssdk.services.codebuild.CodeBuildAsyncClient | 
| com.amazonaws.services.codebuild.AWSCodeBuildClient | software.amazon.awssdk.services.codebuild.CodeBuildClient | 
| com.amazonaws.services.codecommit.AWSCodeCommitAsyncClient | software.amazon.awssdk.services.codecommit.CodeCommitAsyncClient | 
| com.amazonaws.services.codecommit.AWSCodeCommitClient | software.amazon.awssdk.services.codecommit.CodeCommitClient | 
| com.amazonaws.services.codedeploy.AmazonCodeDeployAsyncClient | software.amazon.awssdk.services.codedeploy.CodeDeployAsyncClient | 
| com.amazonaws.services.codedeploy.AmazonCodeDeployClient | software.amazon.awssdk.services.codedeploy.CodeDeployClient | 
| com.amazonaws.services.codepipeline.AWSCodePipelineAsyncClient | software.amazon.awssdk.services.codepipeline.CodePipelineAsyncClient | 
| com.amazonaws.services.codepipeline.AWSCodePipelineClient | software.amazon.awssdk.services.codepipeline.CodePipelineClient | 
| com.amazonaws.services.codestar.AWSCodeStarAsyncClient | software.amazon.awssdk.services.codestar.CodeStarAsyncClient | 
| com.amazonaws.services.codestar.AWSCodeStarClient | software.amazon.awssdk.services.codestar.CodeStarClient | 
| com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityAsyncClient | software.amazon.awssdk.services.cognitoidentity.CognitoIdentityAsyncClient | 
| com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient | software.amazon.awssdk.services.cognitoidentity.CognitoIdentityClient | 
| com.amazonaws.services.cognitoidp.AWSCognitoIdentityProviderAsyncClient | software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderAsyncClient | 
| com.amazonaws.services.cognitoidp.AWSCognitoIdentityProviderClient | software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient | 
| com.amazonaws.services.cognitosync.AmazonCognitoSyncAsyncClient | software.amazon.awssdk.services.cognitosync.CognitoSyncAsyncClient | 
| com.amazonaws.services.cognitosync.AmazonCognitoSyncClient | software.amazon.awssdk.services.cognitosync.CognitoSyncClient | 
| com.amazonaws.services.comprehend.AmazonComprehendAsyncClient | software.amazon.awssdk.services.comprehend.ComprehendAsyncClient | 
| com.amazonaws.services.comprehend.AmazonComprehendClient | software.amazon.awssdk.services.comprehend.ComprehendClient | 
| com.amazonaws.services.config.AmazonConfigAsyncClient | software.amazon.awssdk.services.config.ConfigAsyncClient | 
| com.amazonaws.services.config.AmazonConfigClient | software.amazon.awssdk.services.config.ConfigClient | 
| com.amazonaws.services.connect.AmazonConnectAsyncClient | software.amazon.awssdk.services.connect.ConnectAsyncClient | 
| com.amazonaws.services.connect.AmazonConnectClient | software.amazon.awssdk.services.connect.ConnectClient | 
| com.amazonaws.services.costandusagereport.AWSCostAndUsageReportAsyncClient | software.amazon.awssdk.services.costandusagereport.CostAndUsageReportAsyncClient | 
| com.amazonaws.services.costandusagereport.AWSCostAndUsageReportClient | software.amazon.awssdk.services.costandusagereport.CostAndUsageReportClient | 
| com.amazonaws.services.costexplorer.AWSCostExplorerAsyncClient | software.amazon.awssdk.services.costexplorer.CostExplorerAsyncClient | 
| com.amazonaws.services.costexplorer.AWSCostExplorerClient | software.amazon.awssdk.services.costexplorer.CostExplorerClient | 
| com.amazonaws.services.databasemigrationservice.AWSDatabaseMigrationServiceAsyncClient | software.amazon.awssdk.services.databasemigration.DatabaseMigrationAsyncClient | 
| com.amazonaws.services.databasemigrationservice.AWSDatabaseMigrationServiceClient | software.amazon.awssdk.services.databasemigration.DatabaseMigrationClient | 
| com.amazonaws.services.datapipeline.DataPipelineAsyncClient | software.amazon.awssdk.services.datapipeline.DataPipelineAsyncClient | 
| com.amazonaws.services.datapipeline.DataPipelineClient | software.amazon.awssdk.services.datapipeline.DataPipelineAsyncClient | 
| com.amazonaws.services.dax.AmazonDaxAsyncClient | software.amazon.awssdk.services.dax.DaxAsyncClient | 
| com.amazonaws.services.dax.AmazonDaxClient | software.amazon.awssdk.services.dax.DaxClient | 
| com.amazonaws.services.devicefarm.AWSDeviceFarmAsyncClient | software.amazon.awssdk.services.devicefarm.DeviceFarmAsyncClient | 
| com.amazonaws.services.devicefarm.AWSDeviceFarmClient | software.amazon.awssdk.services.devicefarm.DeviceFarmClient | 
| com.amazonaws.services.directconnect.AmazonDirectConnectAsyncClient | software.amazon.awssdk.services.directconnect.DirectConnectAsyncClient | 
| com.amazonaws.services.directconnect.AmazonDirectConnectClient | software.amazon.awssdk.services.directconnect.DirectConnectClient | 
| com.amazonaws.services.directory.AWSDirectoryServiceAsyncClient | software.amazon.awssdk.services.directory.DirectoryAsyncClient | 
| com.amazonaws.services.directory.AWSDirectoryServiceClient | software.amazon.awssdk.services.directory.DirectoryClient | 
| com.amazonaws.services.dlm.AmazonDLMAsyncClient | software.amazon.awssdk.services.dlm.DlmAsyncClient | 
| com.amazonaws.services.dlm.AmazonDLMClient | software.amazon.awssdk.services.dlm.DlmClient | 
| com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsyncClient | software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient | 
| com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient | software.amazon.awssdk.services.dynamodb.DynamoDbClient | 
| com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsAsyncClient | software.amazon.awssdk.services.dynamodb.streams.DynamoDbStreamsAsyncClient | 
| com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClient | software.amazon.awssdk.services.dynamodb.streams.DynamoDbStreamsClient | 
| com.amazonaws.services.ec2.AmazonEC2AsyncClient | software.amazon.awssdk.services.ec2.Ec2AsyncClient | 
| com.amazonaws.services.ec2.AmazonEC2Client | software.amazon.awssdk.services.ec2.Ec2Client | 
| com.amazonaws.services.ecr.AmazonECRAsyncClient | software.amazon.awssdk.services.ecr.EcrAsyncClient | 
| com.amazonaws.services.ecr.AmazonECRClient | software.amazon.awssdk.services.ecr.EcrClient | 
| com.amazonaws.services.ecs.AmazonECSAsyncClient | software.amazon.awssdk.services.ecs.EcsAsyncClient | 
| com.amazonaws.services.ecs.AmazonECSClient | software.amazon.awssdk.services.ecs.EcsClient | 
| com.amazonaws.services.eks.AmazonEKSAsyncClient | software.amazon.awssdk.services.eks.EksAsyncClient | 
| com.amazonaws.services.eks.AmazonEKSClient | software.amazon.awssdk.services.eks.EksClient | 
| com.amazonaws.services.elasticache.AmazonElastiCacheAsyncClient | software.amazon.awssdk.services.elasticache.ElastiCacheAsyncClient | 
| com.amazonaws.services.elasticache.AmazonElastiCacheClient | software.amazon.awssdk.services.elasticache.ElastiCacheClient | 
| com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkAsyncClient | software.amazon.awssdk.services.elasticbeanstalk.ElasticBeanstalkAsyncClient | 
| com.amazonaws.services.elasticbeanstalk.AWSElasticBeanstalkClient | software.amazon.awssdk.services.elasticbeanstalk.ElasticBeanstalkClient | 
| com.amazonaws.services.elasticfilesystem.AmazonElasticFileSystemAsyncClient | software.amazon.awssdk.services.efs.EfsAsyncClient | 
| com.amazonaws.services.elasticfilesystem.AmazonElasticFileSystemClient | software.amazon.awssdk.services.efs.EfsClient | 
| com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingAsyncClient | software.amazon.awssdk.services.elasticloadbalancing.ElasticLoadBalancingAsyncClient | 
| com.amazonaws.services.elasticloadbalancing.AmazonElasticLoadBalancingClient | software.amazon.awssdk.services.elasticloadbalancing.ElasticLoadBalancingClient | 
| com.amazonaws.services.elasticloadbalancingv2.AmazonElasticLoadBalancingAsyncClient | software.amazon.awssdk.services.elasticloadbalancingv2.ElasticLoadBalancingV2AsyncClient | 
| com.amazonaws.services.elasticloadbalancingv2.AmazonElasticLoadBalancingClient | software.amazon.awssdk.services.elasticloadbalancingv2.ElasticLoadBalancingV2Client | 
| com.amazonaws.services.elasticmapreduce.AmazonElasticMapReduceAsyncClient | software.amazon.awssdk.services.emr.EmrAsyncClient | 
| com.amazonaws.services.elasticmapreduce.AmazonElasticMapReduceClient | software.amazon.awssdk.services.emr.EmrClient | 
| com.amazonaws.services.elasticsearch.AWSElasticsearchAsyncClient | software.amazon.awssdk.services.elasticsearch.ElasticsearchAsyncClient | 
| com.amazonaws.services.elasticsearch.AWSElasticsearchClient | software.amazon.awssdk.services.elasticsearch.ElasticsearchClient | 
| com.amazonaws.services.elastictranscoder.AmazonElasticTranscoderAsyncClient | software.amazon.awssdk.services.elastictranscoder.ElasticTranscoderAsyncClient | 
| com.amazonaws.services.elastictranscoder.AmazonElasticTranscoderClient | software.amazon.awssdk.services.elastictranscoder.ElasticTranscoderClient | 
| com.amazonaws.services.fms.AWSFMSAsyncClient | software.amazon.awssdk.services.fms.FmsAsyncClient | 
| com.amazonaws.services.fms.AWSFMSClient | software.amazon.awssdk.services.fms.FmsClient | 
| com.amazonaws.services.gamelift.AmazonGameLiftAsyncClient | software.amazon.awssdk.services.gamelift.GameLiftAsyncClient | 
| com.amazonaws.services.gamelift.AmazonGameLiftClient | software.amazon.awssdk.services.gamelift.GameLiftClient | 
| com.amazonaws.services.glacier.AmazonGlacierAsyncClient | software.amazon.awssdk.services.glacier.GlacierAsyncClient | 
| com.amazonaws.services.glacier.AmazonGlacierClient | software.amazon.awssdk.services.glacier.GlacierClient | 
| com.amazonaws.services.glue.AWSGlueAsyncClient | software.amazon.awssdk.services.glue.GlueAsyncClient | 
| com.amazonaws.services.glue.AWSGlueClient | software.amazon.awssdk.services.glue.GlueClient | 
| com.amazonaws.services.greengrass.AWSGreengrassAsyncClient | software.amazon.awssdk.services.greengrass.GreengrassAsyncClient | 
| com.amazonaws.services.greengrass.AWSGreengrassClient | software.amazon.awssdk.services.greengrass.GreengrassClient | 
| com.amazonaws.services.guardduty.AmazonGuardDutyAsyncClient | software.amazon.awssdk.services.guardduty.GuardDutyAsyncClient | 
| com.amazonaws.services.guardduty.AmazonGuardDutyClient | software.amazon.awssdk.services.guardduty.GuardDutyClient | 
| com.amazonaws.services.health.AWSHealthAsyncClient | software.amazon.awssdk.services.health.HealthAsyncClient | 
| com.amazonaws.services.health.AWSHealthClient | software.amazon.awssdk.services.health.HealthClient | 
| com.amazonaws.services.identitymanagement.AmazonIdentityManagementAsyncClient | software.amazon.awssdk.services.iam.IamAsyncClient | 
| com.amazonaws.services.identitymanagement.AmazonIdentityManagementClient | software.amazon.awssdk.services.iam.IamClient | 
| com.amazonaws.services.importexport.AmazonImportExportAsyncClient | Deprecated | 
| com.amazonaws.services.importexport.AmazonImportExportClient | Deprecated | 
| com.amazonaws.services.inspector.AmazonInspectorAsyncClient | software.amazon.awssdk.services.inspector.InspectorAsyncClient | 
| com.amazonaws.services.inspector.AmazonInspectorClient | software.amazon.awssdk.services.inspector.InspectorClient | 
| com.amazonaws.services.iot.AWSIotAsyncClient | software.amazon.awssdk.services.iot.IotAsyncClient | 
| com.amazonaws.services.iot.AWSIotClient | software.amazon.awssdk.services.iot.IotClient | 
| com.amazonaws.services.iot1clickdevices.AWSIoT1ClickDevicesAsyncClient | software.amazon.awssdk.services.iot1clickdevices.Iot1ClickDevicesAsyncClient | 
| com.amazonaws.services.iot1clickdevices.AWSIoT1ClickDevicesClient | software.amazon.awssdk.services.iot1clickdevices.Iot1ClickDevicesClient | 
| com.amazonaws.services.iot1clickprojects.AWSIoT1ClickProjectsAsyncClient | software.amazon.awssdk.services.iot1clickprojects.Iot1ClickProjectsAsyncClient | 
| com.amazonaws.services.iot1clickprojects.AWSIoT1ClickProjectsClient | software.amazon.awssdk.services.iot1clickprojects.Iot1ClickProjectsClient | 
| com.amazonaws.services.iotanalytics.AWSIoTAnalyticsAsyncClient | software.amazon.awssdk.services.iotanalytics.IotAnalyticsAsyncClient | 
| com.amazonaws.services.iotanalytics.AWSIoTAnalyticsClient | software.amazon.awssdk.services.iotanalytics.IotAnalyticsClient | 
| com.amazonaws.services.iotdata.AWSIotDataAsyncClient | software.amazon.awssdk.services.iotdata.IotDataAsyncClient | 
| com.amazonaws.services.iotdata.AWSIotDataClient | software.amazon.awssdk.services.iotdata.IotDataClient | 
| com.amazonaws.services.iotjobsdataplane.AWSIoTJobsDataPlaneAsyncClient | software.amazon.awssdk.services.iotdataplane.IotDataPlaneAsyncClient | 
| com.amazonaws.services.iotjobsdataplane.AWSIoTJobsDataPlaneClient | software.amazon.awssdk.services.iotdataplane.IotDataPlaneClient | 
| com.amazonaws.services.kinesis.AmazonKinesisAsyncClient | software.amazon.awssdk.services.kinesis.KinesisAsyncClient | 
| com.amazonaws.services.kinesis.AmazonKinesisClient | software.amazon.awssdk.services.kinesis.KinesisClient | 
| com.amazonaws.services.kinesisanalytics.AmazonKinesisAnalyticsAsyncClient | software.amazon.awssdk.services.kinesisanalytics.KinesisAnalyticsAsyncClient | 
| com.amazonaws.services.kinesisanalytics.AmazonKinesisAnalyticsClient | software.amazon.awssdk.services.kinesisanalytics.KinesisAnalyticsClient | 
| com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseAsyncClient | software.amazon.awssdk.services.firehose.FirehoseAsyncClient | 
| com.amazonaws.services.kinesisfirehose.AmazonKinesisFirehoseClient | software.amazon.awssdk.services.firehose.FirehoseClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoArchivedMediaAsyncClient | software.amazon.awssdk.services.kinesisvideoarchivedmedia.KinesisVideoArchivedMediaAsyncClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoArchivedMediaClient | software.amazon.awssdk.services.kinesisvideoarchivedmedia.KinesisVideoArchivedMediaClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoAsyncClient | software.amazon.awssdk.services.kinesisvideo.KinesisVideoAsyncClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoClient | software.amazon.awssdk.services.kinesisvideo.KinesisVideoClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoMediaAsyncClient | software.amazon.awssdk.services.kinesisvideomedia.KinesisVideoMediaAsyncClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoMediaClient | software.amazon.awssdk.services.kinesisvideomedia.KinesisVideoMediaClient | 
| com.amazonaws.services.kinesisvideo.AmazonKinesisVideoPutMediaClient | 지원되지 않음  | 
| com.amazonaws.services.kms.AWSKMSAsyncClient | software.amazon.awssdk.services.kms.KmsAsyncClient | 
| com.amazonaws.services.kms.AWSKMSClient | software.amazon.awssdk.services.kms.KmsClient | 
| com.amazonaws.services.lambda.AWSLambdaAsyncClient | software.amazon.awssdk.services.lambda.LambdaAsyncClient | 
| com.amazonaws.services.lambda.AWSLambdaClient | software.amazon.awssdk.services.lambda.LambdaClient | 
| com.amazonaws.services.lexmodelbuilding.AmazonLexModelBuildingAsyncClient | software.amazon.awssdk.services.lexmodelbuilding.LexModelBuildingAsyncClient | 
| com.amazonaws.services.lexmodelbuilding.AmazonLexModelBuildingClient | software.amazon.awssdk.services.lexmodelbuilding.LexModelBuildingClient | 
| com.amazonaws.services.lexruntime.AmazonLexRuntimeAsyncClient | software.amazon.awssdk.services.lexruntime.LexRuntimeAsyncClient | 
| com.amazonaws.services.lexruntime.AmazonLexRuntimeClient | software.amazon.awssdk.services.lexruntime.LexRuntimeClient | 
| com.amazonaws.services.lightsail.AmazonLightsailAsyncClient | software.amazon.awssdk.services.lightsail.LightsailAsyncClient | 
| com.amazonaws.services.lightsail.AmazonLightsailClient | software.amazon.awssdk.services.lightsail.LightsailClient | 
| com.amazonaws.services.logs.AWSLogsAsyncClient | software.amazon.awssdk.services.logs.LogsAsyncClient | 
| com.amazonaws.services.logs.AWSLogsClient | software.amazon.awssdk.services.logs.LogsClient | 
| com.amazonaws.services.machinelearning.AmazonMachineLearningAsyncClient | software.amazon.awssdk.services.machinelearning.MachineLearningAsyncClient | 
| com.amazonaws.services.machinelearning.AmazonMachineLearningClient | software.amazon.awssdk.services.machinelearning.MachineLearningClient | 
| com.amazonaws.services.macie.AmazonMacieAsyncClient | software.amazon.awssdk.services.macie.MacieAsyncClient | 
| com.amazonaws.services.macie.AmazonMacieClient | software.amazon.awssdk.services.macie.MacieClient | 
| com.amazonaws.services.marketplacecommerceanalytics.AWSMarketplaceCommerceAnalyticsAsyncClient | software.amazon.awssdk.services.marketplacecommerceanalytics.MarketplaceCommerceAnalyticsAsyncClient | 
| com.amazonaws.services.marketplacecommerceanalytics.AWSMarketplaceCommerceAnalyticsClient | software.amazon.awssdk.services.marketplacecommerceanalytics.MarketplaceCommerceAnalyticsClient | 
| com.amazonaws.services.marketplaceentitlement.AWSMarketplaceEntitlementAsyncClient | software.amazon.awssdk.services.marketplaceentitlement.MarketplaceEntitlementAsyncClient | 
| com.amazonaws.services.marketplaceentitlement.AWSMarketplaceEntitlementClient | software.amazon.awssdk.services.marketplaceentitlement.MarketplaceEntitlementClient | 
| com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringAsyncClient | software.amazon.awssdk.services.marketplacemetering.MarketplaceMeteringAsyncClient | 
| com.amazonaws.services.marketplacemetering.AWSMarketplaceMeteringClient | software.amazon.awssdk.services.marketplacemetering.MarketplaceMeteringClient | 
| com.amazonaws.services.mediaconvert.AWSMediaConvertAsyncClient | software.amazon.awssdk.services.mediaconvert.MediaConvertAsyncClient | 
| com.amazonaws.services.mediaconvert.AWSMediaConvertClient | software.amazon.awssdk.services.mediaconvert.MediaConvertClient | 
| com.amazonaws.services.medialive.AWSMediaLiveAsyncClient | software.amazon.awssdk.services.medialive.MediaLiveAsyncClient | 
| com.amazonaws.services.medialive.AWSMediaLiveClient | software.amazon.awssdk.services.medialive.MediaLiveClient | 
| com.amazonaws.services.mediapackage.AWSMediaPackageAsyncClient | software.amazon.awssdk.services.mediapackage.MediaPackageAsyncClient | 
| com.amazonaws.services.mediapackage.AWSMediaPackageClient | software.amazon.awssdk.services.mediapackage.MediaPackageClient | 
| com.amazonaws.services.mediastore.AWSMediaStoreAsyncClient | software.amazon.awssdk.services.mediastore.MediaStoreAsyncClient | 
| com.amazonaws.services.mediastore.AWSMediaStoreClient | software.amazon.awssdk.services.mediastore.MediaStoreClient | 
| com.amazonaws.services.mediastoredata.AWSMediaStoreDataAsyncClient | software.amazon.awssdk.services.mediastoredata.MediaStoreDataAsyncClient | 
| com.amazonaws.services.mediastoredata.AWSMediaStoreDataClient | software.amazon.awssdk.services.mediastoredata.MediaStoreDataClient | 
| com.amazonaws.services.mediatailor.AWSMediaTailorAsyncClient | software.amazon.awssdk.services.mediatailor.MediaTailorAsyncClient | 
| com.amazonaws.services.mediatailor.AWSMediaTailorClient | software.amazon.awssdk.services.mediatailor.MediaTailorClient | 
| com.amazonaws.services.migrationhub.AWSMigrationHubAsyncClient | software.amazon.awssdk.services.migrationhub.MigrationHubAsyncClient | 
| com.amazonaws.services.migrationhub.AWSMigrationHubClient | software.amazon.awssdk.services.migrationhub.MigrationHubClient | 
| com.amazonaws.services.mobile.AWSMobileAsyncClient | software.amazon.awssdk.services.mobile.MobileAsyncClient | 
| com.amazonaws.services.mobile.AWSMobileClient | software.amazon.awssdk.services.mobile.MobileClient | 
| com.amazonaws.services.mq.AmazonMQAsyncClient | software.amazon.awssdk.services.mq.MqAsyncClient | 
| com.amazonaws.services.mq.AmazonMQClient | software.amazon.awssdk.services.mq.MqClient | 
| com.amazonaws.services.mturk.AmazonMTurkAsyncClient | software.amazon.awssdk.services.mturk.MTurkAsyncClient | 
| com.amazonaws.services.mturk.AmazonMTurkClient | software.amazon.awssdk.services.mturk.MTurkClient | 
| com.amazonaws.services.neptune.AmazonNeptuneAsyncClient | software.amazon.awssdk.services.neptune.NeptuneAsyncClient | 
| com.amazonaws.services.neptune.AmazonNeptuneClient | software.amazon.awssdk.services.neptune.NeptuneClient | 
| com.amazonaws.services.opsworks.AWSOpsWorksAsyncClient | software.amazon.awssdk.services.opsworks.OpsWorksAsyncClient | 
| com.amazonaws.services.opsworks.AWSOpsWorksClient | software.amazon.awssdk.services.opsworks.OpsWorksClient | 
| com.amazonaws.services.opsworkscm.AWSOpsWorksCMAsyncClient | software.amazon.awssdk.services.opsworkscm.OpsWorksCmAsyncClient | 
| com.amazonaws.services.opsworkscm.AWSOpsWorksCMClient | software.amazon.awssdk.services.opsworkscm.OpsWorksCmClient | 
| com.amazonaws.services.organizations.AWSOrganizationsAsyncClient | software.amazon.awssdk.services.organizations.OrganizationsAsyncClient | 
| com.amazonaws.services.organizations.AWSOrganizationsClient | software.amazon.awssdk.services.organizations.OrganizationsClient | 
| com.amazonaws.services.pi.AWSPIAsyncClient | software.amazon.awssdk.services.pi.PiAsyncClient | 
| com.amazonaws.services.pi.AWSPIClient | software.amazon.awssdk.services.pi.PiClient | 
| com.amazonaws.services.pinpoint.AmazonPinpointAsyncClient | software.amazon.awssdk.services.pinpoint.PinpointAsyncClient | 
| com.amazonaws.services.pinpoint.AmazonPinpointClient | software.amazon.awssdk.services.pinpoint.PinpointClient | 
| com.amazonaws.services.polly.AmazonPollyAsyncClient | software.amazon.awssdk.services.polly.PollyAsyncClient | 
| com.amazonaws.services.polly.AmazonPollyClient | software.amazon.awssdk.services.polly.PollyClient | 
| com.amazonaws.services.pricing.AWSPricingAsyncClient | software.amazon.awssdk.services.pricing.PricingAsyncClient | 
| com.amazonaws.services.pricing.AWSPricingClient | software.amazon.awssdk.services.pricing.PricingClient | 
| com.amazonaws.services.rds.AmazonRDSAsyncClient | software.amazon.awssdk.services.rds.RdsAsyncClient | 
| com.amazonaws.services.rds.AmazonRDSClient | software.amazon.awssdk.services.rds.RdsClient | 
| com.amazonaws.services.redshift.AmazonRedshiftAsyncClient | software.amazon.awssdk.services.redshift.RedshiftAsyncClient | 
| com.amazonaws.services.redshift.AmazonRedshiftClient | software.amazon.awssdk.services.redshift.RedshiftClient | 
| com.amazonaws.services.rekognition.AmazonRekognitionAsyncClient | software.amazon.awssdk.services.rekognition.RekognitionAsyncClient | 
| com.amazonaws.services.rekognition.AmazonRekognitionClient | software.amazon.awssdk.services.rekognition.RekognitionClient | 
| com.amazonaws.services.resourcegroups.AWSResourceGroupsAsyncClient | software.amazon.awssdk.services.resourcegroups.ResourceGroupsAsyncClient | 
| com.amazonaws.services.resourcegroups.AWSResourceGroupsClient | software.amazon.awssdk.services.resourcegroups.ResourceGroupsClient | 
| com.amazonaws.services.resourcegroupstaggingapi.AWSResourceGroupsTaggingAPIAsyncClient | software.amazon.awssdk.services.resourcegroupstaggingapi.ResourceGroupsTaggingApiAsyncClient | 
| com.amazonaws.services.resourcegroupstaggingapi.AWSResourceGroupsTaggingAPIClient | software.amazon.awssdk.services.resourcegroupstaggingapi.ResourceGroupsTaggingApiClient | 
| com.amazonaws.services.route53.AmazonRoute53AsyncClient | software.amazon.awssdk.services.route53.Route53AsyncClient | 
| com.amazonaws.services.route53.AmazonRoute53Client | software.amazon.awssdk.services.route53.Route53Client | 
| com.amazonaws.services.route53domains.AmazonRoute53DomainsAsyncClient | software.amazon.awssdk.services.route53domains.Route53DomainsAsyncClient | 
| com.amazonaws.services.route53domains.AmazonRoute53DomainsClient | software.amazon.awssdk.services.route53domains.Route53DomainsClient | 
| com.amazonaws.services.s3.AmazonS3Client | software.amazon.awssdk.services.s3.S3Client | 
| com.amazonaws.services.sagemaker.AmazonSageMakerAsyncClient | software.amazon.awssdk.services.sagemaker.SageMakerAsyncClient | 
| com.amazonaws.services.sagemaker.AmazonSageMakerClient | software.amazon.awssdk.services.sagemaker.SageMakerClient | 
| com.amazonaws.services.sagemakerruntime.AmazonSageMakerRuntimeAsyncClient | software.amazon.awssdk.services.sagemakerruntime.SageMakerRuntimeAsyncClient | 
| com.amazonaws.services.sagemakerruntime.AmazonSageMakerRuntimeClient | software.amazon.awssdk.services.sagemakerruntime.SageMakerRuntimeClient | 
| com.amazonaws.services.secretsmanager.AWSSecretsManagerAsyncClient | software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClient | 
| com.amazonaws.services.secretsmanager.AWSSecretsManagerClient | software.amazon.awssdk.services.secretsmanager.SecretsManagerClient | 
| com.amazonaws.services.securitytoken.AWSSecurityTokenServiceAsyncClient | software.amazon.awssdk.services.sts.StsAsyncClient | 
| com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClient | software.amazon.awssdk.services.sts.StsClient | 
| com.amazonaws.services.serverlessapplicationrepository.AWSServerlessApplicationRepositoryAsyncClient | software.amazon.awssdk.services.serverlessapplicationrepository.ServerlessApplicationRepositoryAsyncClient | 
| com.amazonaws.services.serverlessapplicationrepository.AWSServerlessApplicationRepositoryClient | software.amazon.awssdk.services.serverlessapplicationrepository.ServerlessApplicationRepositoryClient | 
| com.amazonaws.services.servermigration.AWSServerMigrationAsyncClient | software.amazon.awssdk.services.sms.SmsAsyncClient | 
| com.amazonaws.services.servermigration.AWSServerMigrationClient | software.amazon.awssdk.services.sms.SmsClient | 
| com.amazonaws.services.servicecatalog.AWSServiceCatalogAsyncClient | software.amazon.awssdk.services.servicecatalog.ServiceCatalogAsyncClient | 
| com.amazonaws.services.servicecatalog.AWSServiceCatalogClient | software.amazon.awssdk.services.servicecatalog.ServiceCatalogClient | 
| com.amazonaws.services.servicediscovery.AWSServiceDiscoveryAsyncClient | software.amazon.awssdk.services.servicediscovery.ServiceDiscoveryAsyncClient | 
| com.amazonaws.services.servicediscovery.AWSServiceDiscoveryClient | software.amazon.awssdk.services.servicediscovery.ServiceDiscoveryClient | 
| com.amazonaws.services.shield.AWSShieldAsyncClient | software.amazon.awssdk.services.shield.ShieldAsyncClient | 
| com.amazonaws.services.shield.AWSShieldClient | software.amazon.awssdk.services.shield.ShieldClient | 
| com.amazonaws.services.simpledb.AmazonSimpleDBAsyncClient | software.amazon.awssdk.services.simpledb.SimpleDbAsyncClient | 
| com.amazonaws.services.simpledb.AmazonSimpleDBClient | software.amazon.awssdk.services.simpledb.SimpleDbClient | 
| com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceAsyncClient | software.amazon.awssdk.services.ses.SesAsyncClient | 
| com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient | software.amazon.awssdk.services.ses.SesClient | 
| com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementAsyncClient | software.amazon.awssdk.services.ssm.SsmAsyncClient | 
| com.amazonaws.services.simplesystemsmanagement.AWSSimpleSystemsManagementClient | software.amazon.awssdk.services.ssm.SsmClient | 
| com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowAsyncClient | software.amazon.awssdk.services.swf.SwfAsyncClient | 
| com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflowClient | software.amazon.awssdk.services.swf.SwfClient | 
| com.amazonaws.services.snowball.AmazonSnowballAsyncClient | software.amazon.awssdk.services.snowball.SnowballAsyncClient | 
| com.amazonaws.services.snowball.AmazonSnowballClient | software.amazon.awssdk.services.snowball.SnowballClient | 
| com.amazonaws.services.sns.AmazonSNSAsyncClient | software.amazon.awssdk.services.sns.SnsAsyncClient | 
| com.amazonaws.services.sns.AmazonSNSClient | software.amazon.awssdk.services.sns.SnsClient | 
| com.amazonaws.services.sqs.AmazonSQSAsyncClient | software.amazon.awssdk.services.sqs.SqsAsyncClient | 
| com.amazonaws.services.sqs.AmazonSQSClient | software.amazon.awssdk.services.sqs.SqsClient | 
| com.amazonaws.services.stepfunctions.AWSStepFunctionsAsyncClient | software.amazon.awssdk.services.sfn.SfnAsyncClient | 
| com.amazonaws.services.stepfunctions.AWSStepFunctionsClient | software.amazon.awssdk.services.sfn.SfnClient | 
| com.amazonaws.services.storagegateway.AWSStorageGatewayAsyncClient | software.amazon.awssdk.services.storagegateway.StorageGatewayAsyncClient | 
| com.amazonaws.services.storagegateway.AWSStorageGatewayClient | software.amazon.awssdk.services.storagegateway.StorageGatewayClient | 
| com.amazonaws.services.support.AWSSupportAsyncClient | software.amazon.awssdk.services.support.SupportAsyncClient | 
| com.amazonaws.services.support.AWSSupportClient | software.amazon.awssdk.services.support.SupportClient | 
| com.amazonaws.services.transcribe.AmazonTranscribeAsyncClient | software.amazon.awssdk.services.transcribe.TranscribeAsyncClient | 
| com.amazonaws.services.transcribe.AmazonTranscribeClient | software.amazon.awssdk.services.transcribe.TranscribeClient | 
| com.amazonaws.services.translate.AmazonTranslateAsyncClient | software.amazon.awssdk.services.translate.TranslateAsyncClient | 
| com.amazonaws.services.translate.AmazonTranslateClient | software.amazon.awssdk.services.translate.TranslateClient | 
| com.amazonaws.services.waf.AWSWAFAsyncClient | software.amazon.awssdk.services.waf.WafAsyncClient | 
| com.amazonaws.services.waf.AWSWAFClient | software.amazon.awssdk.services.waf.WafClient | 
| com.amazonaws.services.waf.AWSWAFRegionalAsyncClient | software.amazon.awssdk.services.waf.regional.WafRegionalAsyncClient | 
| com.amazonaws.services.waf.AWSWAFRegionalClient | software.amazon.awssdk.services.waf.regional.WafRegionalClient | 
| com.amazonaws.services.workdocs.AmazonWorkDocsAsyncClient | software.amazon.awssdk.services.workdocs.WorkDocsAsyncClient | 
| com.amazonaws.services.workdocs.AmazonWorkDocsClient | software.amazon.awssdk.services.workdocs.WorkDocsClient | 
| com.amazonaws.services.workmail.AmazonWorkMailAsyncClient | software.amazon.awssdk.services.workmail.WorkMailAsyncClient | 
| com.amazonaws.services.workmail.AmazonWorkMailClient | software.amazon.awssdk.services.workmail.WorkMailClient | 
| com.amazonaws.services.workspaces.AmazonWorkspacesAsyncClient | software.amazon.awssdk.services.workspaces.WorkSpacesAsyncClient | 
| com.amazonaws.services.workspaces.AmazonWorkspacesClient | software.amazon.awssdk.services.workspaces.WorkSpacesClient | 
| com.amazonaws.services.xray.AWSXRayAsyncClient | software.amazon.awssdk.services.xray.XRayAsyncClient | 
| com.amazonaws.services.xray.AWSXRayClient | software.amazon.awssdk.services.xray.XRayClient | 

# 클라이언트 만들기 기본값
<a name="client-creation-defaults"></a>

버전 2.x에서는 기본 클라이언트 만들기 로직이 다음과 같이 변경되었습니다.
+ S3의 기본 자격 증명 공급자 체인에는 더 이상 익명 자격 증명이 포함되지 않습니다. `AnonymousCredentialsProvider`를 사용하여 수동으로 S3에 대한 익명 액세스를 지정해야 합니다.
+ 기본 클라이언트 만들기와 관련된 다음 환경 변수가 상이합니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/client-creation-defaults.html)
+ 기본 클라이언트 만들기와 관련된 다음 환경 시스템 속성이 상이합니다.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/client-creation-defaults.html)
+ 버전 2.x는 다음 시스템 속성을 지원하지 않습니다.
+     
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/client-creation-defaults.html)
+ 사용자 지정 `endpoints.json` 파일에서 리전 구성을 로드하는 것은 더 이상 지원되지 않습니다.

# 클라이언트 구성
<a name="client-configuration"></a>

1.x에서는 클라이언트 또는 클라이언트 빌더에서 `ClientConfiguration` 인스턴스를 설정하여 SDK 클라이언트 구성을 수정했습니다. 버전 2.x에서는 클라이언트 구성이 별도의 구성 클래스로 분할됩니다. 별도의 구성 클래스를 사용하면 비동기 클라이언트와 동기 클라이언트에 대해 서로 다른 HTTP 클라이언트를 구성할 수 있지만 여전히 동일한 클래스를 사용할 수 있습니다. `ClientOverrideConfiguration` 

**Example 버전 1.x의 클라이언트 구성**  

```
AmazonDynamoDBClientBuilder.standard()
.withClientConfiguration(clientConfiguration)
.build()
```

**Example 버전 2.x의 동기식 클라이언트 구성**  

```
ProxyConfiguration.Builder proxyConfig = ProxyConfiguration.builder();

ApacheHttpClient.Builder httpClientBuilder =
        ApacheHttpClient.builder()
                        .proxyConfiguration(proxyConfig.build());

ClientOverrideConfiguration.Builder overrideConfig =
        ClientOverrideConfiguration.builder();

DynamoDbClient client =
        DynamoDbClient.builder()
                      .httpClientBuilder(httpClientBuilder)
                      .overrideConfiguration(overrideConfig.build())
                      .build();
```

**Example 버전 2.x의 동기식 클라이언트 구성**  

```
NettyNioAsyncHttpClient.Builder httpClientBuilder =
        NettyNioAsyncHttpClient.builder();

ClientOverrideConfiguration.Builder overrideConfig =
        ClientOverrideConfiguration.builder();

ClientAsyncConfiguration.Builder asyncConfig =
        ClientAsyncConfiguration.builder();

DynamoDbAsyncClient client =
        DynamoDbAsyncClient.builder()
                           .httpClientBuilder(httpClientBuilder)
                           .overrideConfiguration(overrideConfig.build())
                           .asyncConfiguration(asyncConfig.build())
                           .build();
```

## HTTP 클라이언트
<a name="client-configuration-http"></a>

### 주목할 만한 변경 사항
<a name="client-configuration-http-notables"></a>
+ 버전 2.x에서는 `clientBuilder.httpClientBuilder`를 사용하여 구현을 지정하여 런타임에 사용할 HTTP 클라이언트를 변경할 수 있습니다.
+ `clientBuilder.httpClient`를 사용하여 HTTP 클라이언트를 서비스 클라이언트 빌더에 전달하면 서비스 클라이언트가 닫힐 때 기본적으로 HTTP 클라이언트는 닫히지 않습니다. 이렇게 하면 서비스 클라이언트 간에 HTTP 클라이언트를 공유할 수 있습니다.
+ 비동기식 HTTP 클라이언트는 이제 비차단 I/O를 사용합니다.
+ 이제 일부 작업에서는 성능 향상을 위해 HTTP/2를 사용합니다.

### 설정 변경
<a name="client-configuration-http-setting-diffs"></a>


| 설정 | 1.x | 2.x 동기식, Apache | 2.x 비동기식, Netty | 
| --- | --- | --- | --- | 
|  |  <pre>ClientConfiguration clientConfig = <br />    new ClientConfiguration()</pre>  |  <pre>ApacheHttpClient.Builder httpClientBuilder = <br />    ApacheHttpClient.builder()</pre>  |  <pre>NettyNioAsyncHttpClient.Builder httpClientBuilder = <br />    NettyNioAsyncHttpClient.builder()</pre>  | 
| 최대 연결 수 |  <pre>clientConfig.setMaxConnections(...)<br />clientConfig.withMaxConnections(...)</pre>  |  <pre>httpClientBuilder.maxConnections(...)</pre>  |  <pre>httpClientBuilder.maxConcurrency(...)</pre>  | 
| 연결 제한 시간 |  <pre>clientConfig.setConnectionTimeout(...)<br />clientConfig.withConnectionTimeout(...)</pre>  |  <pre>httpClientBuilder.connectionTimeout(...)<br />httpClientBuilder.connectionAcquisitionTimeout(...)</pre>  |  <pre>httpClientBuilder.connectionTimeout(...)</pre>  | 
| 소켓 제한 시간 |  <pre>clientConfig.setSocketTimeout(...)<br />clientConfig.withSocketTimeout(...)</pre>  |  <pre>httpClientBuilder.socketTimeout(...)</pre>  |  <pre>httpClientBuilder.writeTimeout(...)<br />httpClientBuilder.readTimeout(...)</pre>  | 
| 연결 시 TTL |  <pre>clientConfig.setConnectionTTL(...)<br />clientConfig.withConnectionTTL(...)</pre>  |  <pre>httpClientBuilder.connectionTimeToLive(...)</pre>  |  <pre>httpClientBuilder.connectionTimeToLive(...)</pre>  | 
| 연결 시 최대 유휴 |  <pre>clientConfig.setConnectionMaxIdleMillis(...)<br />clientConfig.withConnectionMaxIdleMillis(...)</pre>  |  <pre>httpClientBuilder.connectionMaxIdleTime(...)</pre>  |  <pre>httpClientBuilder.connectionMaxIdleTime(...)</pre>  | 
| 비활성화 후 유효성 확인 |  <pre>clientConfig.setValidateAfterInactivityMillis(...)<br />clientConfig.withValidateAfterInactivityMillis(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 로컬 주소 |  <pre>clientConfig.setLocalAddress(...)<br />clientConfig.withLocalAddress(...)</pre>  |  <pre>httpClientBuilder.localAddress(...)</pre>  | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/857) | 
| Expect-continue 사용 |  <pre>clientConfig.setUseExpectContinue(...)<br />clientConfig.withUseExpectContinue(...)</pre>  |  <pre>httpClientBuilder.expectContinueEnabled(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 연결 리퍼 |  <pre>clientConfig.setUseReaper(...)<br />clientConfig.withReaper(...)</pre>  |  <pre>httpClientBuilder.useIdleConnectionReaper(...)</pre>  |  <pre>httpClientBuilder.useIdleConnectionReaper(...)</pre>  | 
|  |  <pre>AmazonDynamoDBClientBuilder.standard()<br />    .withClientConfiguration(clientConfiguration)<br />    .build()</pre>  |  <pre>DynamoDbClient.builder()<br />    .httpClientBuilder(httpClientBuilder)<br />    .build()</pre>  |  <pre>DynamoDbAsyncClient.builder()<br />.httpClientBuilder(httpClientBuilder)<br />.build()</pre>  | 

## HTTP 클라이언트 프록시
<a name="client-configuration-http-proxy"></a>


| Settings | 1.x | 2.x 동기식, Apache | 2.x 비동기식, Netty | 
| --- | --- | --- | --- | 
|  |  <pre>ClientConfiguration clientConfig =<br />    new ClientConfiguration()</pre>  |  <pre>ProxyConfiguration.Builder proxyConfig =<br />    ProxyConfiguration.builder()</pre>  |  <pre>ProxyConfiguration.Builder proxyConfig =<br />    ProxyConfiguration.builder()</pre>  | 
| 프록시 호스트 |  <pre>clientConfig.setProxyHost(...)<br />clientConfig.withProxyHost(...)</pre>  |  <pre>proxyConfig.endpoint(...)</pre>  |  <pre>proxyConfig.host(...)</pre>  | 
| 프록시 포트 |  <pre>clientConfig.setProxyPort(...)<br />clientConfig.withProxyPort(...)</pre>  |  <pre>proxyConfig.endpoint(...)</pre> [프록시 포트](http-configuration-apache.md#http-configuration-apache-proxy-conf-ex)는 `endpoint`에 포함되어 있습니다.  |  <pre>proxyConfig.port(...)</pre>  | 
| 프록시 사용자 이름 |  <pre>clientConfig.setProxyUsername(...)<br />clientConfig.withProxyUsername(...)</pre>  |  <pre>proxyConfig.username(...)</pre>  |  <pre>proxyConfig.username(...)</pre>  | 
| 프록시 비밀번호 |  <pre>clientConfig.setProxyPassword(...)<br />clientConfig.withProxyPassword(...)</pre>  |  <pre>proxyConfig.password(...)</pre>  |  <pre>proxyConfig.password(...)</pre>  | 
| 프록시 도메인 |  <pre>clientConfig.setProxyDomain(...)<br />clientConfig.withProxyDomain(...)</pre>  |  <pre>proxyConfig.ntlmDomain(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 프록시 워크스테이션 |  <pre>clientConfig.setProxyWorkspace(...)<br />clientConfig.withProxyWorkstation(...)</pre>  |  <pre>proxyConfig.ntlmWorkstation(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 프록시 인증 메서드 |  <pre>clientConfig.setProxyAuthenticationMethods(...)<br />clientConfig.withProxyAuthenticationMethods(...)</pre>  |  [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/858)  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 선제적 기본 프록시 인증 |  <pre>clientConfig.setPreemptiveBasicProxyAuth(...)<br />clientConfig.withPreemptiveBasicProxyAuth(...)</pre>  |  <pre>proxyConfig.preemptiveBasicAuthenticationEnabled(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 비프록시 호스트 |  <pre>clientConfig.setNonProxyHosts(...)<br />clientConfig.withNonProxyHosts(...)</pre>  |  <pre>proxyConfig.nonProxyHosts(...)</pre>  |  <pre>proxyConfig.nonProxyHosts(...)</pre>  | 
| 소켓 프록시 사용 해제 |  <pre>clientConfig.setDisableSocketProxy(...)<br />clientConfig.withDisableSocketProxy(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|  |  <pre>AmazonDynamoDBClientBuilder.standard()<br />    .withClientConfiguration(clientConfiguration)<br />    .build()</pre>  |  <pre>httpClientBuilder.proxyConfiguration(<br />    proxyConfig.build())</pre>  |  <pre>httpClientBuilder.proxyConfiguration(<br />    proxyConfig.build())</pre>  | 

## 클라이언트 재정의
<a name="client-override-config-diffs"></a>


| 설정 | 1.x | 2.x | 
| --- | --- | --- | 
|  |  <pre>ClientConfiguration clientConfig =<br />    new ClientConfiguration()</pre>  |  <pre>ClientOverrideConfiguration.Builder overrideConfig =<br />    ClientOverrideConfiguration.builder()</pre>  | 
| 사용자 에이전트 접두사 |  <pre>clientConfig.setUserAgentPrefix(...)<br />clientConfig.withUserAgentPrefix(...)</pre>  |  <pre>overrideConfig.advancedOption(<br />    SdkAdvancedClientOption.USER_AGENT_PREFIX, ...)</pre>  | 
| 사용자 에이전트 접미사 |  <pre>clientConfig.setUserAgentSuffix(...)<br />clientConfig.withUserAgentSuffix(...)</pre>  |  <pre>overrideConfig.advancedOption(<br />    SdkAdvancedClientOption.USER_AGENT_SUFFIX, ...)</pre>  | 
| Signer |  <pre>clientConfig.setSignerOverride(...)<br />clientConfig.withSignerOverride(...)</pre>  |  <pre>overrideConfig.advancedOption(<br />    SdkAdvancedClientOption.SIGNER, ...)</pre>  | 
| 추가 헤더 |  <pre>clientConfig.addHeader(...)<br />clientConfig.withHeader(...)</pre>  |  <pre>overrideConfig.putHeader(...)</pre>  | 
| 요청 제한 시간 |  <pre>clientConfig.setRequestTimeout(...)<br />clientConfig.withRequestTimeout(...)</pre>  |  <pre>overrideConfig.apiCallAttemptTimeout(...)</pre>  | 
| 클라이언트 실행 제한 시간 |  <pre>clientConfig.setClientExecutionTimeout(...)<br />clientConfig.withClientExecutionTimeout(...)</pre>  |  <pre>overrideConfig.apiCallTimeout(...)</pre>  | 
| Gzip 사용 |  <pre>clientConfig.setUseGzip(...)<br />clientConfig.withGzip(...)</pre>  |  비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new))  | 
| 소켓 버퍼 크기 힌트 |  <pre>clientConfig.setSocketBufferSizeHints(...)<br />clientConfig.withSocketBufferSizeHints(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 캐시 응답 메타데이터 |  <pre>clientConfig.setCacheResponseMetadata(...)<br />clientConfig.withCacheResponseMetadata(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| 응답 메타데이터 캐시 크기 |  <pre>clientConfig.setResponseMetadataCacheSize(...)<br />clientConfig.withResponseMetadataCacheSize(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| DNS 해석기 |  <pre>clientConfig.setDnsResolver(...)<br />clientConfig.withDnsResolver(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
| TCP 킵얼라이브 |  <pre>clientConfig.setUseTcpKeepAlive(...)<br />clientConfig.withTcpKeepAlive(...)</pre>  |  이제 이 옵션은 HTTP 클라이언트 구성에 포함됩니다. <pre>- ApacheHttpClient.builder().tcpKeepAlive(true)<br />- NettyNioAsyncHttpClient.builder().tcpKeepAlive(true)</pre>  | 
| 보안 임의 |  <pre>clientConfig.setSecureRandom(...)<br />clientConfig.withSecureRandom(...)</pre>  | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|  |  <pre>AmazonDynamoDBClientBuilder.standard()<br />    .withClientConfiguration(clientConfiguration)<br />    .build()</pre>  |  <pre>DynamoDbClient.builder()<br />    .overrideConfiguration(overrideConfig.build())<br />    .build()</pre>  | 

## 클라이언트 재정의 재시도
<a name="client-override-retry-config-diffs"></a>


| 설정 | 1.x | 2.x | 
| --- | --- | --- | 
|  |  <pre>ClientConfiguration clientConfig =<br />    new ClientConfiguration()</pre>  |  <pre>ClientOverrideConfiguration.Builder overrideConfigBuilder = <br />    ClientOverrideConfiguration.builder();</pre>  | 
| 최대 오류 재시도 |  <pre>clientConfig.setMaxErrorRetry(...)<br />clientConfig.withMaxErrorRetry(...)</pre>  |  <pre>// Configure the default retry strategy.<br />overrideConfigBuilder.retryStrategy(b -> b.maxAttempts(...));</pre>  | 
| 스로틀링 재시도 사용 |  <pre>clientConfig.setUseThrottleRetries(...)<br />clientConfig.withUseThrottleRetries(...)</pre>  | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/645) | 
| 스로틀링 전 최대 연속 재시도 횟수 |  <pre>clientConfig.setMaxConsecutiveRetriesBeforeThrottling(...)<br />clientConfig.withMaxConsecutiveRetriesBeforeThrottling(...)</pre>  | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/645) | 
|  |  <pre>AmazonDynamoDBClientBuilder.standard()<br />    .withClientConfiguration(clientConfiguration)<br />    .build()</pre>  |  <pre>DynamoDbClient.builder()<br />        .overrideConfiguration(overrideConfigBuilder.build())<br />        .build();<br /><br />// You also have the option to use a lambda expression to configure and<br />// build the 'ClientOverrideConfiguration.Builder'.<br />DynamoDbClient client = DynamoDbClient.builder()<br />        .overrideConfiguration(o -> o.retryStrategy(b -> b.maxAttempts(5)))<br />        .build();</pre>  | 

## 비동기 클라이언트
<a name="client-async-config-diffs"></a>


| 설정 | 1.x | 2.x | 
| --- | --- | --- | 
|  |  |  <pre>ClientAsyncConfiguration.Builder asyncConfig =<br />    ClientAsyncConfiguration.builder()</pre>  | 
| 실행자 |  <pre>AmazonDynamoDBAsyncClientBuilder.standard()<br />    .withExecutorFactory(...)<br />    .build()</pre>  |  <pre>asyncConfig.advancedOption(<br />    SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR, ...)</pre>  | 
|  |  |  <pre>DynamoDbAsyncClient.builder()<br />    .asyncConfiguration(asyncConfig)<br />    .build()</pre>  | 

## 기타 클라이언트 변경 사항
<a name="client-config-other-diffs"></a>

1.x의 다음 `ClientConfiguration` 옵션은 SDK의 2.x에서 변경되었으며 동등한 직접 기능이 없습니다.


| 설정 | 1.x | 2.x 동등 | 
| --- | --- | --- | 
| 프로토콜 |  <pre>clientConfig.setProtocol(Protocol.HTTP)<br />clientConfig.withProtocol(Protocol.HTTP)</pre>  |  프로토콜 설정은 기본적으로 HTTPS입니다. 설정을 수정하려면 클라이언트 빌더에서 HTTP 엔드포인트를 설정하는 프로토콜을 지정합니다. <pre>clientBuilder.endpointOverride(<br />    URI.create("http://..."))</pre>  | 

# 자격 증명 공급자 변경 사항
<a name="migration-client-credentials"></a>

이 단원에서는 AWS SDK for Java의 버전 1.x와 2.x 사이의 자격 증명 공급자 클래스 및 메서드의 이름 변경 사항을 매핑합니다.

## 주요 차이점
<a name="client-credentials"></a>
+ 기본 자격 증명 공급자는 버전 2.x의 환경 변수보다 먼저 시스템 속성을 로드합니다. 자세한 정보는 [자격 증명 사용하기](credentials.md)를 참조하세요.
+ 생성자 메서드는 `create` 또는 `builder` 메서드로 대체됩니다.  
**Example**  

  ```
  DefaultCredentialsProvider.create();
  ```
+ 비동기 새로 고침은 더 이상 기본적으로 설정되지 않습니다. 자격 증명 공급자의 `builder`를 사용해 지정해야 합니다.  
**Example**  

  ```
  ContainerCredentialsProvider provider = ContainerCredentialsProvider.builder()
          		.asyncCredentialUpdateEnabled(true)
          		.build();
  ```
+ `ProfileCredentialsProvider.builder()`를 사용하여 사용자 지정 프로필 파일의 경로를 지정할 수 있습니다.  
**Example**  

  ```
  ProfileCredentialsProvider profile = ProfileCredentialsProvider.builder()
          		.profileFile(ProfileFile.builder().content(Paths.get("myProfileFile.file")).build())
          		.build();
  ```
+ 프로필 파일 형식이 AWS CLI과 더 비슷하도록 변경되었습니다. 지침을 보려면 *AWS Command Line Interface 사용 설명서*의 [AWS CLI 구성](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)을 참조하세요.

## 버전 1.x와 2.x 간에 매핑된 자격 증명 공급자 변경 사항
<a name="credentials-changes-mapping"></a>

### `AWSCredentialsProvider`
<a name="credentials-provider-changes-AWSCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.AWSCredentialsProvider | software.amazon.awssdk.auth.credentials.AwsCredentialsProvider | 
| 메서드 이름 | getCredentials | resolveCredentials | 
| 지원되지 않는 메서드 | refresh | 지원되지 않음 | 

### `DefaultAWSCredentialsProviderChain`
<a name="credentials-provider-changes-DefaultAWSCredentialsProviderChain"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.DefaultAWSCredentialsProviderChain | software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider | 
| 생성 | new DefaultAWSCredentialsProviderChain | DefaultCredentialsProvider.create | 
| 지원되지 않는 메서드 | getInstance | 지원되지 않음 | 
| 외부 설정의 우선순위 |  시스템 속성보다 환경 변수 우선  |  환경 변수보다 시스템 속성 우선  | 

### `AWSStaticCredentialsProvider`
<a name="credentials-provider-changes-AWSStaticCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.AWSStaticCredentialsProvider | software.amazon.awssdk.auth.credentials.StaticCredentialsProvider | 
| 생성 | new AWSStaticCredentialsProvider | StaticCredentialsProvider.create | 

### `EnvironmentVariableCredentialsProvider`
<a name="credentials-provider-changes-EnvironmentVariableCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.EnvironmentVariableCredentialsProvider | software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider | 
| 생성 | new EnvironmentVariableCredentialsProvider | EnvironmentVariableCredentialsProvider.create | 
| 환경 변수 이름 | AWS\$1ACCESS\$1KEY | AWS\$1ACCESS\$1KEY\$1ID | 
|  | AWS\$1SECRET\$1KEY | AWS\$1SECRET\$1ACCESS\$1KEY | 

### `SystemPropertiesCredentialsProvider`
<a name="credentials-provider-changes-SystemPropertiesCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.SystemPropertiesCredentialsProvider | software.amazon.awssdk.auth.credentials.SystemPropertyCredentialsProvider | 
| 생성 | new SystemPropertiesCredentialsProvider | SystemPropertiesCredentialsProvider.create | 
| 시스템 속성 이름 | aws.secretKey | aws.secretAccessKey | 

### `ProfileCredentialsProvider`
<a name="credentials-provider-changes-ProfileCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.profile.ProfileCredentialsProvider | software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider | 
| 생성 | new ProfileCredentialsProvider | ProfileCredentialsProvider.create | 
| 사용자 지정 프로필의 위치 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-client-credentials.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-client-credentials.html)  | 

### `ContainerCredentialsProvider`
<a name="credentials-provider-changes-ContainerCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.ContainerCredentialsProvider | software.amazon.awssdk.auth.credentials.ContainerCredentialsProvider | 
| 생성 | new ContainerCredentialsProvider | ContainerCredentialsProvider.create | 
| 비동기식 새로 고침 지정 | 지원되지 않음 | 기본 동작 | 

### `InstanceProfileCredentialsProvider`
<a name="credentials-provider-changes-InstanceProfileCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.InstanceProfileCredentialsProvider | software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider | 
| 생성 | new InstanceProfileCredentialsProvider | InstanceProfileCredentialsProvider.create | 
| 비동기식 새로 고침 지정 | new InstanceProfileCredentialsProvider(true) |  `InstanceProfileCredentialProvider.builder().asyncCredentialUpdateEnabled(true).build()`  | 
| 시스템 속성 이름 | com.amazonaws.sdk.disableEc2Metadata | aws.disableEc2Metadata | 
|  | com.amazonaws.sdk.ec2MetadataServiceEndpointOverride | aws.ec2MetadataServiceEndpoint | 

### `STSAssumeRoleSessionCredentialsProvider`
<a name="credentials-provider-changes-STSAssumeRoleSessionCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider | software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider | 
| 생성 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-client-credentials.html)  | StsAssumeRoleCredentialsProvider.builder | 
| 비동기식 새로 고침 | 기본 동작 | 기본 동작 | 
| 구성 | new STSAssumeRoleSessionCredentialsProvider.Builder | StsClient 및 AssumeRoleRequest 요청 구성 | 

### `STSSessionCredentialsProvider`
<a name="credentials-provider-changes-STSSessionCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.STSSessionCredentialsProvider | software.amazon.awssdk.services.sts.auth.StsGetSessionTokenCredentialsProvider | 
| 생성 |  `new STSSessionCredentialsProvider`  | StsGetSessionTokenCredentialsProvider.builder | 
| 비동기식 새로 고침 | 기본 동작 | StsGetSessionTokenCredentialsProvider.builder | 
| 구성 | 생성자 파라미터 | 빌더에서 StsClient 및 GetSessionTokenRequest 요청 구성 | 

### `WebIdentityFederationSessionCredentialsProvider`
<a name="credentials-provider-changes-WebIdentityFederationSessionCredentialsProvider"></a>


| 변경 범주 | 1.x | 2.x | 
| --- | --- | --- | 
| 패키지/클래스 이름 | com.amazonaws.auth.WebIdentityFederationSessionCredentialsProvider | software.amazon.awssdk.services.sts.auth.StsAssumeRoleWithWebIdentityCredentialsProvider | 
| 생성 |  `new WebIdentityFederationSessionCredentialsProvider`  | StsAssumeRoleWithWebIdentityCredentialsProvider.builder | 
| 비동기식 새로 고침 | 기본 동작 | StsAssumeRoleWithWebIdentityCredentialsProvider.builder | 
| 구성 | 생성자 파라미터 | 빌더에서 StsClient 및 AssumeRoleWithWebIdentityRequest 요청 구성 | 

### 클래스 교체됨
<a name="credentials-provider-changes-Replacements"></a>


| 1.x 클래스 | 2.x 대체 클래스 | 
| --- | --- | 
| com.amazonaws.auth.EC2ContainerCredentialsProviderWrapper | software.amazon.awssdk.auth.credentials.ContainerCredentialsProvider 및 software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider | 
| com.amazonaws.services.s3.S3CredentialsProviderChain | software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider 및 software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider | 

### 클래스 제거됨
<a name="credentials-provider-changes-Removed"></a>


| 1.x 클래스 | 
| --- | 
| com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider | 
| com.amazonaws.auth.PropertiesFileCredentialsProvider | 

# 리전 변경
<a name="migration-client-region"></a>

이 단원에서는 `Region` 및 `Regions` 클래스 사용을 위해 AWS SDK for Java 2.x에 구현된 변경 사항에 대해 설명합니다.

## 리전 구성
<a name="region-configuration"></a>
+ 일부 AWS 서비스에는 리전별 엔드포인트가 없습니다. 이러한 서비스를 사용할 때는 리전을 `Region.AWS_GLOBAL` 또는 `Region.AWS_CN_GLOBAL`로 설정해야 합니다.  
**Example**  

  ```
  Region region = Region.AWS_GLOBAL;
  ```
+  `com.amazonaws.regions.Regions` 및 `com.amazonaws.regions.Region` 클래스가 이제 하나의 클래스 `software.amazon.awssdk.regions.Region`로 결합되었습니다.

## 메서드 및 클래스 이름 매핑
<a name="region-method-mapping"></a>

다음 표는 AWS SDK for Java의 버전 1.x와 2.x 사이의 리전 관련 클래스를 매핑합니다. `of()` 메서드를 사용하여 이러한 클래스의 인스턴스를 만들 수 있습니다.

**Example**  

```
RegionMetadata regionMetadata = RegionMetadata.of(Region.US_EAST_1);
```


**1.x 리전 클래스 메서드 변경 사항**  

| 1.x | 2.x | 
| --- | --- | 
|  `Regions.fromName`  |  `Region.of`  | 
|  `Regions.getName`  |  `Region.id`  | 
|  `Regions.getDescription`  |  `Region.metadata().description()`  | 
|  `Regions.getCurrentRegion`  |  지원되지 않음  | 
|  `Regions.DEFAULT_REGION`  |  지원되지 않음  | 
|  `Regions.name`  |  `Region.id`  | 


**1.x 리전 클래스 메서드 변경 사항**  

| 1.x | 2.x | 
| --- | --- | 
|  `Region.getName`  |  `Region.id`  | 
|  `Region.hasHttpsEndpoint`  |  지원되지 않음  | 
|  `Region.hasHttpEndpoint`  |  지원되지 않음  | 
|  `Region.getAvailableEndpoints`  |  지원되지 않음  | 
|  `Region.createClient`  |  지원되지 않음  | 


**RegionMetadata 클래스 메서드 변경 사항**  

| 1.x | 2.x | 
| --- | --- | 
|  `RegionMetadata.getName`  |  `RegionMetadata.name`  | 
|  `RegionMetadata.getDomain`  |  `RegionMetadata.domain`  | 
|  `RegionMetadata.getPartition`  |  `RegionMetadata.partition`  | 


**ServiceMetadata 클래스 메서드 변경 사항**  

| 1.x | 2.x | 
| --- | --- | 
|  `Region.getServiceEndpoint`  |  `ServiceMetadata.endpointFor(Region)`  | 
|  `Region.isServiceSupported`  |  `ServiceMetadata.regions().contains(Region)`  | 

# 작업, 요청 및 응답 변경 사항
<a name="migration-operation-requests-responses"></a>

SDK for Java 버전 2에서는 요청이 클라이언트 작업으로 전달됩니다. 예를 들어 `DynamoDbClient's` `PutItemRequest`는 `DynamoDbClient.putItem` 작업으로 전달됩니다. 이러한 작업은와 AWS 서비스같은의 응답을 반환합니다`PutItemResponse`.

SDK for Java 버전 2는 버전 1에서 다음과 같이 변경되었습니다.
+ 응답 페이지가 여러 개인 작업에는 이제 응답의 모든 항목을 자동으로 반복할 수 있는 `Paginator` 메서드가 포함됩니다.
+ 요청 및 응답은 변경할 수 없습니다.
+ 생성자 대신 정적 빌더 메서드를 사용하여 요청 및 응답을 만들어야 합니다. 예를 들어 버전 1의 `new PutItemRequest().withTableName(...)`은 이제 `PutItemRequest.builder().tableName(...).build()`입니다.
+ 작업은 요청(`dynamoDbClient.putItem(request -> request.tableName(...))`)을 만드는 간단한 방법을 지원합니다.

다음 섹션에서는 버전 1과 버전 2 간의 특정 변경 사항을 설명합니다. 일부 파라미터 유형 변경 사항은 [마이그레이션 도구](migration-tool.md)를 사용하여 자동으로 변환할 수 있지만, 다른 변경 사항은 코드를 수동으로 업데이트해야 합니다.

# 데이터 파라미터 변경
<a name="migration-date-parameters"></a>

버전 1에서는 많은 작업에서 시간 기반 파라미터에 대한 `java.util.Date` 객체를 수락했습니다. 버전 2에서는 이러한 작업에서 대신 `java.time.Instant` 객체를 사용합니다.

[마이그레이션 도구](migration-tool.md)를 사용하여 `Date` 파라미터를 자동으로 변환하거나 `Date` 객체에서 `toInstant()` 메서드를 직접 호출하여 파라미터를 수동으로 변환할 수 있습니다.

**Example - 버전 1에서 만료 날짜가 있는 미리 서명된 URL 생성**  

```
// Generate a presigned URL that expires at a specific date
Date expiration = new Date(System.currentTimeMillis() + 3600000); // 1 hour from now
URL presignedUrl = s3Client.generatePresignedUrl(bucketName, keyName, expiration);
```

**Example - 버전 2에서 만료 인스턴스가 있는 미리 서명된 URL 생성**  

```
// Generate a presigned URL that expires at a specific instant
Date expiration = new Date(System.currentTimeMillis() + 3600000); // 1 hour from now
PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(
    GetObjectPresignRequest.builder()
        .getObjectRequest(GetObjectRequest.builder()
            .bucket(bucketName)
            .key(keyName)
            .build())
        .signatureDuration(Duration.between(Instant.now(), expiration.toInstant()))
        .build());
```

# 바이너리 데이터 처리 변경
<a name="migration-binary-data"></a>

버전 1에서는 `ByteBuffer` 객체를 직접 사용하여 바이너리 데이터를 처리했습니다. 버전 2에서 SDK는 바이너리 데이터로 작업하는 보다 편리하고 유형에 안전한 방법을 제공하는 `SdkBytes` 객체를 사용합니다.

[마이그레이션 도구](migration-tool.md)를 사용하여 `SdkBytes`를 자동으로 `ByteBuffer`로 변환하거나 반환된 `SdkBytes` 객체에서 `asByteBuffer()`를 직접적으로 호출하여 수동으로 변환할 수 있습니다.

**Example - 버전 1의 메시지 속성에서 바이너리 데이터 가져오기**  

```
// Get binary data from a message attribute
MessageAttributeValue messageAttributeValue = new MessageAttributeValue();
ByteBuffer binaryValue = messageAttributeValue.getBinaryValue();
String binaryString = new String(messageAttributeValue.getBinaryValue().array());
```

**Example - 버전 2의 메시지 속성에서 바이너리 데이터 가져오기**  

```
// Get binary data from a message attribute
MessageAttributeValue messageAttributeValue = MessageAttributeValue.builder().build();
ByteBuffer binaryValue = messageAttributeValue.binaryValue().asByteBuffer();
String binaryString = new String(messageAttributeValue.binaryValue().asByteBuffer().array());
```

# 제한 시간 파라미터 변경 사항
<a name="migration-timeout-parameters"></a>

버전 1에서는 제한 시간 값이 밀리초를 나타내는 정수 값으로 지정되었습니다. 버전 2에서 제한 시간 파라미터는 `java.time.Duration` 객체를 사용하여 유형 안전과 명확성을 개선합니다.

[마이그레이션 도구](migration-tool.md)를 사용하여 숫자 제한 시간 값을 자동으로 변환하거나 숫자 값을 적절한 `Duration` 팩토리 메서드로 래핑하여 수동으로 변환할 수 있습니다.

**Example - 버전 1에서 요청 제한 시간 설정**  

```
// Set request timeout in milliseconds
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setRequestTimeout(5000); // 5 seconds
```

**Example - 버전 2에서 요청 제한 시간 설정**  

```
// Set request timeout using Duration
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setRequestTimeout(Duration.ofMillis(5000)); // 5 seconds

// Or more clearly:
clientConfiguration.setRequestTimeout(Duration.ofSeconds(5)); // 5 seconds
```

제한 시간 값에 다음 `Duration` 팩토리 메서드를 사용할 수 있습니다.
+ `Duration.ofMillis(long millis)` - 밀리초 값의 경우.
+ `Duration.ofSeconds(long seconds)` - 두 번째 값의 경우.
+ `Duration.ofMinutes(long minutes)` - 분 값의 경우.

# 의 1.x와 2.x 간의 스트리밍 작업 차이 AWS SDK for Java
<a name="migration-streaming-ops"></a>

Amazon S3 `getObject` 및 `putObject` 메서드 등의 스트리밍 작업은 SDK 버전 2.x에서 비차단 I/O를 지원합니다. 따라서 요청 및 응답 모델 객체는 더 이상 `InputStream`을 파라미터로 사용하지 않습니다. 대신 동기식 요청의 경우 요청 객체가 `RequestBody`(바이트 스트림)를 허용합니다. 동등한 비동기식 요청은 `AsyncRequestBody`를 허용합니다.

**Example 1.x에서의 아마존 S3 `putObject` 작업**  

```
s3client.putObject(BUCKET, KEY, new File(file_path));
```

**Example 2.x에서의 Amazon S3 `putObject` 작업**  

```
s3client.putObject(PutObjectRequest.builder()
                                 .bucket(BUCKET)
                                 .key(KEY)
                                 .build(),
                 RequestBody.of(Paths.get("myfile.in")));
```

스트리밍 응답 객체는 V2에서 동기식 클라이언트의 경우 `ResponseTransformer`, 비동기식 클라이언트의 경우 `AsyncResponseTransformer`를 허용합니다.

**Example 1.x에서의 아마존 S3 `getObject` 작업**  

```
S3Object o = s3.getObject(bucket, key);
S3ObjectInputStream s3is = o.getObjectContent();
FileOutputStream fos = new FileOutputStream(new File(key));
```

**Example 2.x에서의 Amazon S3 `getObject` 작업**  

```
s3client.getObject(GetObjectRequest.builder().bucket(bucket).key(key).build(),
		ResponseTransformer.toFile(Paths.get("key")));
```

SDK for Java 2.x에서 스트리밍 응답 작업에는 응답을 메모리에 로드하고 인 메모리의 일반적인 유형 변환을 간소화하는 `AsBytes` 메서드가 포함됩니다.

# 의 1.x와 2.x 간 직렬화 차이 AWS SDK for Java
<a name="migration-serialization-changes"></a>

## 파라미터 차이를 요청할 객체 나열
<a name="serialization-diffs-list-obj-to-req-param"></a>

SDK for Java v1와 v2.x는 파라미터를 요청하기 위해 List 객체를 직렬화하는 방식이 다릅니다.

SDK for Java 1.x는 빈 목록을 직렬화하지 않는 반면, SDK for Java 2.x는 빈 목록을 빈 파라미터로 직렬화합니다.

예를 들어 `SampleRequest`를 받는 `SampleOperation`이 있는 서비스를 생각해 보겠습니다. `SampleRequest`는 다음 예시와 같이 두 개의 파라미터(문자열 유형 `str1`과 목록 유형 `listParam`)를 허용합니다.

**Example 1.x의 `SampleOperation`**  

```
SampleRequest v1Request = new SampleRequest()
    .withStr1("TestName");

sampleServiceV1Client.sampleOperation(v1Request);
```
와이어 레벨 로깅은 `listParam` 파라미터가 직렬화되지 않았음을 보여줍니다.  

```
Action=SampleOperation&Version=2011-01-01&str1=TestName
```

**Example 2.x의 `SampleOperation`**  

```
sampleServiceV2Client.sampleOperation(b -> b
    .str1("TestName"));
```
와이어 레벨 로깅은 `listParam` 파라미터가 값 없이 직렬화되었음을 보여줍니다.  

```
Action=SampleOperation&Version=2011-01-01&str1=TestName&listParam=
```

## V1의 POJO와 V2의 빌더 비교
<a name="serialization-json-objects"></a>

V1 SDK for Java는 변경 가능한 POJO 클래스를 사용하기 때문에 [Jackson](https://github.com/FasterXML/jackson-docs)과 같은 직렬화 및 역직렬화 라이브러리는 모델 객체를 직접 사용할 수 있습니다.

반대로 V2 SDK for Java는 변경 불가능한 모델 객체를 사용합니다. 중간 빌더를 사용하여 역직렬화를 수행해야 합니다.

다음 예제에서는 Jackson `ObjectMapper`를 사용하여 V1 및 V2로 `headBucket` API 직접 호출을 직렬화/역직렬화할 때의 차이점을 보여줍니다.

```
    public void sendRequest() throws IOException {
        final String bucketName = "amzn-s3-demo-bucket";
        final ObjectMapper mapper = new ObjectMapper();

        // V1 uses POJOs to serialize and deserialize.
        final AmazonS3 v1S3Client = AmazonS3ClientBuilder.defaultClient();
        HeadBucketResult resultV1 = v1S3Client.headBucket(
            new HeadBucketRequest(bucketName));

        String v1Serialized = mapper.writeValueAsString(resultV1);

        HeadBucketResult deserializedV1 = mapper.readValue(v1Serialized, HeadBucketResult.class);
        
        // V2 uses builders to serialize and deserialize.
        S3Client v2S3Client = S3Client.create();
        HeadBucketResponse v2Response = v2S3Client.headBucket(
            b -> b.bucket(bucketName));

        String v2Serialized = mapper.writeValueAsString(
            v2Response.toBuilder());

        HeadBucketResponse v2Deserialized = mapper.readValue(
            v2Serialized, HeadBucketResponse.serializableBuilderClass())
            .build();
    }
```

# 의 1.x와 2.x 간 역직렬화 차이 AWS SDK for Java
<a name="migration-deserialization-changes"></a>

## V2의 비어 있는 컬렉션과 V1의 `nulls` 비교
<a name="deserialization-diffs-list-obj-to-req-param"></a>

SDK for Java v1.x 및 v2.x는 JSON 응답을 비어 있는 목록 및 맵과 역직렬화하는 방식이 다릅니다.

SDK가 목록 또는 맵으로 모델링된 누락 속성이 있는 응답을 수신하면 V1은 누락된 속성을 `null`로 역직렬화하는 반면, V2는 속성을 변경할 수 없는 비어 있는 컬렉션 객체로 역직렬화합니다.

예를 들어 DynamoDB 클라이언트에서 `describeTable` 메서드에 대해 반환된 응답을 고려합니다. 다음 예제 메서드에는 글로벌 보조 인덱스가 없는 테이블에서 `describeTable` 메서드를 실행하는 V2 DynamoDB 클라이언트와 V1 DynamoDB 클라이언트가 포함되어 있습니다.

**Example 응답에 누락된 목록으로 모델링된 속성의 역직렬화**  

```
public void deserializationDiffs(){

    DescribeTableResponse v2Response = dynamoDbClientV2.describeTable(builder -> builder.tableName(TABLE_NAME));
    // V2 provides has* methods on model objects for list/map members. No null check needed.
    LOGGER.info( String.valueOf(v2Response.table().hasGlobalSecondaryIndexes()) );
    LOGGER.info( String.valueOf(v2Response.table().globalSecondaryIndexes().isEmpty()) );
    // V2 deserialize to an empty collection.
    LOGGER.info(v2Response.table().globalSecondaryIndexes().toString());

    // V1 deserialize to null.
    DescribeTableResult v1Result = dynamoDbClientV1.describeTable(new DescribeTableRequest(TABLE_NAME));
    if (v1Result.getTable().getGlobalSecondaryIndexes() != null){
        LOGGER.info(v1Result.getTable().getGlobalSecondaryIndexes().toString());
    } else {
        LOGGER.info("The list of global secondary indexes returned by the V1 call is <null>");
    }
}
```
다음은 로그된 출력을 보여줍니다.  

```
INFO  org.example.DeserializationDifferences:45 - false
INFO  org.example.DeserializationDifferences:46 - true
INFO  org.example.DeserializationDifferences:48 - []
INFO  org.example.DeserializationDifferences:55 - The list of global secondary indexes returned by the V1 call is <null>
```

Java SDK 2.x는 `null`을 반환하는 대신 비어 있는 목록을 역직렬화하고 변경 불가능한 비어 있는 컬렉션에 매핑하여 더 안전하고 간결한 코드를 승격해 관용적인 접근 방식을 취합니다. V2를 사용하면 서비스가 이전 예제에 표시된 `hasGlobalSecondaryIndexes`와 같이 `has*` 메서드를 사용하여 목록 또는 맵으로 모델링된 속성을 반환했는지 확인할 수 있습니다.

이 접근 방식은 명시적 `null` 확인의 필요성을 방지하고 존재하지 않거나 비어 있는 데이터 구문을 처리하기 위한 최신 Java 모범 사례에 부합합니다.

### 전체 예제
<a name="full-example-deserialization"></a>

```
package org.example;

import com.amazonaws.regions.Regions;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest;
import com.amazonaws.services.dynamodbv2.model.DescribeTableResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;

import java.util.UUID;

public class DeserializationDifferences {
    private static final Logger LOGGER = LoggerFactory.getLogger(DeserializationDifferences.class);
    private static final String TABLE_NAME = "DeserializationTable-" + UUID.randomUUID();
    DynamoDbClient dynamoDbClientV2 = DynamoDbClient.create();
    AmazonDynamoDB dynamoDbClientV1 = AmazonDynamoDBClientBuilder.standard().withRegion(Regions.US_EAST_1).build();

    public static void main(String[] args) {

        DeserializationDifferences difference = new DeserializationDifferences();
        difference.createTable();
        difference.deserializationDiffs();
        difference.deleteTable();
    }

    public void createTable(){
        dynamoDbClientV2.createTable(b -> b
                .billingMode(BillingMode.PAY_PER_REQUEST)
                .tableName(TABLE_NAME)
                .keySchema(b1 -> b1.attributeName("Id").keyType(KeyType.HASH))
                .attributeDefinitions(b2 -> b2.attributeName("Id").attributeType(ScalarAttributeType.S)));
        dynamoDbClientV2.waiter().waitUntilTableExists(b -> b.tableName(TABLE_NAME));
    }

    public void deserializationDiffs(){

        DescribeTableResponse v2Response = dynamoDbClientV2.describeTable(builder -> builder.tableName(TABLE_NAME));
        // V2 provides has* methods on model objects for list/map members. No null check needed.
        LOGGER.info( String.valueOf(v2Response.table().hasGlobalSecondaryIndexes()) );
        LOGGER.info( String.valueOf(v2Response.table().globalSecondaryIndexes().isEmpty()) );
        // V2 deserialize to an empty collection.
        LOGGER.info(v2Response.table().globalSecondaryIndexes().toString());

        // V1 deserialize to null.
        DescribeTableResult v1Result = dynamoDbClientV1.describeTable(new DescribeTableRequest(TABLE_NAME));
        if (v1Result.getTable().getGlobalSecondaryIndexes() != null){
            LOGGER.info(v1Result.getTable().getGlobalSecondaryIndexes().toString());
        } else {
            LOGGER.info("The list of global secondary indexes returned by the V1 call is <null>");
        }
    }

    public void deleteTable(){
        dynamoDbClientV2.deleteTable(b -> b.tableName(TABLE_NAME));
        dynamoDbClientV2.waiter().waitUntilTableNotExists(b -> b.tableName(TABLE_NAME));
    }
}
```

V1 및 V2 클라이언트의 `describeTable` 메서드에 대한 JSON 응답에는 `GlobalSecondaryIndexes` 속성이 없습니다.

```
{
  "Table": {
    "AttributeDefinitions": [
      {
        "AttributeName": "Id",
        "AttributeType": "S"
      }
    ],
    "BillingModeSummary": {
      "BillingMode": "PAY_PER_REQUEST",
      "LastUpdateToPayPerRequestDateTime": ...
    },
    "CreationDateTime": ...,
    "DeletionProtectionEnabled": false,
    "ItemCount": 0,
    "KeySchema": [
      {
        "AttributeName": "Id",
        "KeyType": "HASH"
      }
    ],
    "ProvisionedThroughput": {
      "NumberOfDecreasesToday": 0,
      "ReadCapacityUnits": 0,
      "WriteCapacityUnits": 0 
    },
    "TableArn": "arn:aws:dynamodb:us-east-1:11111111111:table/DeserializationTable-...",
    "TableId": "...",
    "TableName": "DeserializationTable-...",
    "TableSizeBytes": 0,
    "TableStatus": "ACTIVE",
    "TableThroughputModeSummary": {
      "LastUpdateToPayPerRequestDateTime": ...,
      "TableThroughputMode": "PAY_PER_REQUEST"
    },
    "WarmThroughput": {
      "ReadUnitsPerSecond": 12000,
      "Status": "ACTIVE",
      "WriteUnitsPerSecond": 4000
    }
  }
}
```

# 예외 변경
<a name="migration-exception-changes"></a>

예외 클래스 이름, 구문 및 관계가 변경되었습니다. `software.amazon.awssdk.core.exception.SdkException`은 다른 모든 예외가 확장되는 새 기본 `Exception` 클래스입니다.

이 표는 예외 클래스 이름 변경 내용을 매핑합니다.


| 1.x | 2.x | 
| --- | --- | 
|   `com.amazonaws.SdkBaseException` `com.amazonaws.AmazonClientException`   |   `software.amazon.awssdk.core.exception.SdkException`   | 
|   `com.amazonaws.SdkClientException`   |   `software.amazon.awssdk.core.exception.SdkClientException`   | 
|   `com.amazonaws.AmazonServiceException`   |   `software.amazon.awssdk.awscore.exception.AwsServiceException`   | 

다음 표는 버전 1.x와 2.x 사이의 예외 클래스에 대한 메서드를 매핑합니다.


| 1.x | 2.x | 
| --- | --- | 
|   `AmazonServiceException.getRequestId`   |   `SdkServiceException.requestId`   | 
|   `AmazonServiceException.getServiceName`   |   `AwsServiceException.awsErrorDetails().serviceName`   | 
|   `AmazonServiceException.getErrorCode`   |   `AwsServiceException.awsErrorDetails().errorCode`   | 
|   `AmazonServiceException.getErrorMessage`   |   `AwsServiceException.awsErrorDetails().errorMessage`   | 
|   `AmazonServiceException.getStatusCode`   |   `AwsServiceException.awsErrorDetails().sdkHttpResponse().statusCode`   | 
|   `AmazonServiceException.getHttpHeaders`   |   `AwsServiceException.awsErrorDetails().sdkHttpResponse().headers`   | 
|   `AmazonServiceException.rawResponse`   |   `AwsServiceException.awsErrorDetails().rawResponse`   | 

# 서비스별 CLI
<a name="migration-service-changes"></a>

## Amazon S3 변경 사항
<a name="s3-operations-name"></a>

DK for Java 2.x는 기본적으로 익명 액세스를 사용 해제합니다. 따라서 `AnonymousCredentialsProvider`를 사용하여 익명 액세스를 사용해야 합니다.

### 작업 이름 변경 사항
<a name="s3-op-name-changes"></a>

AWS SDK for Java 2.x에서는 Amazon S3 클라이언트의 많은 작업 이름이 변경되었습니다. 버전 1.x에서는 서비스 API에서 Amazon S3 클라이언트가 직접 생성되지 않습니다. 이로 인해 SDK 작업과 서비스 API 간에 불일치가 발생합니다. 버전 2.x에서는 이제 서비스 API와의 일관성을 높이기 위해 Amazon S3 클라이언트를 생성합니다.

다음 테이블에는 두 버전의 작업 이름이 나와 있습니다.


**Amazon S3 작업 이름**  

| 1.x | 2.x | 
| --- | --- | 
| abortMultipartUpload | abortMultipartUpload | 
| changeObjectStorageClass  | copyObject | 
| completeMultipartUpload  | completeMultipartUpload | 
| copyObject | copyObject | 
| copyPart | uploadPartCopy | 
| createBucket | createBucket | 
| deleteBucket | deleteBucket | 
| deleteBucketAnalyticsConfiguration | deleteBucketAnalyticsConfiguration | 
| deleteBucketCrossOriginConfiguration | deleteBucketCors | 
| deleteBucketEncryption | deleteBucketEncryption | 
| deleteBucketInventoryConfiguration | deleteBucketInventoryConfiguration | 
| deleteBucketLifecycleConfiguration | deleteBucketLifecycle | 
| deleteBucketMetricsConfiguration | deleteBucketMetricsConfiguration | 
| deleteBucketPolicy | deleteBucketPolicy | 
| deleteBucketReplicationConfiguration | deleteBucketReplication | 
| deleteBucketTaggingConfiguration | deleteBucketTagging | 
| deleteBucketWebsiteConfiguration | deleteBucketWebsite | 
| deleteObject | deleteObject | 
| deleteObjectTagging | deleteObjectTagging | 
| deleteObjects | deleteObjects | 
| deleteVersion | deleteObject | 
| disableRequesterPays | putBucketRequestPayment | 
| doesBucketExist | headBucket | 
| doesBucketExistV2 | headBucket | 
| doesObjectExist | headObject | 
| enableRequesterPays | putBucketRequestPayment | 
| generatePresignedUrl | [S3Presigner](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/presigner/S3Presigner.html) | 
| getBucketAccelerateConfiguration | getBucketAccelerateConfiguration | 
| getBucketAcl | getBucketAcl | 
| getBucketAnalyticsConfiguration | getBucketAnalyticsConfiguration | 
| getBucketCrossOriginConfiguration | getBucketCors | 
| getBucketEncryption | getBucketEncryption | 
| getBucketInventoryConfiguration | getBucketInventoryConfiguration | 
| getBucketLifecycleConfiguration | getBucketLifecycle 또는 getBucketLifecycleConfiguration | 
| getBucketLocation | getBucketLocation | 
| getBucketLoggingConfiguration | getBucketLogging | 
| getBucketMetricsConfiguration | getBucketMetricsConfiguration | 
| getBucketNotificationConfiguration | getBucketNotification 또는 getBucketNotificationConfiguration | 
| getBucketPolicy | getBucketPolicy | 
| getBucketReplicationConfiguration | getBucketReplication | 
| getBucketTaggingConfiguration | getBucketTagging | 
| getBucketVersioningConfiguration | getBucketVersioning | 
| getBucketWebsiteConfiguration | getBucketWebsite | 
| getObject | getObject | 
| getObjectAcl | getObjectAcl | 
| getObjectAsString | getObjectAsBytes().asUtf8String | 
| getObjectMetadata | headObject | 
| getObjectTagging | getObjectTagging | 
| getResourceUrl | [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Utilities.html#getUrl(java.util.function.Consumer)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Utilities.html#getUrl(java.util.function.Consumer)) | 
| getS3AccountOwner | listBuckets | 
| getUrl | [S3Utilities\$1getUrl](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Utilities.html#getUrl(java.util.function.Consumer)) | 
| headBucket | headBucket | 
| initiateMultipartUpload | createMultipartUpload | 
| isRequesterPaysEnabled | getBucketRequestPayment | 
| listBucketAnalyticsConfigurations | listBucketAnalyticsConfigurations | 
| listBucketInventoryConfigurations | listBucketInventoryConfigurations | 
| listBucketMetricsConfigurations | listBucketMetricsConfigurations | 
| listBuckets | listBuckets | 
| listMultipartUploads | listMultipartUploads | 
| listNextBatchOfObjects | listObjectsV2Paginator | 
| listNextBatchOfVersions | listObjectVersionsPaginator | 
| listObjects | listObjects | 
| listObjectsV2 | listObjectsV2 | 
| listParts | listParts | 
| listVersions | listObjectVersions | 
| putObject | putObject | 
| restoreObject | restoreObject | 
| restoreObjectV2 | restoreObject | 
| selectObjectContent | selectObjectContent | 
| setBucketAccelerateConfiguration | putBucketAccelerateConfiguration | 
| setBucketAcl | putBucketAcl | 
| setBucketAnalyticsConfiguration | putBucketAnalyticsConfiguration | 
| setBucketCrossOriginConfiguration | putBucketCors | 
| setBucketEncryption | putBucketEncryption | 
| setBucketInventoryConfiguration | putBucketInventoryConfiguration | 
| setBucketLifecycleConfiguration | putBucketLifecycle 또는 putBucketLifecycleConfiguration | 
| setBucketLoggingConfiguration | putBucketLogging | 
| setBucketMetricsConfiguration | putBucketMetricsConfiguration | 
| setBucketNotificationConfiguration | putBucketNotification‘or’putBucketNotificationConfiguration | 
| setBucketPolicy | putBucketPolicy | 
| setBucketReplicationConfiguration | putBucketReplication | 
| setBucketTaggingConfiguration | putBucketTagging | 
| setBucketVersioningConfiguration | putBucketVersioning | 
| setBucketWebsiteConfiguration | putBucketWebsite | 
| setObjectAcl | putObjectAcl | 
| setObjectRedirectLocation | copyObject | 
| setObjectTagging | putObjectTagging | 
| uploadPart | uploadPart | 

## Amazon SNS 변경 사항
<a name="sns-changes"></a>

SNS 클라이언트는 더 이상 액세스하도록 구성된 리전 이외의 리전에서 SNS 주제에 액세스할 수 없습니다.

## Amazon SQS 변경 사항
<a name="sqs-changes"></a>

SQS 클라이언트는 더 이상 액세스하도록 구성된 리전 이외의 리전에서 SQS 대기열에 액세스할 수 없습니다.

## Amazon RDS 변경 사항
<a name="rds-changes"></a>

SDK for Java 2.x는 1.x의 `RdsIamAuthTokenGenerator` 클래스 대신 `RdsUtilities#generateAuthenticationToken`을 사용합니다.

# 의 버전 1에서 버전 2로 Amazon S3 작업 변경 AWS SDK for Java
<a name="migration-s3"></a>

는 새 패키지 구조, 업데이트된 클래스 이름, 수정된 메서드 서명을 포함하여 S3 클라이언트에 중요한 변경 사항을 AWS SDK for Java 2.x 도입합니다. [마이그레이션 도구](migration-tool.md)를 사용하여 V1에서 V2로 많은 메서드를 자동으로 마이그레이션할 수 있지만, `listNextBatchOfObjects` 및 `selectObjectContent`와 같은 일부 메서드는 수동 마이그레이션이 필요합니다. 또한 V2는 `AccessControlList` 및 `CannedAccessControlList`와 같은 특정 V1 클래스를 새 구현으로 대체합니다.

**Topics**
+ [버전 1과 버전 2 간의 S3 클라이언트 차이점 AWS SDK for Java](migration-s3-client.md)
+ [Transfer Manager를 버전 1에서 버전 2로 마이그레이션 AWS SDK for Java](migration-s3-transfer-manager.md)
+ [버전 1에서 버전 2로 Amazon S3 URI 구문 분석에 관한 변경 사항](migration-s3-uri-parser.md)
+ [S3 이벤트 알림 API를 버전 1에서 버전 2로 변경](migration-s3-event-notification.md)

# 버전 1과 버전 2 간의 S3 클라이언트 차이점 AWS SDK for Java
<a name="migration-s3-client"></a>

이 주제에서는 SDK for Java 버전 1과 버전 2의 S3 클라이언트 간 차이점이 [마이그레이션 도구](migration-tool.md)가 마이그레이션을 자동화하는 방법에 따라 구성됩니다. 이 도구는 대부분의 메서드를 V1에서 V2로 마이그레이션하는 것을 지원하지만 일부 메서드는 수동으로 마이그레이션해야 합니다. S3 클라이언트 메서드 외에도 일부 S3 V1 클래스에는 수동으로 마이그레이션해야 하는 직접 V2와 동등한 요소가 없습니다.

**Contents**
+ [마이그레이션 도구에서 지원하는 V1 메서드 예제](#methods-tool-migration)
  + [`putObject`](#V1-V2-putobject)
  + [`getObject`](#V1-V2-getobject)
+ [수동 마이그레이션이 필요한 V1 메서드](#s3-methods-manual-migration)
  + [`S3ObjectId`을 사용하는 `getObject`](#V1s-getObject-using-V1s-S3ObjectId)
  + [`ObjectMetadata`을 사용하는 `getETag`](#V1s-ObjectMetadata-using-V1s-getETag)
  + [`listNextBatchOfObjects`](#V1-listNextBatchOfObjects)
  + [`listNextBatchOfVersions`](#V1-listNextBatchOfVersions)
  + [`selectObjectContent`](#V1-selectObjectContent)
  + [`setBucketAcl`](#V1-setBucketAcl)
  + [`setObjectAcl`](#V1-setObjectAcl)
  + [`initiateMultipartUpload`](#V1-initiateMultipartUpload)
    + [마이그레이션 예제](#V1-initiateMultipartUpload-migration-ex)
    + [구현 차이점](#V1-initiateMultipartUpload-impl-diffs)
  + [`setRegion`](#V1-setRegion)
  + [`setS3ClientOptions(S3ClientOptions clientOptions)`](#V1-setS3ClientOptions)
  + [`setBucketLoggingConfiguration`](#V1-setBucketLoggingConfiguration)
  + [`setBucketLifecycleConfiguration`](#V1-setBucketLifecycleConfiguration)
  + [`setBucketTaggingConfiguration`](#V1-setBucketTaggingConfiguration)
+ [수동 마이그레이션이 필요한 V1 클래스](#s3-classes-manual-migration)
  + [`AccessControlList`](#V1-AccessControlList)
  + [`CannedAccessControlList`](#V1-CannedAccessControlList)
  + [`BucketNotificationConfiguration`](#V1-BucketNotificationConfiguration)
  + [`MultiFactorAuthentication`](#V1-MultifactorAuthentication)

## 마이그레이션 도구에서 지원하는 V1 메서드 예제
<a name="methods-tool-migration"></a>

마이그레이션 도구는 대부분의 메서드를 V1에서 V2로 자동으로 마이그레이션합니다. `putObject` 및 `getObject` 메서드는 2가지 예제입니다.

### `putObject`
<a name="V1-V2-putobject"></a>

```
// SDK V1
s3Client.putObject("amzn-s3-demo-bucket", "my-key", "Hello World!");


// SDK V2
s3Client.putObject(req -> req 
    .bucket("amzn-s3-demo-bucket") 
    .key("my-key"), 
    RequestBody.fromString("Hello World!"));
```

### `getObject`
<a name="V1-V2-getobject"></a>

```
// SDK V1
S3Object object = s3Client.getObject("amzn-s3-demo-bucket", "my-key");
InputStream content = object.getObjectContent();


// SDK V2
ResponseInputStream<GetObjectResponse> response = s3Client.getObject(req -> req 
    .bucket("amzn-s3-demo-bucket") 
    .key("my-key"));
```

## 수동 마이그레이션이 필요한 V1 메서드
<a name="s3-methods-manual-migration"></a>

다음 V1 S3 클라이언트 메서드를 수동으로 마이그레이션해야 합니다. 마이그레이션 도구를 사용하면 V2 출력 Java 파일에 이 주제로 연결되는 설명이 표시됩니다.

### V1의 `S3ObjectId`에서 V2의 `GetObjectRequest.builder()`를 사용한 V1 `getObject`
<a name="V1s-getObject-using-V1s-S3ObjectId"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
        .withRegion(Regions.US_WEST_2)
        .build();

S3ObjectId s3ObjectId = new S3ObjectId(
    "amzn-s3-demo-bucket",
    "object-key",
    "abc123version" 
);

GetObjectRequest getRequest= new GetObjectRequest(s3ObjectId);
S3Object s3ObjectVersioned = s3Client.getObject(getRequest);


// SDK V2
// V2 does not include a 'S3ObjectId' class. V2 uses the request builder pattern 
// to supply the bucket, key, and version parameters.
S3Client s3Client = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

GetObjectRequest getRequest = GetObjectRequest.builder()
    .bucket("amzn-s3-demo-bucket")
    .key("object-key")
    .versionId("abc123version")
    .build();

ResponseInputStream<GetObjectResponse> response = s3Client.getObject(getRequest);
```

### V1의 `ObjectMetadata`에서 V2의 `GetObjectResponse.eTag()`를 사용한 V1 `getETag()`
<a name="V1s-ObjectMetadata-using-V1s-getETag"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

S3Object object = s3ClientV1.getObject("amzn-s3-demo-bucket", "my-key");

// Double quotes are removed by the S3 client.
System.out.println(object.getObjectMetadata().getETag());

// SDK V2
S3Client s3ClientV2 = S3Client.builder()
        .region(Region.US_WEST_2)
        .build();

ResponseInputStream<GetObjectResponse> response = s3ClientV2.getObject(
        req -> req.bucket("amzn-s3-demo-bucket").key("my-key"));

// Double quotes are *NOT* removed. This is the unchanged ETag value as S3 sent it.
System.out.println(response.response().eTag());
```

### V1의 `listNextBatchOfObjects`에서 V2의 `listObjectsV2Paginator`
<a name="V1-listNextBatchOfObjects"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

ObjectListing objectListing = s3ClientV1.listObjects("bucket-name");
while (objectListing.isTruncated()) {
    objectListing = s3ClientV1.listNextBatchOfObjects(objectListing);
    for (S3ObjectSummary summary : objectListing.getObjectSummaries()) {
        System.out.println(summary.getKey());
    }
}


// SDK V2
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

ListObjectsV2Request request = ListObjectsV2Request.builder()
    .bucket("bucket-name")
    .build();

// V2 returns a paginator.
ListObjectsV2Iterable responses = s3Client.listObjectsV2Paginator(request);

for (ListObjectsV2Response page : responses) {
    page.contents().forEach(content -> {
        System.out.println(content.key());
    });
}
```

### V1의 `listNextBatchOfVersions`에서 V2의 `listObjectVersionsPaginator`
<a name="V1-listNextBatchOfVersions"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

VersionListing versionListing = s3ClientV1.listVersions("bucket-name", "prefix");
while (versionListing.isTruncated()) {
    versionListing = s3ClientV1.listNextBatchOfVersions(versionListing);
    for (S3VersionSummary version : versionListing.getVersionSummaries()) {
        System.out.println(version.getKey() + " " + version.getVersionId());
    }
}


// SDK V2
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

ListObjectVersionsRequest request = ListObjectVersionsRequest.builder()
    .bucket("bucket-name")
    .prefix("prefix")
    .build();

// V2 returns a paginator.
ListObjectVersionsIterable responses = s3ClientV2.listObjectVersionsPaginator(request);

for (ListObjectVersionsResponse page : responses) {
    page.versions().forEach(version -> {
        System.out.println(version.key() + " " + version.versionId());
    });
}
```

### `selectObjectContent`
<a name="V1-selectObjectContent"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

SelectObjectContentRequest request = new SelectObjectContentRequest()
    .withBucket("bucket-name")
    .withKey("object-key")
    .withExpression("select * from S3Object")
    .withExpressionType(ExpressionType.SQL)
 

SelectObjectContentResult result = s3ClientV1.selectObjectContent(request);
InputStream resultInputStream = result.getPayload().getRecordsInputStream();


// SDK V2
// In V2, 'selectObjectContent()' is available only on the S3AsyncClient. 
// V2 handles responses using an event-based 'SelectObjectContentEventStream'.
S3AsyncClient s3ClientV2 = S3AsyncClient.builder()
    .region(Region.US_WEST_2)
    .build();

SelectObjectContentRequest request = SelectObjectContentRequest.builder()
    .bucket("bucket-name")
    .key("object-key")
    .expression("select * from S3Object")
    .expressionType(ExpressionType.SQL)
    .build();
    
SelectObjectContentResponseHandler handler = new SelectObjectContentResponseHandler() {
    // Implement the required abstract methods such as 'onEventStream()'.
};

CompletableFuture<Void> future = s3ClientV2.selectObjectContent(request, handler);
// The 'SelectObjectContentResponseHandler' implementation processes the results.
```

### `PutBucketAclRequest.builder()`에 V1의 `setBucketAcl`에서 V2의 `acl` 메서드
<a name="V1-setBucketAcl"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

AccessControlList acl = new AccessControlList();
acl.grantPermission(GroupGrantee.AllUsers, Permission.Read);
s3ClientV1.setBucketAcl("bucket-name", acl);


// SDK V2
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

PutBucketAclRequest request = PutBucketAclRequest.builder()
    .bucket("bucket-name")
    .acl(BucketCannedACL.PRIVATE)
    .build();

s3ClientV2.putBucketAcl(request);
```

### `PutObjectAclRequest.builder()`에 V1의 `setObjectAcl`에서 V2의 `acl` 메서드
<a name="V1-setObjectAcl"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

AccessControlList acl = new AccessControlList();
acl.grantPermission(GroupGrantee.AllUsers, Permission.Read);
s3ClientV1.setObjectAcl("bucket-name", "object-key", acl);


// SDK V2
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

PutObjectAclRequest request = PutObjectAclRequest.builder()
    .bucket("bucket-name")
    .key("object-key")
    .acl(ObjectCannedACL.PRIVATE)
    .build();

s3ClientV2.putObjectAcl(request);
```

### V1의 `initiateMultipartUpload`에서 V2의 `createMultipartUpload`
<a name="V1-initiateMultipartUpload"></a>

#### 마이그레이션 예제
<a name="V1-initiateMultipartUpload-migration-ex"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();
    
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType("application/zip");
metadata.addUserMetadata("mykey", "myvalue");

InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(
    "bucket-name", 
    "object-key",
    metadata
);

InitiateMultipartUploadResult initResponse = s3ClientV1.initiateMultipartUpload(initRequest);
String uploadId = initResponse.getUploadId();


// SDK V2
// V1 uses ObjectMetadata methods, whereas V2 uses a simple Map.
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

CreateMultipartUploadRequest createMultipartRequest = CreateMultipartUploadRequest.builder() 
    .bucket("amzn-s3-demo-bucket") 
    .key("object-key") 
    .contentType("application/zip") 
    .metadata(Collections.singletonMap("mykey", "myvalue"))
    .build();

CreateMultipartUploadResponse response = s3ClientV2.createMultipartUpload(createMultipartRequest);
String uploadId = response.uploadId();
```

#### 구현 차이점
<a name="V1-initiateMultipartUpload-impl-diffs"></a>

다음 메서드의 기본 `Content-Type` 헤더 값은 다음 테이블의 내용과 같이 다릅니다.


****  

| SDK 버전 | 방법 | 기본값 `Content-Type` | 
| --- | --- | --- | 
| 버전 1 | [initiateMultipartUpload](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html#initiateMultipartUpload-com.amazonaws.services.s3.model.InitiateMultipartUploadRequest-) | application/octet-stream | 
| 버전 2 | [createMultipartUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html#createMultipartUpload(software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest)) | binary/octet-stream | 

### 클라이언트 빌더에 V1의 `setRegion`에서 V2의 `region` 메서드
<a name="V1-setRegion"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard().build();
s3ClientV1.setRegion(Region.getRegion(Regions.US_WEST_2));


// SDK V2
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();
```

### V1의 `setS3ClientOptions(S3ClientOptions clientOptions)`
<a name="V1-setS3ClientOptions"></a>

V2는 `setS3ClientOptions` 메서드와 함께 단일 `S3ClientOptions` 객체를 사용하는 대신 클라이언트 빌더에 옵션을 설정하는 메서드를 제공합니다.

### V1의 `setBucketLoggingConfiguration`에서 V2의 `putBucketLogging`
<a name="V1-setBucketLoggingConfiguration"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

BucketLoggingConfiguration loggingConfig = new BucketLoggingConfiguration();
loggingConfig.setDestinationBucketName("log-bucket");

SetBucketLoggingConfigurationRequest request = new SetBucketLoggingConfigurationRequest(
    "amzn-s3-demo-source-bucket",
    loggingConfig
);

s3ClientV1.setBucketLoggingConfiguration(request);


// SDK V2
// In V2, V1's 'BucketLoggingConfiguration' is replaced by 'BucketLoggingStatus' 
// and 'LoggingEnabled'.
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

LoggingEnabled loggingEnabled = LoggingEnabled.builder()
    .targetBucket("log-bucket")
    .build();

BucketLoggingStatus loggingStatus = BucketLoggingStatus.builder()
    .loggingEnabled(loggingEnabled)
    .build();

PutBucketLoggingRequest request = PutBucketLoggingRequest.builder()
    .bucket("amzn-s3-demo-source-bucket")
    .bucketLoggingStatus(loggingStatus)
    .build();

s3ClientV2.putBucketLogging(request);
```

### V1의 `setBucketLifecycleConfiguration`에서 V2의 `putBucketLifecycleConfiguration`
<a name="V1-setBucketLifecycleConfiguration"></a>

```
// SDK V1
BucketLifecycleConfiguration.Rule rule = new BucketLifecycleConfiguration.Rule()
    .withId("Archive and Delete Rule")
    .withPrefix("documents/")
    .withStatus(BucketLifecycleConfiguration.ENABLED)
    .withTransitions(Arrays.asList(
        new Transition()
            .withDays(30)
            .withStorageClass(StorageClass.StandardInfrequentAccess.toString()),
        new Transition()
            .withDays(90)
            .withStorageClass(StorageClass.Glacier.toString())
    ))
    .withExpirationInDays(365);

BucketLifecycleConfiguration configuration = new BucketLifecycleConfiguration()
    .withRules(Arrays.asList(rule));

s3ClientV1.setBucketLifecycleConfiguration("amzn-s3-demo-bucket", configuration);


// SDK V2
LifecycleRule rule = LifecycleRule.builder()
    .id("Archive and Delete Rule")
    .filter(LifecycleRuleFilter.builder()
        .prefix("documents/")
        .build())
    .status(ExpirationStatus.ENABLED)
    .transitions(Arrays.asList(
        Transition.builder()
            .days(30)
            .storageClass(TransitionStorageClass.STANDARD_IA)
            .build(),
        Transition.builder()
            .days(90)
            .storageClass(TransitionStorageClass.GLACIER)
            .build()
    ))
    .expiration(LifecycleExpiration.builder()
        .days(365)
        .build())
    .build();

PutBucketLifecycleConfigurationRequest request = PutBucketLifecycleConfigurationRequest.builder()
    .bucket("amzn-s3-demo-bucket")
    .lifecycleConfiguration(BucketLifecycleConfiguration.builder()
        .rules(rule)
        .build())
    .build();

s3ClientV2.putBucketLifecycleConfiguration(request);
```

### V1의 `setBucketTaggingConfiguration`에서 V2의 `putBucketTagging`
<a name="V1-setBucketTaggingConfiguration"></a>

```
// SDK V1
List<TagSet> tagsets = new ArrayList<>();
TagSet tagSet = new TagSet();
tagSet.setTag("key1", "value1");
tagSet.setTag("key2", "value2");
tagsets.add(tagSet);

BucketTaggingConfiguration bucketTaggingConfiguration = new BucketTaggingConfiguration();
bucketTaggingConfiguration.setTagSets(tagsets);

SetBucketTaggingConfigurationRequest request = new SetBucketTaggingConfigurationRequest(
    "amzn-s3-demo-bucket",
    bucketTaggingConfiguration
);

s3ClientV1.setBucketTaggingConfiguration(request);


// SDK V2
Tagging tagging = Tagging.builder()
    .tagSet(Arrays.asList(
        Tag.builder()
            .key("key1")
            .value("value1")
            .build(),
        Tag.builder()
            .key("key2")
            .value("value2")
            .build()
    ))
    .build();

PutBucketTaggingRequest request = PutBucketTaggingRequest.builder()
    .bucket("amzn-s3-demo-bucket")
    .tagging(tagging)
    .build();

s3ClientV2.putBucketTagging(request);
```

## 수동 마이그레이션이 필요한 V1 클래스
<a name="s3-classes-manual-migration"></a>

### V1의 `AccessControlList`에서 V2의 `AccessControlPolicy`
<a name="V1-AccessControlList"></a>

```
// SDK V1
AccessControlList aclV1 = new AccessControlList();
aclV1.setOwner(new Owner("owner-id", "owner-name"));
aclV1.grantPermission(GroupGrantee.AllUsers, Permission.Read);

// SDK V2
// To migrate from V1 to V2, replace direct 'AccessControlList' modifications with an
// 'AccessControlPolicy.builder()' that contains both owner information and grants. 
// Note that V2's approach requires building the complete permission set upfront rather than modifying permissions incrementally.
AccessControlPolicy acpV2 = AccessControlPolicy.builder()
    .owner(Owner.builder()
        .id("owner-id")
        .displayName("owner-name")
        .build())
    .grants(Arrays.asList(
         Grant.builder()
            .grantee(Grantee.builder()
                 .type(Type.GROUP)
                 .uri("http://acs.amazonaws.com/groups/global/AllUsers") 
                 .build())
             .permission(Permission.READ)
             .build()
     ))
     .build();
```

### V1의 `CannedAccessControlList` 열거형에서 V2의 `BucketCannedACL` 및 `ObjectCannedACL` 열거형
<a name="V1-CannedAccessControlList"></a>

```
// SDK V1
// In V1, 'CannedAccessControlList' is an enumeration of predefined ACLs.
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard().build();

// Creating a bucket.
s3ClientV1.setBucketAcl("bucket-name", CannedAccessControlList.PublicRead);

// Creating an object.
PutObjectRequest putObjectRequest = new PutObjectRequest("bucket-name", "object-key", file)
    .withCannedAcl(CannedAccessControlList.PublicRead);
s3ClientV1.putObject(putObjectRequest);


// SDK V2
// V2 replaces V1's 'CannedAccessControlList' with 'BucketCannedACL' for buckets and 'ObjectCannedACL' for objects.
S3Client s3ClientV2 = S3Client.builder().build();

// Creating a bucket.
PutBucketAclRequest bucketRequest = PutBucketAclRequest.builder()
    .bucket("bucket-name")
    .acl(BucketCannedACL.PRIVATE)
    .build();
s3ClientV2.putBucketAcl(bucketRequest);

// Creating an object.
PutObjectRequest objectRequest = PutObjectRequest.builder()
    .bucket("bucket-name")
    .key("object-key")
    .acl(ObjectCannedACL.PUBLIC_READ)
    .build();
s3ClientV2.putObject(objectRequest, RequestBody.fromFile(file));
```

### V1의 `BucketNotificationConfiguration`에서 V2의 `NotificationConfiguration`
<a name="V1-BucketNotificationConfiguration"></a>

```
//SDK V1
BucketNotificationConfiguration notificationConfig = new BucketNotificationConfiguration();

// Adding configurations by name
notificationConfig.addConfiguration("lambdaConfig", 
    new LambdaConfiguration("arn:aws:lambda:function", "s3:ObjectCreated:"));

notificationConfig.addConfiguration("topicConfig",
    new TopicConfiguration("arn:aws:sns:topic", "s3:ObjectRemoved:"));

notificationConfig.addConfiguration("queueConfig",
    new QueueConfiguration("arn:aws:sqs:queue", "s3:ObjectRestore:*"));

s3Client.setBucketNotificationConfiguration("bucket", notificationConfig);


// SDK V2
// In V2, V1's BucketNotificationConfiguration is renamed to NotificationConfiguration. 
// V2 contains no common abstract class for LambdaFunction/Topic/Queue configurations.
NotificationConfiguration notificationConfig = NotificationConfiguration.builder()
    .lambdaFunctionConfigurations(
        LambdaFunctionConfiguration.builder()
            .lambdaFunctionArn("arn:aws:lambda:function")
            .events(Event.valueOf("s3:ObjectCreated:"))
            .build())
    .topicConfigurations(
        TopicConfiguration.builder()
            .topicArn("arn:aws:sns:topic")
            .events(Event.valueOf("s3:ObjectRemoved:"))
            .build())
    .queueConfigurations(
        QueueConfiguration.builder()
            .queueArn("arn:aws:sqs:queue")
            .events(Event.valueOf("s3:ObjectRestore:*"))
            .build())
    .build();

s3Client.putBucketNotificationConfiguration(req -> req
    .bucket("bucket")
    .notificationConfiguration(notificationConfig));
```

### 요청 빌더에 V1의 `MultiFactorAuthentication`에서 V2의 `mfa` 메서드
<a name="V1-MultifactorAuthentication"></a>

```
// SDK V1
AmazonS3 s3ClientV1 = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.US_WEST_2)
    .build();

BucketVersioningConfiguration versioningConfig = new BucketVersioningConfiguration()
    .withStatus(BucketVersioningConfiguration.ENABLED);

// Create an MFA configuration object.
MultiFactorAuthentication mfa = new MultiFactorAuthentication(
    "arn:aws:iam::1234567890:mfa/user",
    "123456"
);

// Create the request object.
SetBucketVersioningConfigurationRequest request = new SetBucketVersioningConfigurationRequest(
    "bucket-name",
    versioningConfig,
    mfa
);

// Send the request.
s3ClientV1.setBucketVersioningConfiguration(request);


// SDK V2
// V2 replaces V1's MultiFactorAuthentication POJO with parameters you set on the request builder.
S3Client s3ClientV2 = S3Client.builder()
    .region(Region.US_WEST_2)
    .build();

PutBucketVersioningRequest request = PutBucketVersioningRequest.builder()
    .bucket("bucket-name")
    .versioningConfiguration(VersioningConfiguration.builder()
        .status(BucketVersioningStatus.ENABLED)
        .build())
    .mfa("arn:aws:iam::1234567890:mfa/user 123456")  // Single method takes both MFA erial number and token.
    .build();

s3ClientV2.putBucketVersioning(request);
```

# Transfer Manager를 버전 1에서 버전 2로 마이그레이션 AWS SDK for Java
<a name="migration-s3-transfer-manager"></a>

이 마이그레이션 안내서에서는 생성자 변경 사항, 메서드 매핑 및 일반적인 작업에 대한 코드 예제를 포함하여 Transfer Manager v1과 S3 Transfer Manager v2 간의 주요 차이점을 다룹니다. 이러한 차이점을 검토한 후 기존 Transfer Manager 코드를 성공적으로 마이그레이션하여 v2에서 향상된 성능과 비동기식 작업을 활용할 수 있습니다.

**AWS SDK 마이그레이션 도구 정보**  
는 v1 Transfer Manager API의 대부분을 v2로 마이그레이션할 수 있는 자동화된 [마이그레이션 도구를](migration-tool.md) AWS SDK for Java 제공합니다. 그러나 마이그레이션 도구는 여러 v1 Transfer Manager 기능을 지원하지 않습니다. 이러한 경우 이 주제의 안내를 사용하여 Transfer Manager 코드를 수동으로 마이그레이션해야 합니다.  
이 안내서 전체에서 **마이그레이션 상태**는 마이그레이션 도구가 생성자, 메서드 또는 기능을 자동으로 마이그레이션할 수 있는지 여부를 보여줍니다.  
**지원됨**: 마이그레이션 도구가 이 코드를 자동으로 변환할 수 있습니다.
**지원되지 않음**: 코드를 수동으로 마이그레이션해야 합니다.
‘지원됨’으로 표시된 항목에 대해서도 마이그레이션 결과를 검토하고 철저히 테스트합니다. Transfer Manager 마이그레이션에는 동기식 작업에서 비동기식 작업으로의 상당한 아키텍처 변경이 포함됩니다.

## 개요
<a name="s3-tm-migration-overview"></a>

S3 Transfer Manager v2는 Transfer Manager API에 중요한 변경 사항을 도입합니다. S3 Transfer Manager v2는 비동기 작업을 기반으로 하며 특히 AWS CRT 기반 Amazon S3 클라이언트를 사용할 때 더 나은 성능을 제공합니다.

### 주요 차이점
<a name="s3-tm-migration-key-differences"></a>
+ **패키지**: `com.amazonaws.services.s3.transfer` → `software.amazon.awssdk.transfer.s3`
+ **클래스 이름**: `TransferManager` → `S3TransferManager`
+ **클라이언트 종속성**: 동기식 Amazon S3 클라이언트 → 비동기식 Amazon S3 클라이언트(`S3AsyncClient`)
+ **아키텍처**: 동기식 작업 → `CompletableFuture`를 사용한 비동기식 작업
+ **성능**: AWS CRT 기반 클라이언트 지원으로 향상

## 높은 수준의 변경 사항
<a name="s3-tm-migration-high-level-changes"></a>


| 속성 | V1 | V2 | 
| --- | --- | --- | 
| Maven 종속성 | aws-java-sdk-s3 | s3-transfer-manager | 
| Package | com.amazonaws.services.s3.transfer | software.amazon.awssdk.transfer.s3 | 
| 기본 클래스 | TransferManager | S3TransferManager | 
| Amazon S3 클라이언트 | AmazonS3(동기식) | S3AsyncClient(비동기식) | 
| 반환 유형 | 차단된 작업 | CompletableFuture<T> | 

## Maven 종속성
<a name="s3-tm-migration-dependencies"></a>


| V1 | V2 | 
| --- | --- | 
|  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>>1.12.7871</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-java-sdk-s3</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.31.682</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3-transfer-manager</artifactId><br />    </dependency><br />    <!-- Optional: For enhanced performance with AWS CRT --><br />    <dependency><br />        <groupId>software.amazon.awssdk.crt</groupId><br />        <artifactId>aws-crt</artifactId><br />        <version>0.38.53</version><br />    </dependency><br /></dependencies></pre>  | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom). 3[최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt).

## 클라이언트 생성자 마이그레이션
<a name="s3-tm-migration-client-constructor"></a>

### 지원되는 생성자(자동 마이그레이션)
<a name="s3-tm-migration-supported-constructors"></a>


| V1 생성자 | V2와 동일 | 마이그레이션 상태 | 
| --- | --- | --- | 
| new TransferManager() | S3TransferManager.create() | 지원됨 | 
| TransferManagerBuilder. defaultTransferManager() | S3TransferManager.create() | 지원됨 | 
| TransferManagerBuilder. standard().build() | S3TransferManager.builder().build() | 지원됨 | 
| new TransferManager(AWSCredentials) | S3TransferManager.builder() .s3Client(S3AsyncClient.builder() .credentialsProvider(...).build()) .build() | 지원됨 | 
| new TransferManager( AWSCredentialsProvider) | S3TransferManager.builder() .s3Client(S3AsyncClient.builder() .credentialsProvider(...).build()) .build() | 지원됨 | 

### 지원되지 않는 생성자(수동 마이그레이션 필요)
<a name="s3-tm-migration-unsupported-constructors"></a>


| V1 생성자 | V2와 동일 | 마이그레이션 참고 사항 | 
| --- | --- | --- | 
| new TransferManager(AmazonS3) | 수동 마이그레이션 필요 | S3AsyncClient 별도로 만들기 | 
| new TransferManager(AmazonS3, ExecutorService) | 수동 마이그레이션 필요 | S3AsyncClient 만들기 및 실행기 구성 | 
| new TransferManager(AmazonS3, ExecutorService, boolean) | 수동 마이그레이션 필요 | 지원되지 않는 shutDownThreadPools 파라미터 | 

### 수동 마이그레이션 예제
<a name="s3-tm-migration-manual-examples"></a>

**V1 코드:**

```
AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
TransferManager transferManager = new TransferManager(s3Client);
```

**V2 코드:**

```
// Create an `S3AsyncClient` with similar configuration
S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
    .credentialsProvider(DefaultCredentialsProvider.create())
    .build();

// Provide the configured `S3AsyncClient` to the S3 transfer manager builder.
S3TransferManager transferManager = S3TransferManager.builder()
    .s3Client(s3AsyncClient)
    .build();
```

## 클라이언트 메서드 마이그레이션
<a name="s3-tm-migration-client-methods"></a>

현재 마이그레이션 도구는 기본 `copy`, `download`, `upload`, `uploadDirectory`, `downloadDirectory`, `resumeDownload`, `resumeUpload` 메서드를 지원합니다.

### 주요 전송 메서드
<a name="s3-tm-migration-core-transfer-methods"></a>


| V1 메서드 | V2 메서드 | 반환 유형 변경 사항 | 마이그레이션 상태 | 
| --- | --- | --- | --- | 
| upload(String, String, File) | uploadFile(UploadFileRequest) | Upload → FileUpload | 지원됨 | 
| upload(PutObjectRequest) | upload(UploadRequest) | Upload → Upload | 지원됨 | 
| download(String, String, File) | downloadFile(DownloadFileRequest) | Download → FileDownload | 지원됨 | 
| download(GetObjectRequest, File) | downloadFile(DownloadFileRequest) | Download → FileDownload | 지원됨 | 
| copy(String, String, String, String) | copy(CopyRequest) | Copy → Copy | 지원됨 | 
| copy(CopyObjectRequest) | copy(CopyRequest) | Copy → Copy | 지원됨 | 
| uploadDirectory(String, String, File, boolean) | uploadDirectory( UploadDirectoryRequest) | MultipleFileUpload → DirectoryUpload | 지원됨 | 
| downloadDirectory(String, String, File) | downloadDirectory( DownloadDirectoryRequest) | MultipleFileDownload → DirectoryDownload | 지원됨 | 

### 재사용 가능한 전송 메서드
<a name="s3-tm-migration-resumable-methods"></a>


| V1 메서드 | V2 메서드 | 마이그레이션 상태 | 
| --- | --- | --- | 
| resumeUpload(PersistableUpload) | resumeUploadFile(ResumableFileUpload) | 지원됨 | 
| resumeDownload(PersistableDownload) | resumeDownloadFile(ResumableFileDownload) | 지원됨 | 

### 수명 주기 메서드
<a name="s3-tm-migration-lifecycle-methods"></a>


| V1 메서드 | V2 메서드 | 마이그레이션 상태 | 
| --- | --- | --- | 
| shutdownNow() | close() | 지원됨 | 
| shutdownNow(boolean) | close() 메서드를 사용하여 수동으로 코드 조정 | 지원되지 않음 | 

### 지원되지 않는 V1 클라이언트 메서드
<a name="s3-tm-migration-unsupported-methods"></a>


| V1 메서드 | V2 대안 | 참고 | 
| --- | --- | --- | 
| abortMultipartUploads(String, Date) | 하위 수준 Amazon S3 클라이언트 사용 | 지원되지 않음 | 
| getAmazonS3Client() | 참조를 별도로 저장 | 지원되지 않음, v2에 getter 없음 | 
| getConfiguration() | 참조를 별도로 저장 | 지원되지 않음, v2에 getter 없음 | 
| uploadFileList(...) | 여러 uploadFile() 직접 호출 | 지원되지 않음 | 
| TransferStateChangeListener 파라미터가 있는 copy 메서드 | TransferListener 사용 | [수동 마이그레이션 예제 참조](#tm-unsupported-client-methods-copy) | 
| S3ProgressListener 파라미터가 있는 download 메서드 | [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/TransferListener.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/TransferListener.html) 사용 | [수동 마이그레이션 예제 참조](#tm-unsupported-client-methods-download) | 
|  파라미터가 4개 이상인 `downloadDirectory` 메서드  |  | [수동 마이그레이션 예제 참조](#tm-unsupported-client-methods-download-dir) | 
| ObjectMetadataProvider 파라미터가 있는 upload 메서드 | 요청 시 메타데이터 설정 | [수동 마이그레이션 예제 참조](#tm-unsupported-client-methods-upload) | 
| \$1Provider 파라미터가 있는 uploadDirectory 메서드 | 요청 시 태그 설정 | [수동 마이그레이션 예제 참조](#tm-unsupported-client-methods-uploadDirectory) | 

#### `TransferStateChangeListener` 파라미터가 있는 `copy` 메서드
<a name="tm-unsupported-client-methods-copy"></a>
+ `copy(CopyObjectRequest copyObjectRequest, AmazonS3 srcS3, TransferStateChangeListener stateChangeListener)`
+ `copy(CopyObjectRequest copyObjectRequest, TransferStateChangeListener stateChangeListener)`

```
// V1 ----------------------------------------------------------------------------------------------
// Initialize source S3 client
AmazonS3 s3client = AmazonS3ClientBuilder.standard()
                .withRegion("us-west-2")
                .build();
                
// Initialize Transfer Manager
TransferManager tm = TransferManagerBuilder.standard()
                .withS3Client(srcS3)
                .build();

CopyObjectRequest copyObjectRequest = new CopyObjectRequest(
                "amzn-s3-demo-source-bucket",
                "source-key",         
                "amzn-s3-demo-destination-bucket", 
                "destination-key"    
        );

TransferStateChangeListener stateChangeListener = new TransferStateChangeListener() {
            @Override
            public void transferStateChanged(Transfer transfer, TransferState state) {
              //Implementation of the TransferStateChangeListener
            }
        };

Copy copy = tm.copy(copyObjectRequest, srcS3, stateChangeListener);


// V2 ----------------------------------------------------------------------------------------------
S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
                .region(Region.US_WEST_2)          
                .build();

S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();

// Create transfer listener (equivalent to TransferStateChangeListener in v1)                                
TransferListener transferListener = new TransferListener() {
            @Override
            public void transferInitiated(Context.TransferInitiated context) {
               //Implementation
               System.out.println("Transfer initiated");
            }

            @Override
            public void bytesTransferred(Context.BytesTransferred context) {
                //Implementation
                System.out.println("Bytes transferred");
            }

            @Override
            public void transferComplete(Context.TransferComplete context) {
                //Implementation
                System.out.println("Transfer completed!");
            }

            @Override
            public void transferFailed(Context.TransferFailed context) {
                //Implementation
                System.out.println("Transfer failed");
            }
        };

CopyRequest copyRequest = CopyRequest.builder()
                              .copyObjectRequest(req -> req
                                  .sourceBucket("amzn-s3-demo-source-bucket")
                                  .sourceKey("source-key")
                                  .destinationBucket("amzn-s3-demo-destination-bucket")
                                  .destinationKey("destination-key")
                               )
                                .addTransferListener(transferListener) // Configure the transferListener into the request
                                .build();
  
Copy copy = transferManager.copy(copyRequest);
```

#### `S3ProgressListener` 파라미터가 있는 `download` 메서드
<a name="tm-unsupported-client-methods-download"></a>
+ `download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener)`
+ `download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis)`
+ `download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis, boolean resumeOnRetry)`

```
// V1 ----------------------------------------------------------------------------------------------
S3ProgressListener progressListener = new S3ProgressListener() {
        @Override
        public void progressChanged(com.amazonaws.event.ProgressEvent progressEvent) {
            long bytes = progressEvent.getBytesTransferred();
            ProgressEventType eventType = progressEvent.getEventType();
            // Use bytes and eventType as needed
        }

        @Override
        public void onPersistableTransfer(PersistableTransfer persistableTransfer) {

        }
    };

Download download1 = tm.download(getObjectRequest, file, progressListener); 
Download download2 = tm.download(getObjectRequest, file, progressListener, timeoutMillis)
Download download3 = tm.download(getObjectRequest, file, progressListener, timeoutMillis, true)

// V2 ----------------------------------------------------------------------------------------------
TransferListener transferListener = new TransferListener() {
    @Override
    public void transferInitiated(Context.InitializedContext context) {
        // Equivalent to ProgressEventType.TRANSFER_STARTED_EVENT
        System.out.println("Transfer initiated");
    }

    @Override
    public void bytesTransferred(Context.BytesTransferred context) {
        // Equivalent to ProgressEventType.REQUEST_BYTE_TRANSFER_EVENT
        long bytes = context.bytesTransferred();
        System.out.println("Bytes transferred: " + bytes);
    }

    @Override
    public void transferComplete(Context.TransferComplete context) {
        // Equivalent to ProgressEventType.TRANSFER_COMPLETED_EVENT
        System.out.println("Transfer completed");
    }

    @Override
    public void transferFailed(Context.TransferFailed context) {
        // Equivalent to ProgressEventType.TRANSFER_FAILED_EVENT
        System.out.println("Transfer failed: " + context.exception().getMessage());
    }
};
DownloadFileRequest downloadFileRequest = 
                         DownloadFileRequest.builder()
                             .getObjectRequest(getObjectRequest)
                             .destination(file.toPath())
                             .addTransferListener(transferListener)
                             .build();

// For download1
FileDownload download = transferManager.downloadFile(downloadFileRequest);

// For download2
CompletedFileDownload completedFileDownload = download.completionFuture()
                                                  .get(timeoutMillis, TimeUnit.MILLISECONDS);

// For download3, the v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1.
// If a download is interrupted, you need to start a new download request.
```

#### 파라미터가 4개 이상인 `downloadDirectory` 메서드
<a name="tm-unsupported-client-methods-download-dir"></a>
+ `downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry)`
+ `downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry, KeyFilter filter)`
+ `downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, KeyFilter filter)`

```
// V1 ----------------------------------------------------------------------------------------------
KeyFilter filter = new KeyFilter() {
            @Override
            public boolean shouldInclude(S3ObjectSummary objectSummary) {
                //Filter implementation
            }
        };
MultipleFileDownload multipleFileDownload = tm.downloadDirectory(bucketName, keyPrefix, destinationDirectory, filter);

// V2 ----------------------------------------------------------------------------------------------
// The v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1.
// If a download is interrupted, you need to start a new download request.
DownloadFilter filter = new DownloadFilter() {
            @Override
            public boolean test(S3Object s3Object) {
                // Filter implementation.
            }
        };

DownloadDirectoryRequest downloadDirectoryRequest = 
                              DownloadDirectoryRequest.builder()
                                  .bucket(bucketName)
                                  .filter(filter)
                                  .listObjectsV2RequestTransformer(builder -> builder.prefix(keyPrefix))
                                  .destination(destinationDirectory.toPath())
                                  .build();
                                                                            
DirectoryDownload directoryDownload = transferManager.downloadDirectory(downloadDirectoryRequest);
```

#### `ObjectMetadata` 파라미터가 있는 `upload` 메서드
<a name="tm-unsupported-client-methods-upload"></a>
+ `upload(String bucketName, String key, InputStream input, ObjectMetadata objectMetadata)`

```
// V1 ----------------------------------------------------------------------------------------------ObjectMetadata metadata = new ObjectMetadata();
ObjectMetadata metadata = new ObjectMetadata();

metadata.setContentType("text/plain");        // System-defined metadata
metadata.setContentLength(22L);               // System-defined metadata
metadata.addUserMetadata("myKey", "myValue"); // User-defined metadata

PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, metadata);

Upload upload = transferManager.upload("amzn-s3-demo-bucket", "my-key", inputStream, metadata);

// V2 ----------------------------------------------------------------------------------------------
/* When you use an InputStream to upload in V2, you should specify the content length 
   and use `RequestBody.fromInputStream()`. 
   If you don't provide the content length, the entire stream will be buffered in memory. 
   If you can't determine the content length, we recommend using the CRT-based S3 client.
*/
Map<String, String> userMetadata = new HashMap<>();
userMetadata.put("x-amz-meta-myKey", "myValue");

PutObjectRequest putObjectRequest = 
                        PutObjectRequest.builder()
                            .bucket("amzn-s3-demo-bucket1")
                            .key("k")
                            .contentType("text/plain") //System-defined metadata usually has separate methods in the builder.
                            .contentLength(22L)
                            .metadata(userMetadata) //metadata() is only for user-defined metadata.
                            .build();

UploadRequest uploadRequest = 
                        UploadRequest.builder()
                            .putObjectRequest(putObjectRequest)
                            .requestBody(AsyncRequestBody.fromInputStream(stream, 22L, executor))
                            .build();
                                                   
transferManager.upload(uploadRequest).completionFuture().join();
```

#### `ObjectMetadataProvider` 파라미터가 있는 `uploadDirectory`
<a name="tm-unsupported-client-methods-uploadDirectory"></a>
+ `uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider)`
+ `uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider)`
+ `uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider, ObjectCannedAclProvider cannedAclProvider)`

```
// V1 ----------------------------------------------------------------------------------------------
tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider)
tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider)
tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider, cannedAclProvider)

// V2 ----------------------------------------------------------------------------------------------
UploadDirectoryRequest request = UploadDirectoryRequest.builder()
                                  .bucket(bucketName)
                                  .s3Prefix(virtualDirectoryKeyPrefix)
                                  .source(directory.toPath())
                                  .maxDepth(includeSubdirectories ? Integer.MAX_VALUE : 1)
                                  .uploadFileRequestTransformer(builder -> {
                                      // 1.Replace `ObjectMetadataProvider`, `ObjectTaggingProvider`, and `ObjectCannedAclProvider` with an
                                        // `UploadFileRequestTransformer` that can combine the functionality of all three *Provider implementations.
                                        // 2. Convert your v1 `ObjectMetadata` to v2 `PutObjectRequest` parameters.
                                        // 3. Convert your v1 `ObjectTagging` to v2 `Tagging`.
                                        // 4. Convert your v1 `CannedAccessControlList` to v2 `ObjectCannedACL`.
                                  })
                                  .build();
        
DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
```

## 모델 객체 마이그레이션
<a name="s3-tm-migration-model-objects"></a>

에서는 AWS SDK for Java 2.x많은 `TransferManager` 모델 객체가 재설계되었으며 v1의 모델 객체에서 사용할 수 있는 여러 getter 및 setter 메서드가 더 이상 지원되지 않습니다.

v2에서는 `CompletableFuture<T>` 클래스를 사용하여 전송이 성공적으로 완료되거나 예외가 발생했을 때 작업을 수행합니다. 필요한 경우 `join()` 메서드를 사용하여 완료될 때까지 기다릴 수 있습니다.

### 주요 전송 객체
<a name="s3-tm-migration-core-transfer-objects"></a>


| V1 클래스 | V2 클래스 | 마이그레이션 상태 | 
| --- | --- | --- | 
| TransferManager | S3TransferManager | 지원됨 | 
| TransferManagerBuilder | S3TransferManager.Builder | 지원됨 | 
| Transfer | Transfer | 지원됨 | 
| AbortableTransfer | Transfer | 지원됨(별도 클래스 없음) | 
| Copy | Copy | 지원됨 | 
| Download | FileDownload | 지원됨 | 
| Upload | Upload / FileUpload | 지원됨 | 
| MultipleFileDownload | DirectoryDownload | 지원됨 | 
| MultipleFileUpload | DirectoryUpload | 지원됨 | 

### 객체 지속성
<a name="s3-tm-migration-persistence-objects"></a>


| V1 클래스 | V2 클래스 | 마이그레이션 상태 | 
| --- | --- | --- | 
| PersistableDownload | ResumableFileDownload | 지원됨 | 
| PersistableUpload | ResumableFileUpload | 지원됨 | 
| PersistableTransfer | ResumableTransfer | 지원됨 | 
| PauseResult<T> | 직접 재개 가능한 객체 | 지원되지 않음 | 

### 결과 객체
<a name="s3-tm-migration-result-objects"></a>


| V1 클래스 | V2 클래스 | 마이그레이션 상태 | 
| --- | --- | --- | 
| CopyResult | CompletedCopy | 지원됨 | 
| UploadResult | CompletedUpload | 지원됨 | 

### 구성 객체
<a name="s3-tm-migration-configuration-objects"></a>


| V1 클래스 | V2 클래스 | 마이그레이션 상태 | 
| --- | --- | --- | 
| TransferManagerConfiguration | MultipartConfiguration(Amazon S3 클라이언트 기반) | 지원됨 | 
| TransferProgress | TransferProgress \$1 TransferProgressSnapshot | 지원됨 | 
| KeyFilter | DownloadFilter | 지원됨 | 

### 지원되지 않는 객체
<a name="s3-tm-migration-unsupported-objects"></a>


| V1 클래스 | V2 대안 | 마이그레이션 상태 | 
| --- | --- | --- | 
| PauseStatus | 지원되지 않음 | 지원되지 않음 | 
| UploadContext | 지원되지 않음 | 지원되지 않음 | 
| ObjectCannedAclProvider | PutObjectRequest.builder().acl() | 지원되지 않음 | 
| ObjectMetadataProvider | PutObjectRequest.builder().metadata() | 지원되지 않음 | 
| ObjectTaggingProvider | PutObjectRequest.builder().tagging() | 지원되지 않음 | 
| PresignedUrlDownload | 지원되지 않음 | 지원되지 않음 | 

## TransferManagerBuilder 구성 마이그레이션
<a name="s3-tm-migration-builder-configuration"></a>

### 구성 변경
<a name="migration-transfer-manager-config-changes"></a>

v2 Transfer Manager에 대해 설정해야 하는 구성 변경 사항은 사용하는 S3 클라이언트에 따라 다릅니다. AWS CRT 기반 S3 클라이언트 또는 표준 Java 기반 S3 비동기 클라이언트 중에서 선택할 수 있습니다. 차이점에 대한 자세한 내용은 [의 S3 클라이언트 AWS SDK for Java 2.x](examples-s3.md#s3-clients) 주제를 참조하세요.

------
#### [ Use the AWS CRT-based S3 client ]


****  

| 설정 | v1 | v2 - AWS CRT 기반 S3 클라이언트를 사용하는 Transfer Manager | 
| --- | --- | --- | 
|    (빌더 구하기)  |  <pre>TransferManagerBuilder tmBuilder = <br />   TransferManagerBuilder.standard();</pre>  |  <pre>S3TransferManager.Builder tmBuilder  = <br />  S3TransferManager.builder();</pre>  | 
|    S3 클라이언트  |  <pre>tmBuilder.withS3Client(...);<br />tmBuilder.setS3Client(...);</pre>  |  <pre>tmBuilder.s3Client(...);</pre>  | 
|    실행자  |  <pre>tmBuilder.withExecutorFactory(...);<br />tmBuilder.setExecutorFactory(...);</pre>  |  <pre>tmBuilder.executor(...);</pre>  | 
|    스레드 풀 종료  |  <pre>tmBuilder.withShutDownThreadPools(...);<br />tmBuilder.setShutdownThreadPools(...);</pre>  | 지원되지 않음. 제공된 실행기는 S3TransferManager가 닫힐 때 종료되지 않습니다. | 
|    최소 업로드 파트 크기  |  <pre>tmBuilder.withMinimumUploadPartSize(...);<br />tmBuilder.setMinimumUploadPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      minimumPartSizeInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    멀티파트 업로드 임계값  |  <pre>tmBuilder.withMultipartUploadThreshold(...);<br />tmBuilder.setMultipartUploadThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      thresholdInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    최소 복사 파트 크기  |  <pre>tmBuilder.withMultipartCopyPartSize(...);<br />tmBuilder.setMultipartCopyPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      minimumPartSizeInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    멀티파트 복사 임계값  |  <pre>tmBuilder.withMultipartCopyThreshold(...);<br />tmBuilder.setMultipartCopyThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.crtBuilder().<br />      thresholdInBytes(...).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    병렬 다운로드 비활성화  |  <pre>tmBuilder.withDisableParallelDownloads(...);<br />tmBuilder.setDisableParallelDownloads(...);</pre>  | 멀티파트 비활성화(기본값)으로 설정된 표준 Java 기반 S3 클라이언트를 Transfer Manager에 전달하여 병렬 다운로드를 비활성화합니다.<pre>S3AsyncClient s3 =<br />   S3AsyncClient.builder().build();<br /><br />tmBuilder.s3Client(s3);</pre> | 
|    항상 멀티파트 md5를 계산하세요.  |  <pre>tmBuilder.withAlwaysCalculateMultipartMd5(...);<br />tmBuilder.setAlwaysCalculateMultipartMd5(...);</pre>  | 지원되지 않음. | 

------
#### [ Use Java-based S3 async client ]


****  

| 설정 | v1 | v2 - Java 기반 S3 비동기식 클라이언트를 사용하는 Transfer Manager | 
| --- | --- | --- | 
|    (빌더 구하기)  |  <pre>TransferManagerBuilder tmBuilder = <br />   TransferManagerBuilder.standard();</pre>  |  <pre>S3TransferManager.Builder tmBuilder  = <br />  S3TransferManager.builder();</pre>  | 
|    S3 클라이언트  |  <pre>tmBuilder.withS3Client(...);<br />tmBuilder.setS3Client(...);</pre>  |  <pre>tmBuilder.s3Client(...);</pre>  | 
|    실행자  |  <pre>tmBuilder.withExecutorFactory(...);<br />tmBuilder.setExecutorFactory(...);</pre>  |  <pre>tmBuilder.executor(...);</pre>  | 
|    스레드 풀 종료  |  <pre>tmBuilder.withShutDownThreadPools(...);<br />tmBuilder.setShutdownThreadPools(...);</pre>  | 지원되지 않음. 제공된 실행기는 S3TransferManager가 닫힐 때 종료되지 않습니다. | 
|    최소 업로드 파트 크기  |  <pre>tmBuilder.withMinimumUploadPartSize(...);<br />tmBuilder.setMinimumUploadPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.minimumPartSizeInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    멀티파트 업로드 임계값  |  <pre>tmBuilder.withMultipartUploadThreshold(...);<br />tmBuilder.setMultipartUploadThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.thresholdInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    최소 복사 파트 크기  |  <pre>tmBuilder.withMultipartCopyPartSize(...);<br />tmBuilder.setMultipartCopyPartSize(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.minimumPartSizeInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    멀티파트 복사 임계값  |  <pre>tmBuilder.withMultipartCopyThreshold(...);<br />tmBuilder.setMultipartCopyThreshold(...);</pre>  |  <pre>S3AsyncClient s3 = S3AsyncClient.builder()<br />    .multipartConfiguration(cfg -><br />        cfg.thresholdInBytes(...)).build();<br /><br />tmBuilder.s3Client(s3);</pre>  | 
|    병렬 다운로드 비활성화  |  <pre>tmBuilder.withDisableParallelDownloads(...);<br />tmBuilder.setDisableParallelDownloads(...);</pre>  | 멀티파트 비활성화(기본값)으로 설정된 표준 Java 기반 S3 클라이언트를 Transfer Manager에 전달하여 병렬 다운로드를 비활성화합니다.<pre>S3AsyncClient s3 =<br />   S3AsyncClient.builder().build();<br /><br />tmBuilder.s3Client(s3);</pre> | 
|    항상 멀티파트 md5를 계산하세요.  |  <pre>tmBuilder.withAlwaysCalculateMultipartMd5(...);<br />tmBuilder.setAlwaysCalculateMultipartMd5(...);</pre>  | 지원되지 않음. | 

------

## 동작 변경 사항
<a name="s3-tm-migration-behavior-changes"></a>

### 비동기식 운영
<a name="s3-tm-migration-async-operations"></a>

**V1(차단):**

```
Upload upload = transferManager.upload("amzn-s3-demo-bucket", "key", file);
upload.waitForCompletion(); // Blocks until complete
```

**V2(비동기식):**

```
FileUpload upload = transferManager.uploadFile(UploadFileRequest.builder()
    .putObjectRequest(PutObjectRequest.builder()
        .bucket("amzn-s3-demo-bucket")
        .key("key")
        .build())
    .source(file)
    .build());

CompletedFileUpload result = upload.completionFuture().join(); // Blocks until complete
// Or handle asynchronously:
upload.completionFuture().thenAccept(result -> {
    System.out.println("Upload completed: " + result.response().eTag());
});
```

### 오류 처리
<a name="s3-tm-migration-error-handling"></a>

**V1:** 하위 요청이 실패하면 디렉터리 전송이 완전히 실패합니다.

**V2:** 일부 하위 요청이 실패하더라도 디렉터리 전송이 성공적으로 완료됩니다. 다음과 같이 오류를 명시적으로 확인합니다.

```
DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
CompletedDirectoryUpload result = directoryUpload.completionFuture().join();

// Check for failed transfers
if (!result.failedTransfers().isEmpty()) {
    System.out.println("Some uploads failed:");
    result.failedTransfers().forEach(failed -> 
        System.out.println("Failed: " + failed.exception().getMessage()));
}
```

### 바이트 범위 페치를 통한 병렬 다운로드
<a name="migration-transfer-manager-behavior-fetches"></a>

v2 SDK에서 자동 병렬 전송 기능이 활성화되면 S3 Transfer Manager v2는 [바이트 범위 가져오기](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range)를 사용하여 객체의 특정 부분을 병렬로 검색(멀티파트 다운로드)합니다. v2를 사용하여 객체를 다운로드하는 방법은 객체가 처음 업로드된 방식에 따라 달라지지 않습니다. 모든 다운로드는 높은 처리량과 동시성의 이점을 누릴 수 있습니다.

이와 대조적으로 v1의 S3 Transfer Manager에서는 객체가 원래 업로드된 방식이 중요합니다. v1 Transfer Manager는 일부가 업로드된 것과 동일한 방식으로 객체의 일부를 검색합니다. 객체가 원래 단일 객체로 업로드된 경우 v1 Transfer Manager는 하위 요청을 사용하여 다운로드 프로세스를 가속화할 수 없습니다.

# 버전 1에서 버전 2로 Amazon S3 URI 구문 분석에 관한 변경 사항
<a name="migration-s3-uri-parser"></a>

이 주제에서는 버전 1(v1)에서 버전 2(v2)로의 Amazon S3 URI 구문 분석의 변경 사항에 대해 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-3-uri-parser-api-changes"></a>

v1에서 S3 URI 구문 분석을 시작하려면 생성자를 사용하여 `AmazonS3URI`를 인스턴스화합니다. v2에서는 `S3Utilities`의 인스턴스에서 `parseUri()`를 직접적으로 호출하여 `S3URI`를 반환합니다.


****  

| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.5871</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency>  <br />        <groupId>com.amazonaws</groupId><br />        <artifactId>s3</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.27.212</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.services.s3 | software.amazon.awssdk.services.s3 | 
| 클래스 이름 | [AmazonS3URI](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3URI.html) | [S3URI](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Uri.html) | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## API 변경 사항
<a name="migration-3-uri-parser-api-changes"></a>


| 동작 | v1 |  v2 | 
| --- | --- | --- | 
| S3 URI를 구문 분석합니다. |  <pre>URI uri = URI.create( "https://s3.amazonaws.com");<br /><br />AmazonS3Uri s3Uri = <br />    new AmazonS3URI(uri, false);</pre>  |  <pre>S3Client s3Client = S3Client.create();<br />S3Utilities s3Utilities =<br />    s3Client.utilities();<br /><br />S3Uri s3Uri =<br />    s3Utilities.parseUri(uri);</pre>  | 
| S3 버킷에서 버킷 이름을 검색합니다. |  <pre>String bucket = s3Uri.getBucket();</pre>  |  <pre>Optional<String> bucket = s3Uri.bucket();</pre>  | 
| 키를 검색합니다. |  <pre>String key = s3Uri.getKey();</pre>  |  <pre>Optional<String> key = s3Uri.key();</pre>  | 
| 리전을 검색합니다. |  <pre>String region = s3Uri.getRegion();</pre>  |  <pre>Optional<Region> region = s3Uri.region();<br /><br />String region;<br />if (s3Uri.region().isPresent()) {<br />    region = s3Uri.region().get().id();<br />}</pre>  | 
|  S3 URI가 경로형인지 검색합니다.  |  <pre>boolean isPathStyle = s3Uri.isPathStyle();</pre>  |  <pre>boolean isPathStyle = s3Uri.isPathStyle();</pre>  | 
| 버전 ID를 검색합니다. |  <pre>String versionId = s3Uri.getVersionId();</pre>  |  <pre>Optional<String> versionId = <br />    s3Uri.firstMatchingRawQueryParameter("versionId");</pre>  | 
| 쿼리 파라미터를 검색합니다. | 해당 사항 없음 |  <pre>Map<String, List<String>> queryParams =<br />    s3Uri.rawQueryParameters();</pre>  | 

### 동작 변경 사항
<a name="migration-s3-uri-parser-behavior-changes"></a>

#### URL 인코딩
<a name="migration-s3-uri-parser-behavior-changes-URLencoding"></a>

v1은 플래그를 전달하여 URI를 URL로 인코딩할지 여부를 지정하는 옵션을 제공합니다. 기본값은 `true`입니다.

v2에서는 URL 인코딩이 지원되지 않습니다. 예약되었거나 안전하지 않은 문자가 있는 객체 키 또는 쿼리 파라미터로 작업하는 경우 URL 인코딩해야 합니다. 예를 들어 공백(`" "`)을 `%20`으로 바꿔야 합니다.

# S3 이벤트 알림 API를 버전 1에서 버전 2로 변경
<a name="migration-s3-event-notification"></a>

이 주제에서는 S3 이벤트 알림 API를 AWS SDK for Java의 버전 1.x(v1)에서 버전 2 .x(v2)로 변경에 대해 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-s3-event-notification-hl"></a>

### 구문 변경 사항
<a name="migration-s3-event-notification-hl-struct"></a>

V1은 `EventNotificationRecord` 유형 및 속성에 정적 내부 클래스를 사용하는 반면, v2는 `EventNotificationRecord` 유형에 대해 별도의 퍼블릭 클래스를 사용합니다.

### 이름 지정 규칙 변경 사항
<a name="migration-s3-event-notification-hl-naming"></a>

V1에서 속성 클래스 이름에는 접미사 *엔터티*가 포함되는 반면, V2에서는 보다 간단한 이름 지정을 위해 이 접미사를 생략합니다. 예를 들어 *eventDataEntity*가 아닌 *eventData*입니다.

## 종속성, 패키지 및 클래스 이름의 변경 사항
<a name="migration-s3-event-notification-deps"></a>

V1에서 S3 이벤트 알림 API 클래스는 S3 모듈(artifactId `aws-java-sdk-s3`)과 함께 사용하여 전이적으로 가져옵니다. 그러나 V2에서는 `s3-event-notifications` 아티팩트에 대한 종속성을 추가해야 합니다.


****  

| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-java-sdk-s3</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X1</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3-event-notifications</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.services.s3.event | software.amazon.awssdk.eventnotifications.s3.model | 
| 클래스 이름 |  [S3EventNotification](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.html) [S3EventNotification.S3EventNotificationRecord](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.S3EventNotificationRecord.html) [S3EventNotification.GlacierEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.GlacierEventDataEntity.html) [S3EventNotification.IntelligentTieringEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.IntelligentTieringEventDataEntity.html) [S3EventNotification.LifecycleEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.LifecycleEventDataEntity.html) [S3EventNotification.ReplicationEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.ReplicationEventDataEntity.html) [S3EventNotification.RequestParametersEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.RequestParametersEntity.html) [S3EventNotification.ResponseElementsEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.ResponseElementsEntity.html) [S3EventNotification.RestoreEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.RestoreEventDataEntity.html) [S3EventNotification.S3BucketEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.S3BucketEntity.html) [S3EventNotification.S3Entity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.S3Entity.html) [S3EventNotification.S3ObjectEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.S3ObjectEntity.html) [S3EventNotification.TransitionEventDataEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.TransitionEventDataEntity.html) [S3EventNotification.UserIdentityEntity](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/event/S3EventNotification.UserIdentityEntity.html)  |   [S3EventNotification](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotification.html) [S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html) [GlacierEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/GlacierEventData.html) [IntelligentTieringEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/IntelligentTieringEventData.html) [LifecycleEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/LifecycleEventData.html) [ReplicationEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/ReplicationEventData.html) [RequestParameters](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/RequestParameters.html) [ResponseElements](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/ResponseElements.html) [RestoreEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/RestoreEventData.html) [S3Bucket](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3Bucket.html) [S3](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3.html) [S3Object](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3Object.html) [TransitionEventData](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/TransitionEventData.html) [UserIdentity](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/UserIdentity.html)  | 

1 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## API 변경 사항
<a name="migration-s3-event-notification-API-changes"></a>

### `S3EventNotification`에 대한 JSON 및 역방향
<a name="migration-s3-event-notification-API-changes-conv"></a>


| 사용 사례: | v1 |  v2 | 
| --- | --- | --- | 
| JSON 문자열에서 S3EventNotification 만들기 |  <pre>S3EventNotification notification = <br />        S3EventNotification.parseJson(message.body());</pre>  |  <pre>S3EventNotification notification = <br />        S3EventNotification.fromJson(message.body());</pre>  | 
| JSON 문자열로 S3EventNotification 변환 |  <pre>String json = notification.toJson();</pre>  |  <pre>String json = notification.toJson();</pre>  | 

### `S3EventNotification`의 액세스 속성
<a name="migration-s3-event-notification-API-changes-attr"></a>


| 사용 사례: | v1 |  v2 | 
| --- | --- | --- | 
| 알림에서 레코드 검색 |  <pre>List<S3EventNotification.S3EventNotificationRecord> records = <br />        notifcation.getRecords();</pre>  |  <pre>List<S3EventNotificationRecord> records = <br />        notification.getRecords();</pre>  | 
| 레코드 목록에서 레코드 검색 |  <pre>S3EventNotification.S3EventNotificationRecord record = <br />        records.stream().findAny().get();</pre>  |  <pre>S3EventNotificationRecord record = <br />        records.stream().findAny().get();</pre>  | 
| Glacier 이벤트 데이터 검색 |  <pre>S3EventNotification.GlacierEventDataEntity glacierEventData =<br />        record.getGlacierEventData();</pre>  |  <pre>GlacierEventData glacierEventData = <br />        record.getGlacierEventData();</pre>  | 
| Glacier 이벤트에서 복원 이벤트 데이터 검색 |  <pre>S3EventNotification.RestoreEventDataEntity restoreEventData = <br />        glacierEventData.getRestoreEventDataEntity();</pre>  |  <pre>RestoreEventData restoreEventData = <br />        glacierEventData.getRestoreEventData();</pre>  | 
| 요청 파라미터 검색 |  <pre>S3EventNotification.RequestParametersEntity requestParameters = <br />        record.getRequestParameters();</pre>  |  <pre>RequestParameters requestParameters = <br />        record.getRequestParameters();</pre>  | 
| 지능형 계층화 이벤트 데이터 검색 |  <pre>S3EventNotification.IntelligentTieringEventDataEntity tieringEventData = <br />        record.getIntelligentTieringEventData();</pre>  |  <pre>IntelligentTieringEventData intelligentTieringEventData = <br />        record.getIntelligentTieringEventData();</pre>  | 
| 수명 주기 이벤트 데이터 검색 |  <pre>S3EventNotification.LifecycleEventDataEntity lifecycleEventData = <br />        record.getLifecycleEventData();</pre>  |  <pre>LifecycleEventData lifecycleEventData = <br />        record.getLifecycleEventData();</pre>  | 
| 이벤트 이름을 열거형으로 검색 |  <pre>S3Event eventNameAsEnum = record.getEventNameAsEnum();</pre>  |  <pre>//getEventNameAsEnum does not exist; use 'getEventName()'<br />String eventName = record.getEventName();</pre>  | 
| 복제 이벤트 데이터 검색 |  <pre>S3EventNotification.ReplicationEventDataEntity replicationEntity = <br />        record.getReplicationEventDataEntity();</pre>  |  <pre>ReplicationEventData replicationEventData = <br />        record.getReplicationEventData();</pre>  | 
| S3 버킷 및 객체 정보 검색 |  <pre>S3EventNotification.S3Entity s3 = record.getS3();</pre>  |  <pre>S3 s3 = record.getS3();</pre>  | 
| 사용자 자격 증명 정보 검색 |  <pre>S3EventNotification.UserIdentityEntity userIdentity = <br />        record.getUserIdentity();</pre>  |  <pre>UserIdentity userIdentity = <br />        record.getUserIdentity();</pre>  | 
| 응답 요소 검색 |  <pre>S3EventNotification.ResponseElementsEntity responseElements = <br />        record.getResponseElements();</pre>  |  <pre>ResponseElements responseElements = <br />        record.getResponseElements();</pre>  | 

## `aws-lambda-java-events` 라이브러리 버전 마이그레이션
<a name="migration-s3-events-notification-lambda-lib"></a>

[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)를 사용하여 Lambda 함수 내에서 S3 알림 이벤트를 사용하는 경우 최신 3.x.x 버전으로 업그레이드하는 것이 좋습니다. 최신 버전은 S3 이벤트 알림 API에서 AWS SDK for Java 1.x의 모든 종속성을 제거합니다.

`aws-lambda-java-events` 라이브러리와 SDK for Java 2.x 간의 S3 이벤트 알림 처리 차이점에 대한 자세한 내용은 [Java 라이브러리를 사용하여 Lambda에서 S3 이벤트 처리: AWS SDK for Java 2.x 및 `aws-lambda-java-events`](examples-s3-event-notifications.md#s3-event-notif-processing-options) 섹션을 참조하세요.

# 프로필 파일 변경 사항
<a name="migration-profile-file"></a>

AWS SDK for Java 2.x는 `~/.aws/config` 및 `~/.aws/credentials`에서 프로필 정의를 구문 분석하여 AWS CLI가 파일을 구문 분석하는 방법을 더 자세히 에뮬레이션합니다.

SDK for Java 2.x:
+ `$HOME`, `$USERPROFILE`(Windows만 해당), `$HOMEDRIVE`, `$HOMEPATH`(Windows만 해당) 및 `user.home` 시스템 속성을 순서대로 확인하여 경로 시작 시 파일 시스템의 기본 경로 구분자가 뒤따르는 `~/` 또는 `~` 코드를 해결합니다.
+ `AWS_CREDENTIAL_PROFILES_FILE` 대신 `AWS_SHARED_CREDENTIALS_FILE` 환경 변수를 찾습니다.
+ 프로필 이름의 시작 부분에 `profile` 단어 없이 구성 파일의 프로필 정의를 자동으로 삭제합니다.
+ 영숫자, 밑줄 또는 대시 문자로 구성되지 않은 프로필 정의를 자동으로 삭제합니다(구성 파일에 대해 선행 `profile` 단어를 제거한 후).
+ 동일한 파일 내에 복제된 프로필 정의의 설정을 병합합니다.
+ 구성 파일과 자격 증명 파일 모두에 중복된 프로필 정의의 설정을 병합합니다.
+ 동일한 파일에서 `[profile foo]` 및 `[foo]`가 모두 발견되면 설정을 병합하지 않습니다.
+ 구성 파일에서 `[profile foo]` 및 `[foo]`를 모두 찾을 경우 `[profile foo]`의 설정을 사용합니다.
+ 동일한 파일 및 프로필에서 마지막으로 복제된 설정의 값을 사용합니다.
+ 주석을 정의하기 위해 `;` 및 `#` 기호를 모두 인식합니다.
+ 문자가 닫는 대괄호 옆에 있더라도 프로필 정의에서 `;` 및 `#` 기호를 인식하여 주석을 정의합니다.
+ 설정 값 앞에 공백이 있는 경우에만 주석을 정의하기 위해 `;` 및 `#` 기호를 인식합니다.
+ 앞에 공백이 없는 경우 설정 값에서 `;` 및 `#`, 다음 모든 콘텐츠를 인식합니다.
+ 역할 기반 자격 증명을 우선순위가 가장 높은 자격 증명으로 간주합니다. 사용자가 `role_arn` 속성을 지정하는 경우 2.x SDK는 항상 역할 기반 자격 증명을 사용합니다.
+ 세션 기반 자격 증명을 차순위 자격 증명으로 간주합니다. 역할 기반 자격 증명을 사용하지 않고 사용자가 `aws_access_key_id` 및 `aws_session_token` 속성을 지정하는 경우 2.x SDK는 항상 세션 기반 자격 증명을 사용합니다.
+ 역할 기반 및 세션 기반 자격 증명을 사용하지 않고 사용자가 `aws_access_key_id` 속성을 지정한 경우 기본 자격 증명을 사용합니다.

# 환경 변수 및 시스템 속성 변경
<a name="migration-env-and-system-props"></a>


| 1.x 환경 변수 | 1.x 시스템 속성 | 2.x 환경 변수 | 2.x 시스템 속성 | 
| --- | --- | --- | --- | 
| AWS\$1ACCESS\$1KEY\$1IDAWS\$1ACCESS\$1KEY | aws.accessKeyId | AWS\$1ACCESS\$1KEY\$1ID | aws.accessKeyId | 
| AWS\$1SECRET\$1KEYAWS\$1SECRET\$1ACCESS\$1KEY | aws.secretKey | AWS\$1SECRET\$1ACCESS\$1KEY | aws.secretAccessKey | 
| AWS\$1SESSION\$1TOKEN | aws.sessionToken | AWS\$1SESSION\$1TOKEN | aws.sessionToken | 
| AWS\$1REGION | aws.region | AWS\$1REGION | aws.region | 
| AWS\$1CONFIG\$1FILE |   | AWS\$1CONFIG\$1FILE | aws.configFile | 
| AWS\$1CREDENTIAL\$1PROFILES\$1FILE |   | AWS\$1SHARED\$1CREDENTIALS\$1FILE | aws.sharedCredentialsFile | 
| AWS\$1PROFILE | aws.profile | AWS\$1PROFILE | aws.profile | 
| AWS\$1EC2\$1METADATA\$1DISABLED | com.amazonaws.sdk.disableEc2Metadata | AWS\$1EC2\$1METADATA\$1DISABLED | aws.disableEc2Metadata | 
|   | com.amazonaws.sdk.ec2MetadataServiceEndpointOverride | AWS\$1EC2\$1METADATA\$1SERVICE\$1ENDPOINT | aws.ec2MetadataServiceEndpoint | 
| AWS\$1CONTAINER\$1CREDENTIALS\$1RELATIVE\$1URI |   | AWS\$1CONTAINER\$1CREDENTIALS\$1RELATIVE\$1URI | aws.containerCredentialsPath | 
| AWS\$1CONTAINER\$1CREDENTIALS\$1FULL\$1URI |   | AWS\$1CONTAINER\$1CREDENTIALS\$1FULL\$1URI | aws.containerCredentialsFullUri | 
| AWS\$1CONTAINER\$1AUTHORIZATION\$1TOKEN |   | AWS\$1CONTAINER\$1AUTHORIZATION\$1TOKEN | aws.containerAuthorizationToken | 
| AWS\$1CBOR\$1DISABLED | com.amazonaws.sdk.disableCbor | CBOR\$1ENABLED | aws.cborEnabled | 
| AWS\$1ION\$1BINARY\$1DISABLE | com.amazonaws.sdk.disableIonBinary | BINARY\$1ION\$1ENABLED | aws.binaryIonEnabled | 
| AWS\$1EXECUTION\$1ENV |   | AWS\$1EXECUTION\$1ENV | aws.executionEnvironment | 
|   | com.amazonaws.sdk.disableCertChecking | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|   | com.amazonaws.sdk.enableDefaultMetrics | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/23) | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/23) | 
|   | com.amazonaws.sdk.enableThrottledRetry | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/645) | [지원되지 않음](https://github.com/aws/aws-sdk-java-v2/issues/645) | 
|   | com.amazonaws.regions.RegionUtils.fileOverride | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|   | com.amazonaws.regions.RegionUtils.disableRemote | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|   | com.amazonaws.services.s3.disableImplicitGlobalClients | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 
|   | com.amazonaws.sdk.enableInRegionOptimizedMode | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 비지원([요청 기능](https://github.com/aws/aws-sdk-java-v2/issues/new)) | 

# 웨이터를 버전 1에서 버전 2로 변경
<a name="migration-waiters"></a>

이 주제에서는 버전 1(v1)에서 버전 2(v2)로 변환 시 웨이터 기능의 변경 사항을 자세히 설명합니다.

다음 표에서는 DynamoDB 웨이터의 차이점을 구체적으로 보여줍니다. 다른 서비스의 웨이터는 동일한 패턴을 따릅니다.

## 높은 수준의 변경 사항
<a name="migration-waiters-api-changes"></a>

웨이터 클래스는 서비스와 동일한 Maven 아티팩트에 있습니다.


| 변경 사항 | v1 | v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.6801</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>dynamodb</artifactId><br />    </dependency><br /></dependencies><br /></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.27.102</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>dynamodb</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.services.dynamodbv2.waiters | software.amazon.awssdk.services.dynamodb.waiters | 
| 클래스 이름 |  `[AmazonDynamoDBWaiters](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/waiters/AmazonDynamoDBWaiters.html)`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-waiters.html)  | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## API 변경 사항
<a name="migration-cf-presign-behavior-changes"></a>


| 변경 사항 | v1 | v2 | 
| --- | --- | --- | 
| 웨이터 만들기 |  <pre>AmazonDynamoDB client = AmazonDynamoDBClientBuilder <br />                            .standard().build();<br />AmazonDynamoDBWaiters waiter = client.waiters();</pre>  | 동기식:<pre>DynamoDbClient client = DynamoDbClient.create();<br />DynamoDbWaiter waiter = client.waiter();</pre>비동기식:<pre>DynamoDbAsyncClient asyncClient = <br />        DynamoDbAsyncClient.create();<br />DynamoDbAsyncWaiter waiter = asyncClient.waiter();</pre> | 
| 테이블이 존재할 때까지 대기 | 동기식:<pre>waiter.tableExists()<br />    .run(new WaiterParameters<>(<br />        new DescribeTableRequest(tableName)));</pre>비동기식:<pre>waiter.tableExists()<br />    .runAsync(new WaiterParameters()<br />      .withRequest(new DescribeTableRequest(tableName)),<br />          new WaiterHandler() {<br />              @Override<br />              public void onWaitSuccess(<br />                  AmazonWebServiceRequest amazonWebServiceRequest) {<br />                    System.out.println("Table creation succeeded");<br />              }<br /><br />              @Override<br />              public void onWaitFailure(Exception e) {<br />                  e.printStackTrace();<br />              }<br />          }).get();</pre> |  동기식: <pre>WaiterResponse<DescribeTableResponse> waiterResponse =<br />    waiter.waitUntilTableExists(<br />        r -> r.tableName("myTable"));<br />waiterResponse.matched().response()<br />       .ifPresent(System.out::println);</pre> 비동기식: <pre>waiter.waitUntilTableExists(r -> r.tableName(tableName))<br />           .whenComplete((r, t) -> {<br />               if (t != null) {<br />                   t.printStackTrace();<br />               } else {<br />                   System.out.println(<br />                        "Table creation succeeded");<br />               }<br />           }).join();</pre>  | 

## 구성 변경
<a name="migration-waiters-config"></a>


| 변경 사항 | v1 | v2 | 
| --- | --- | --- | 
| 폴링 전략(최대 시도 횟수 및 고정 지연) |  <pre>MaxAttemptsRetryStrategy maxAttemptsRetryStrategy = <br />        new MaxAttemptsRetryStrategy(10);<br /><br />FixedDelayStrategy fixedDelayStrategy = <br />        new FixedDelayStrategy(3);<br /><br />PollingStrategy pollingStrategy = <br />        new PollingStrategy(maxAttemptsRetryStrategy, <br />                fixedDelayStrategy);<br /><br />waiter.tableExists().run(<br />        new WaiterParameters<>(<br />            new DescribeTableRequest(tableName)), <br />                pollingStrategy);</pre>  |  <pre><br />FixedDelayBackoffStrategy fixedDelayBackoffStrategy = <br />        FixedDelayBackoffStrategy<br />            .create(Duration.ofSeconds(3));<br /><br />waiter.waitUntilTableExists(r -> r.tableName(tableName),<br />        c -> c.maxAttempts(10)<br />                .backoffStrategy(fixedDelayBackoffStrategy));</pre>  | 

# EC2 메타데이터 유틸리티가 버전 1에서 버전 2로 변경
<a name="migration-imds"></a>

이 항목에서는 버전 1(v1)에서 버전 2(v2)로 변경된 SDK for Java Amazon Elastic Compute Cloud(EC2) 메타데이터 유틸리티의 변경 사항에 대해 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-imds-high-level-changes"></a>


****  

| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.5871</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-java-sdk-core</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.27.212</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>imds</artifactId><br />    </dependency><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>apache-client3</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 |  com.amazonaws.util  |  software.amazon.awssdk.imds  | 
| 인스턴스화 접근 방식 |  인스턴스화 없이 정적 유틸리티 메서드 사용: <pre>String localHostName = <br />           EC2MetadataUtils.getLocalHostName();</pre>  |  정적 팩토리 메서드 사용: <pre>Ec2MetadataClient client = Ec2MetadataClient.create();</pre> 또는 빌더 접근 방식 사용: <pre>Ec2MetadataClient client = Ec2MetadataClient.builder()<br />    .endpointMode(EndpointMode.IPV6)<br />    .build();</pre>  | 
| 클라이언트 유형 | 동기 전용 유틸리티 메서드: EC2MetadataUtils |  동기식: `Ec2MetadataClient` 비동기식: `Ec2MetadataAsyncClient`  | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

3v2에 대한 `apache-client` 모듈 선언에 주목합니다. EC2 메타데이터 유틸리티 V2를 사용하려면 동기식 메타데이터 클라이언트의 경우 `SdkHttpClient` 인터페이스를 구현해야 하고, 비동기식 메타데이터 클라이언트의 경우 `SdkAsyncHttpClient` 인터페이스를 구현해야 합니다. [에서 HTTP 클라이언트 구성 AWS SDK for Java 2.x](http-configuration.md) 섹션에는 사용할 수 있는 HTTP 클라이언트 목록이 표시됩니다.

### 메타데이터 요청
<a name="migration-imds-fetching-changes"></a>

v1에서는 파라미터를 허용하지 않는 정적 메서드를 사용하여 EC2 리소스에 대한 메타데이터를 요청합니다. 이와는 대조적으로 v2에서는 EC2 리소스의 경로를 파라미터로 지정해야 합니다. 다음 표는 서로 다른 접근 방식을 보여줍니다.


****  

| v1 |  v2 | 
| --- | --- | 
|  <pre>String userMetaData = EC2MetadataUtils.getUserData();</pre>  |  <pre>Ec2MetadataClient client = Ec2MetadataClient.create();<br />Ec2MetadataResponse response = <br />                client.get("/latest/user-data");<br />String userMetaData = <br />                response.asString();</pre>  | 

[인스턴스 메타데이터 범주](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/instancedata-data-categories.html)를 참조하여 메타데이터를 요청하기 위해 제공해야 하는 경로를 찾으세요.

**참고**  
v2에서 인스턴스 메타데이터 클라이언트를 사용하는 경우, 메타데이터를 검색하는 모든 요청에 동일한 클라이언트를 사용해야 합니다.

 

## 동작 변경 사항
<a name="migration-imds-behavior-changes"></a>

### JSON 데이터
<a name="migration-imds-behavior-json"></a>

EC2에서 로컬로 실행되는 인스턴스 메타데이터 서비스(IMDS)는 일부 메타데이터를 JSON 형식의 문자열로 반환합니다. 그러한 예로 [인스턴스 ID 문서](https://docs.aws.amazon.com//AWSEC2/latest/UserGuide/instance-identity-documents.html)의 동적 메타데이터를 들 수 있습니다.

v1 API에는 인스턴스 ID 메타데이터의 각 부분에 대한 별도의 메서드가 포함되어 있는 반면, v2 API는 JSON 문자열을 직접 반환합니다. JSON 문자열로 작업하려면 [문서 API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/document/package-summary.html)를 사용하여 응답을 구문 분석하고 JSON 구조를 탐색할 수 있습니다.

다음 표는 v1과 v2에서 인스턴스 ID 문서의 메타데이터를 검색하는 방법을 비교한 것입니다.


****  

| 사용 사례: | v1 |  v2 | 
| --- | --- | --- | 
| 리전 검색 |  <pre>InstanceInfo instanceInfo = <br />        EC2MetadataUtils.getInstanceInfo();<br />String region = instanceInfo.getRegion();</pre>  |  <pre>Ec2MetadataResponse response = <br />    client.get("/latest/dynamic/instance-identity/document");<br />Document instanceInfo = response.asDocument();<br />String region = instanceInfo.asMap().get("region").asString();</pre>  | 
| 인스턴스 ID 검색 |  <pre>InstanceInfo instanceInfo = <br />        EC2MetadataUtils.getInstanceInfo();<br />String instanceId = instanceInfo.instanceId;</pre>  |  <pre>Ec2MetadataResponse response = <br />    client.get("/latest/dynamic/instance-identity/document");<br />Document instanceInfo = response.asDocument();<br />String instanceId = instanceInfo.asMap().get("instanceId").asString();</pre>  | 
| 인스턴스 유형 검색 |  <pre>InstanceInfo instanceInfo = <br />        EC2MetadataUtils.getInstanceInfo();<br />String instanceType = instanceInfo.instanceType();</pre>  |  <pre>Ec2MetadataResponse response = <br />    client.get("/latest/dynamic/instance-identity/document");<br />Document instanceInfo = response.asDocument();<br />String instanceType = instanceInfo.asMap().get("instanceType").asString();</pre>  | 

### 엔드포인트 해상도 차이
<a name="migration-imds-behavior-endpoint-res"></a>

다음 표는 SDK가 엔드포인트를 IMDS로 확인하기 위해 확인하는 위치를 보여줍니다. 위치는 내림차순으로 나열됩니다.


****  

| v1 |  v2 | 
| --- | --- | 
| 시스템 속성: com.amazonaws.sdk.ec2MetadataServiceEndpointOverride | 클라이언트 빌더 구성 메서드: endpoint(...) | 
| 환경 변수: AWS\$1EC2\$1METADATA\$1SERVICE\$1ENDPOINT | 시스템 속성: aws.ec2MetadataServiceEndpoint | 
| 기본 값: http://169.254.169.254 | 구성 파일: ec2\$1metadata\$1service\$1endpoint 설정이 포함된 \$1.aws/config | 
|  | 확인된 endpoint-mode 관련된 값  | 
|  | 기본값: http://169.254.169.254 | 

### v2의 엔드포인트 해상도
<a name="migration-imds-behavior-endpoint-res2"></a>

빌더를 사용하여 엔드포인트를 명시적으로 설정하면 해당 엔드포인트 값이 다른 모든 설정보다 우선합니다. 다음 코드가 실행될 때 `aws.ec2MetadataServiceEndpoint` 시스템 속성 및 구성 파일 `ec2_metadata_service_endpoint` 설정이 있는 경우 무시됩니다.

```
Ec2MetadataClient client = Ec2MetadataClient
  .builder()
  .endpoint(URI.create("endpoint.to.use"))
  .build();
```

#### 엔드포인트 모드
<a name="migration-imds-behavior-endpoint-mode"></a>

v2에서는 엔드포인트 모드를 지정하여 IPv4 또는 IPv6의 기본 엔드포인트 값을 사용하도록 메타데이터 클라이언트를 구성할 수 있습니다. v1에는 엔드포인트 모드를 사용할 수 없습니다. IPv4에 사용되는 기본값은 `http://169.254.169.254`, IPv6의 경우 `http://[fd00:ec2::254]`입니다.

다음 표는 우선 순위가 내려가는 순서대로 엔드포인트 모드를 설정할 수 있는 다양한 방법을 보여줍니다.


****  

|  |  | 가능한 값 | 
| --- | --- | --- | 
| 클라이언트 빌더 구성 메서드: endpointMode(...) |  <pre>Ec2MetadataClient client = Ec2MetadataClient<br />  .builder()<br />  .endpointMode(EndpointMode.IPV4)<br />  .build();</pre>  | EndpointMode.IPV4, EndpointMode.IPV6 | 
| 시스템 속성 | aws.ec2MetadataServiceEndpointMode | IPv4, IPv6(대/소문자를 구분하지 않음) | 
| Config 파일: \$1.aws/config | ec2\$1metadata\$1service\$1endpoint 설정 | IPv4, IPv6(대/소문자를 구분하지 않음) | 
| 이전 방법으로는 지정되지 않음 | IPv4가 사용됨 |  | 

#### SDK가 v2에서 `endpoint` 또는 `endpoint-mode`를 확인하는 방법
<a name="migration-imds-behavior-endpoint-res2-which"></a>

1. SDK는 클라이언트 빌더의 코드에서 설정한 값을 사용하며 외부 설정은 무시합니다. 클라이언트 빌더에서 `endpoint`와 `endpointMode`가 모두 호출되면 SDK는 예외를 던지므로, 어떤 메서드를 사용하든 엔드포인트 값을 사용합니다.

1. 코드에서 값을 설정하지 않으면 SDK는 외부 구성에서 먼저 시스템 속성을 찾은 다음 구성 파일의 설정을 찾습니다.

   1. SDK는 먼저 엔드포인트 값을 확인합니다. 값이 발견되면 해당 값이 사용됩니다.

   1. 여전히 값을 찾지 못한 경우 SDK는 엔드포인트 모드 설정을 찾습니다.

1. 마지막으로, SDK가 외부 설정을 찾지 못하고 코드에서 메타데이터 클라이언트를 구성하지 않은 경우 SDK는 `http://169.254.169.254`의 IPv4 값을 사용합니다.

### IMDSv2
<a name="migration-imds-behavior-imdsv2"></a>

Amazon EC2는 인스턴스 메타데이터에 액세스하는 두 가지 접근 방식을 정의합니다.
+ 인스턴스 메타데이터 서비스 버전 1(IMDSv1) - 요청/응답 방식
+ 인스턴스 메타데이터 서비스 버전 2(IMDSv2) - 세션 지향 방식

다음 표는 Java SDK와 IMDS의 작동 방식을 비교한 것입니다.


****  

| v1 |  v2 | 
| --- | --- | 
| IMDSv2가 기본적으로 사용됨 | 항상 IMDSv2를 사용함 | 
| 각 요청에 대해 세션 토큰을 가져오려고 시도하고 세션 토큰을 가져오지 못하면 IMDSv1으로 돌아갑니다. | 여러 요청에 재사용되는 세션 토큰을 내부 캐시에 보관합니다. | 

SDK for Java 2.x는 IMDSv2만 지원하며 IMDSv1로 돌아가지 않습니다.

## 구성 차이점
<a name="migration-imds-config-diffs"></a>

다음 표에는 다양한 구성 옵션이 나와 있습니다.


****  

| 구성 | v1 |  v2 | 
| --- | --- | --- | 
| 재시도 | 구성을 사용할 수 없음 | 빌더 메서드 retryPolicy(...)를 통해 구성할 수 있습니다. | 
| HTTP | 연결 시간 제한은 AWS\$1METADATA\$1SERVICE\$1TIMEOUT 환경 변수를 통해 구성할 수 있습니다. 기본값은 1초입니다. | 빌더 메서드인 httpClient(...)에 HTTP 클라이언트를 전달하여 구성할 수 있습니다. HTTP 클라이언트의 기본 연결 시간 제한은 2초입니다. | 

### 예제 v2 HTTP 구성
<a name="migration-imds-http-conf-v2-ex"></a>

다음 예제는 메타데이터 클라이언트를 구성하는 방법을 보여줍니다. 이 예제에서는 연결 시간 제한을 구성하고 Apache HTTP 클라이언트를 사용합니다.

```
SdkHttpClient httpClient = ApacheHttpClient.builder()
    .connectionTimeout(Duration.ofSeconds(1))
    .build();

Ec2MetadataClient imdsClient = Ec2MetadataClient.builder()
    .httpClient(httpClient)
    .build();
```

# 버전 1에서 버전 2로 Amazon CloudFront 사전 서명 변경
<a name="migration-cloudfront-presigning"></a>

이 주제에서는 버전 1(v1)에서 버전 2(v2)로의 Amazon CloudFront 변경 사항에 대해 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-cloudfront-presigning-api-changes"></a>


****  

| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.5871</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency>  <br />        <groupId>com.amazonaws</groupId><br />        <artifactId>cloudfront</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.27.212</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>cloudfront</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.services.cloudfront | software.amazon.awssdk.services.cloudfront | 
| 클래스 이름 |  [CloudFrontUrlSigner](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cloudfront/CloudFrontUrlSigner.html) [CloudFrontCookieSigner](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cloudfront/CloudFrontCookieSigner.html)  |  [CloudFrontUtilities](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudfront/CloudFrontUtilities.html) [SignedUrl](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudfront/url/SignedUrl.html) [CannedSignerRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudfront/model/CannedSignerRequest.html) [CustomSignerRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/cloudfront/model/CustomSignerRequest.html)  | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## API 변경 사항
<a name="migration-cf-presign-behavior-changes"></a>


| 동작 | v1 |  v2 | 
| --- | --- | --- | 
| 미리 준비된 요청 구축 | 인수는 API로 직접 전달됩니다. |  <pre>CannedSignerRequest cannedRequest =<br />      CannedSignerRequest.builder()<br />                         .resourceUrl(resourceUrl)<br />                         .privateKey(privateKey)<br />                         .keyPairId(keyPairId)<br />                         .expirationDate(expirationDate)<br />                         .build();</pre>  | 
| 사용자 지정 요청 구축 | 인수는 API로 직접 전달됩니다. |  <pre>CustomSignerRequest customRequest =<br />      CustomSignerRequest.builder()<br />                         .resourceUrl(resourceUrl)<br />                         .resourceUrlPattern(resourceUrlPattern)<br />                         .privateKey(keyFile)<br />                         .keyPairId(keyPairId)<br />                         .expirationDate(expirationDate)<br />                         .activeDate(activeDate)<br />                         .ipRange(ipRange)<br />                         .build();</pre>  | 
| 서명된 URL 생성(미리 준비됨) |  <pre>String signedUrl =<br />  CloudFrontUrlSigner.getSignedURLWithCannedPolicy(<br />    resourceUrl, keyPairId, privateKey, expirationDate);</pre>  |  <pre>CloudFrontUtilities cloudFrontUtilities =<br />    CloudFrontUtilities.create();<br /><br />SignedUrl signedUrl =        <br />    cloudFrontUtilities.getSignedUrlWithCannedPolicy(cannedRequest);<br /><br />String url = signedUrl.url();<br /></pre>  | 
| 서명된 쿠키 생성(사용자 지정) |  <pre>CookiesForCustomPolicy cookies =<br />    CloudFrontCookieSigner.getCookiesForCustomPolicy(<br />        resourceUrl, privateKey, keyPairId, expirationDate, <br />        activeDate, ipRange);<br /></pre>  |  <pre>CloudFrontUtilities cloudFrontUtilities =<br />    CloudFrontUtilities.create();<br /><br />CookiesForCustomPolicy cookies =<br />     cloudFrontUtilities.getCookiesForCustomPolicy(customRequest);<br /></pre>  | 

### v2의 리팩터링된 쿠키 헤더
<a name="migration-cf-presign-behavior-headers"></a>

Java v1에서 Java SDK는 쿠키 헤더를 `Map.Entry<String, String>`으로 제공합니다.

```
Map.Entry<String, String> signatureMap = cookies.getSignature();
String signatureKey = signatureMap.getKey(); // "CloudFront-Signature"
String signatureValue = signatureMap.getValue(); // "[SIGNATURE_VALUE]"
```

Java v2 SDK는 전체 헤더를 단일 `String`으로 제공합니다.

```
String signatureHeaderValue = cookies.signatureHeaderValue(); // "CloudFront-Signature=[SIGNATURE_VALUE]"
```

# IAM 정책 빌더 API를 버전 1에서 버전 2로 변경
<a name="migration-iam-policy-builder"></a>

이 주제에서는 버전 1(v1)에서 버전 2(v2)로의 IAM 정책 빌더 API의 변경 사항에 대해 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-iam-policy-builder-high-level"></a>


****  

| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.5871</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-java-sdk-core</artifactId><br />    </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.27.212</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>iam-policy-builder</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.auth.policy | software.amazon.awssdk.policybuilder.iam | 
| 클래스 이름 |  [정책](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Policy.html) [Statement](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Statement.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-iam-policy-builder.html)  |  [IamPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPolicy.html) [IamStatement](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamStatement.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/migration-iam-policy-builder.html)  | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## API 변경 사항
<a name="migration-iam-policy-builder-api"></a>


****  

| 설정 | v1 |  v2 | 
| --- | --- | --- | 
|  정책 인스턴스화 |  <pre>Policy policy = new Policy();</pre>  |  <pre>IamPolicy.Builder policyBuilder = IamPolicy.builder();<br />...<br />IamPolicy policy = policyBuilder.build();</pre>  | 
|    세트 ID  |  <pre>policy.withtId(...);<br />policy.setId(...);</pre>  |  <pre>policyBuilder.id(...);</pre>  | 
|    세트 버전  | 해당 사항 없음 - 2012-10-17의 기본 버전을 사용합니다. |  <pre>policyBuilder.version(...);</pre>  | 
|    CREATE 문  |  <pre>Statement statement = <br />    new Statement(Effect.Allow)<br />            .withActions(...)<br />            .withConditions(...)<br />            .withId(...)<br />            .withPrincipals(...)<br />            .withResources(...);</pre>  |  <pre>IamStatement statement = <br />    IamStatement.builder()<br />            .effect(IamEffect.ALLOW)<br />            .actions(...)<br />            .notActions(...)<br />            .conditions(...)<br />            .sid(...)<br />            .principals(...)<br />            .notPrincipals(...)<br />            .resources(...)<br />            .notResources(...)<br />            .build()</pre>  | 
|    SET 문  |  <pre>policy.withStatements(statement);<br />policy.setStatements(statement);</pre>  |  <pre>policyBuilder.addStatement(statement);</pre>  | 

## 문 구축에서의 차이점
<a name="migration-iam-policy-builder-statement"></a>

### 작업
<a name="migration-iam-policy-builder-statement-actions"></a>

#### v1
<a name="migration-iam-policy-builder-statement-actions.v1"></a>

v1 SDK에는 정책 문의 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html)` 요소를 나타내는 서비스 작업에 대한 [`enum` 유형](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Action.html)이 포함됩니다. 다음 `enum` 유형은 몇 가지 예제입니다.
+ `[IdentityManagementActions](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/actions/IdentityManagementActions.html)`
+ `[DynamoDBv2Actions](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/actions/DynamoDBv2Actions.html)`
+ `[SQSActions](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/actions/SQSActions.html)`

다음 예제에서는 `SQSActions`에 대한 `SendMessage` 상수를 보여줍니다.

```
Action action = SQSActions.SendMessage;
```

v1의 문에 대해 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html)` 요소를 지정할 수 없습니다.

#### v2
<a name="migration-iam-policy-builder-statement-actions.v2"></a>

v2에서 [IamAction](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamAction.html) 인터페이스는 모든 작업을 나타냅니다. [서비스별 작업](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html) 요소를 지정하려면 다음 코드와 같이 문자열을 `create` 메서드에 전달합니다.

```
IamAction action = IamAction.create("sqs:SendMessage");
```

다음 코드와 같이 v2가 있는 문에 대해 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html)`을 지정할 수 있습니다.

```
IamAction action = IamAction.create("sqs:SendMessage");
IamStatement.builder().addNotAction(action);
```

### 조건
<a name="migration-iam-policy-builder-statement-conditions"></a>

#### v1
<a name="migration-iam-policy-builder-statement-conditions-v1"></a>

문 조건을 나타내기 위해 v1 SDK는의 [https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Condition.html](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Condition.html)의 하위 클래스를 사용합니다.
+  [ArnCondition](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/ArnCondition.html) 
+  [BooleanCondition](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/BooleanCondition.html)
+  [DateCondition](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/DateCondition.html)
+ [IpAddressCondition](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/IpAddressCondition.html)
+ [NumericCondition](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/NumericCondition.html)
+ [ StringCondition ](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/conditions/StringCondition.html)

각 `Condition` 하위 클래스는 조건을 정의하는 데 도움이 되는 비교 `enum` 유형을 정의합니다. 예를 들어 다음은 조건에 대한 *유사하지 않은*[ 문자열 비교](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_String)를 보여줍니다.

```
Condition condition = new StringCondition(StringComparisonType.StringNotLike, "key", "value");
```

#### v2
<a name="migration-iam-policy-builder-statement-conditions-v2"></a>

v2에서는 `[IamCondition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamCondition.html)`을 사용하여 정책 설명에 대한 조건을 구축하고 모든 유형에 대해 `enums`가 포함된`[IamConditionOperator](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamConditionOperator.html)`를 제공합니다.

```
IamCondition condition = IamCondition.create(IamConditionOperator.STRING_NOT_LIKE, "key", "value");
```

### 리소스
<a name="migration-iam-policy-builder-statement-resources"></a>

#### v1
<a name="migration-iam-policy-builder-statement-resources-v1"></a>

정책 문의 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html)` 요소는 SDK의 `[Resource](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Resource.html)` 클래스로 표시됩니다. 생성자에서 ARN을 문자열로 제공합니다. 다음 하위 클래스는 편의 생성자를 제공합니다.
+ [S3BucketResource](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/resources/S3BucketResource.html)
+ [S3ObjectResource](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/resources/S3ObjectResource.html)
+ [SQSQueueResource](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/resources/SQSQueueResource.html)

v1에서는 다음 문과 같이 `withIsNotType` 메서드를 직접적으로 호출하여 `[Resource](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Resource.html)`에 대한 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html)` 요소를 지정할 수 있습니다.

```
Resource resource = new Resource("arn:aws:s3:::amzn-s3-demo-bucket").withIsNotType(true);
```

#### v2
<a name="migration-iam-policy-builder-statement-resources-v2"></a>

v2에서는 ARN을 `IamResource.create` 메서드에 전달하여 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html)` 요소를 만듭니다.

```
IamResource resource = IamResource.create("arn:aws:s3:::amzn-s3-demo-bucket");
```

`[IamResource](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamResource.html)`는 다음 코드 조각과 같이 *[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html)* 요소로 설정할 수 있습니다.

```
IamResource resource = IamResource.create("arn:aws:s3:::amzn-s3-demo-bucket");
IamStatement.builder().addNotResource(resource);
```

`IamResource.ALL`은 모든 리소스를 나타냅니다.

### 보안 주체
<a name="migration-iam-policy-builder-statement-principal"></a>

#### v1
<a name="migration-iam-policy-builder-statement-principal-v1"></a>

v1 SDK는 모든 멤버를 포함하는 보안 주체 유형을 나타내는 다음 `[Principal](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/policy/Principal.html)` 클래스를 제공합니다.
+ `AllUsers`
+ `AllServices`
+ `AllWebProviders`
+ `All`

문에 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html)` 요소를 추가할 수 없습니다.

#### v2
<a name="migration-iam-policy-builder-statement-principal-v2"></a>

v2에서 `IamPrincipal.ALL`은 모든 보안 주체를 나타냅니다.

다른 유형의 보안 주체에 속한 모든 멤버를 나타내려면 `IamPrincipal`을 만들 때 `[IamPrincipalType](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/policybuilder/iam/IamPrincipalType.html)` 클래스를 사용합니다.
+ 모든 사용자에 대한 `IamPrincipal.create(IamPrincipalType.AWS,"*")`입니다.
+ 모든 서비스에 대한 `IamPrincipal.create(IamPrincipalType.SERVICE,"*")`입니다.
+ 모든 웹 공급자에 대한 `IamPrincipal.create(IamPrincipalType.FEDERATED,"*")`입니다.
+ 모든 표준 사용자에 대한 `IamPrincipal.create(IamPrincipalType.CANONICAL_USER,"*")`입니다.

다음 문과 같이 정책 문을 만들 때 `addNotPrincipal` 메서드를 사용하여 `[https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html)` 요소를 나타낼 수 있습니다.

```
IamPrincipal principal = IamPrincipal.create(IamPrincipalType.AWS, "arn:aws:iam::444455556666:root");
IamStatement.builder().addNotPrincipal(principal);
```

# 의 버전 1에서 버전 2로 DynamoDB 작업 시 변경 사항 AWS SDK for Java
<a name="migration-ddb-mapper"></a>



**Topics**
+ [의 버전 1과 버전 2 간의 DynamoDB 매핑 API 차이점 AWS SDK for Java](ddb-mapping.md)
+ [버전 1과 버전 2 간의 API 차이점 문서화 AWS SDK for Java](dynamodb-mapping-document-api.md)
+ [암호화 라이브러리 마이그레이션](ddb-encryption-lib-migrate.md)

# 의 버전 1과 버전 2 간의 DynamoDB 매핑 API 차이점 AWS SDK for Java
<a name="ddb-mapping"></a>

DynamoDB 매핑 API는 AWS SDK for Java의 버전 1과 버전 2 간에 크게 변경되었습니다. 버전 1에서는 `DynamoDBMapper`를 사용하여 Java POJO를 작업합니다. 버전 2에서는 업데이트된 메서드 이름, 향상된 스키마 정의 옵션 및 향상된 유형 안전과 함께 `DynamoDbEnhancedClient`를 사용합니다.

주요 차이점은 다음과 같습니다.
+ 새 메서드 이름(예: `load` 대신 `getItem`)
+ 명시적 테이블 스키마 만들기
+ 동기식 및 비동기식 작업 모두에 대한 기본 제공 지원
+ 비어 있는 문자열 및 구성 처리 방법 변경

이 섹션에서는 v1 `DynamoDBMapper`에서 v2 `DynamoDbEnhancedClient`로 전환하는 데 도움이 되는 매핑 API 변경 사항, 주석 차이, 구성 업데이트 및 마이그레이션 안내를 다룹니다.

**Contents**
+ [SDK for Java의 버전 1에서 버전 2로의 매핑 라이브러리에 대한 개괄적인 변경 사항](dynamodb-mapping-high-level.md)
  + [종속성 차이 가져오기](dynamodb-mapping-high-level.md#dynamodb-mapping-deps)
+ [SDK for Java 버전 1과 버전 2 간의 DynamoDB 매핑 API 변경 사항](dynamodb-mapping-api-changes.md)
  + [클라이언트 만들기](dynamodb-mapping-api-changes.md#dynamodb-mapping-api-changes-client)
  + [DynamoDB 테이블/인덱스에 대한 매핑 설정](dynamodb-mapping-api-changes.md#dynamodb-mapping-api-changes-mapping)
  + [테이블 작업](dynamodb-mapping-api-changes.md#dynamodb-mapping-api-changes-tobleops)
  + [클래스 및 속성 매핑](dynamodb-mapping-api-changes.md#dynamodb-mapping-schemas)
    + [bean 주석](dynamodb-mapping-api-changes.md#dynamodb-mapping-schemas-annos)
    + [V2 추가 주석](dynamodb-mapping-api-changes.md#dynamodb-mapping-schemas-annos-v2-addnl)
  + [구성](dynamodb-mapping-api-changes.md#dynamodb-mapping-configuration)
    + [작업별 구성](dynamodb-mapping-api-changes.md#dynamodb-mapping-configuration-per-op)
  + [조건](dynamodb-mapping-api-changes.md#dynamodb-mapping-conditionals)
  + [유형 변환](dynamodb-mapping-api-changes.md#dynamodb-mapping-type-conv)
    + [기본 변환기](dynamodb-mapping-api-changes.md#dynamodb-mapping-type-conv-defaults)
    + [속성에 대한 사용자 지정 변환기 설정](dynamodb-mapping-api-changes.md#dynamodb-mapping-type-conv-anno)
    + [유형 변환기 팩토리 또는 공급자 추가](dynamodb-mapping-api-changes.md#dynamodb-mapping-type-conv-factory)
+ [SDK for Java 버전 1과 버전 2 간의 문자열 처리 차이점](dynamodb-migration-string-handling.md)
+ [SDK for Java 버전 1과 버전 2의 낙관적 잠금 차이점](dynamodb-migrate-optimstic-locking.md)
+ [SDK for Java 버전 1과 버전 2 간의 유용한 setter 차이점](dynamodb-migrate-fluent-setters.md)

# SDK for Java의 버전 1에서 버전 2로의 매핑 라이브러리에 대한 개괄적인 변경 사항
<a name="dynamodb-mapping-high-level"></a>

각 라이브러리의 매핑 클라이언트 이름은 V1과 V2에서 다릅니다.
+ V1 - DynamoDBMapper
+ V2 - DynamoDB 향상된 클라이언트

두 라이브러리와 거의 동일한 방식으로 상호 작용합니다. 즉, 매퍼/클라이언트를 인스턴스화한 다음 이러한 항목을 읽고 DynamoDB 테이블에 쓰는 API에 Java POJO를 제공합니다. 또한 두 라이브러리 모두 POJO 클래스에 대한 주석을 제공하여 클라이언트가 POJO를 처리하는 방법을 지시합니다.

V2로 이전할 때 눈에 띄는 차이점은 다음과 같습니다.
+ V2와 V1은 하위 수준 DynamoDB 작업에 서로 다른 메서드 이름을 사용합니다. 예제:    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/dynamodb-mapping-high-level.html)
+ V2는 테이블 스키마를 정의하고 POJO 테이블에 매핑하는 다양한 방법을 제공합니다. 빌더를 사용하여 코드에서 생성된 스키마 또는 주석 사용 중에서 선택할 수 있습니다. 또한 V2는 변경 및 변경 불가능한 버전의 스키마를 제공합니다.
+ V2에서는 특히 첫 번째 단계 중 하나로 테이블 스키마를 만드는 반면, V1에서는 필요에 따라 주석이 달린 클래스에서 테이블 스키마를 추론합니다.
+ V2는 향상된 클라이언트 API에 [문서 API 클라이언트](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html)를 포함하는 반면, V1은 [별도의 API](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/DynamoDB.html)를 사용합니다.
+ 모든 API는 V2의 동기식 및 비동기식 버전에서 사용할 수 있습니다.

V2 향상된 클라이언트에 대한 자세한 내용은 이 가이드의 [DynamoDB 매핑 섹션](dynamodb-enhanced-client.md)을 참조하세요.

## 종속성 차이 가져오기
<a name="dynamodb-mapping-deps"></a>


| V1 | V2 | 
| --- | --- | 
|  <pre><dependencyManagement><br />  <dependencies><br />    <dependency><br />      <groupId>com.amazonaws</groupId><br />      <artifactId>aws-java-sdk-bom</artifactId><br />      <version>1.X.X</version><br />      <type>pom</type><br />      <scope>import</scope><br />    </dependency><br />  </dependencies><br /></dependencyManagement> <br /><br /><dependencies><br />  <dependency><br />    <groupId>com.amazonaws</groupId><br />    <artifactId>aws-java-sdk-dynamodb</artifactId><br />  </dependency><br /></dependencies></pre>  |  <pre><dependencyManagement><br />  <dependencies><br />    <dependency><br />      <groupId>software.amazon.awssdk</groupId><br />      <artifactId>bom</artifactId><br />      <version>2.X.X*</version><br />      <type>pom</type><br />      <scope>import</scope><br />    </dependency><br />  </dependencies><br /></dependencyManagement> <br /><br /><dependencies><br />  <dependency><br />    <groupId>software.amazon.awssdk</groupId><br />    <artifactId>dynamodb-enhanced</artifactId><br />  </dependency><br /></dependencies></pre>  | 

\$1 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

V1에서는 단일 종속성에 하위 수준 DynamoDB API와 매핑/문서 API가 모두 포함되는 반면, V2에서는 `dynamodb-enhanced` 아티팩트 종속성을 사용하여 매핑/문서 API에 액세스합니다. `dynamodb-enhanced` 모듈에는 하위 수준 `dynamodb` 모듈에 대한 전이적 종속성이 포함되어 있습니다.

# SDK for Java 버전 1과 버전 2 간의 DynamoDB 매핑 API 변경 사항
<a name="dynamodb-mapping-api-changes"></a>

## 클라이언트 만들기
<a name="dynamodb-mapping-api-changes-client"></a>


****  

| 사용 사례: | V1 | V2 | 
| --- | --- | --- | 
|   일반 인스턴스화  |  <pre>AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard()<br />    .withCredentials(credentialsProvider)<br />    .withRegion(Regions.US_EAST_1)<br />    .build();<br />DynamoDBMapper mapper = new DynamoDBMapper(standardClient);</pre>  |  <pre>DynamoDbClient standardClient = DynamoDbClient.builder()<br />    .credentialsProvider(ProfileCredentialsProvider.create())<br />    .region(Region.US_EAST_1)<br />    .build();<br />DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()<br />    .dynamoDbClient(standardClient)<br />    .build();</pre>  | 
|   최소 인스턴스화  |  <pre>AmazonDynamoDB standardClient = AmazonDynamoDBClientBuilder.standard();<br />DynamoDBMapper mapper = new DynamoDBMapper(standardClient);</pre>  |  <pre>DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create();</pre>  | 
|   속성 변환기 사용\$1  |  <pre>DynamoDBMapper mapper = new DynamoDBMapper(standardClient, <br />                        attributeTransformerInstance);</pre>  |  <pre>DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()<br />    .dynamoDbClient(standardClient)<br />    .extensions(extensionAInstance, extensionBInstance)<br />    .build();</pre>  | 

\$1V2의 확장은 대략 V1의 속성 변환기에 해당합니다. 이 [확장 프로그램을 사용하여 DynamoDB 향상된 클라이언트 작업 사용자 지정](ddb-en-client-extensions.md) 섹션에는 V2의 확장에 대한 자세한 내용이 포함되어 있습니다.

## DynamoDB 테이블/인덱스에 대한 매핑 설정
<a name="dynamodb-mapping-api-changes-mapping"></a>

V1에서는 bean 주석을 통해 DynamoDB 테이블 이름을 지정합니다. V2에서는 팩토리 메서드인 `table()`이 원격 DynamoDB 테이블을 나타내는 `DynamoDbTable`의 인스턴스를 생성합니다. `table()` 메서드의 첫 번째 파라미터는 DynamoDB 테이블 이름입니다.


****  

| 사용 사례: | V1 | V2 | 
| --- | --- | --- | 
|   Java POJO 클래스를 DynamoDB 테이블에 매핑  |  <pre>@DynamoDBTable(tableName ="Customer")<br />public class Customer {<br />  ...<br />}</pre>  |  <pre>DynamoDbTable<Customer> customerTable = enhancedClient.table("Customer",<br />    TableSchema.fromBean(Customer.class));</pre>  | 
|   DynamoDB 보조 인덱스에 매핑  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) [ V1 `query` 메서드](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.Methods.html#DynamoDBMapper.Methods.query)에 대해 설명하는 DynamoDB 개발자 안내서의 섹션에는 전체 예제가 나와 있습니다.  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) 이 안내서의 [보조 인덱스 사용](ddb-en-client-use-secindex.md) 섹션에서는 자세한 내용을 제공합니다.  | 

## 테이블 작업
<a name="dynamodb-mapping-api-changes-tobleops"></a>

이 섹션에서는 작업 API를 설명하며, 이는 대부분의 표준 사용 사례에 대한 V1과 V2 간의 차이점이 포함됩니다.

V2에서는 단일 테이블과 관련된 모든 작업이 향상된 클라이언트가 아닌 `DynamoDbTable` 인스턴스에서 직접적으로 호출됩니다. 향상된 클라이언트에는 여러 테이블을 대상으로 지정할 수 있는 메서드가 포함되어 있습니다.

아래 *테이블 작업*이라는 테이블에서 POJO 인스턴스를 `item` 또는 `customer1` 등의 특정 유형이라고 합니다. V2 예제의 경우 이름이 `table`인 인스턴스는 `DynamoDbTable` 인스턴스에 대한 참조를 반환하는 `enhancedClient.table()`을 이전에 직접적으로 호출한 결과입니다.

대부분의 V2 작업은 표시되지 않은 경우에도 유용한 소비자 패턴으로 직접 호출할 수 있습니다. 예:

```
Customer customer = table.getItem(r → r.key(key));
  or
Customer customer = table.getItem(r → r.key(k -> k.partitionValue("id").sortValue("email")))
```

V1 작업의 경우 *테이블 작업*(아래)에는 모든 오버로드된 양식이 아닌 일반적으로 사용되는 양식 중 일부가 포함됩니다. 예를 들어 `load()` 메서드에는 다음과 같은 오버로드가 있습니다.

```
mapper.load(Customer.class, hashKey)
mapper.load(Customer.class, hashKey, rangeKey)
mapper.load(Customer.class, hashKey, config)
mapper.load(Customer.class, hashKey, rangeKey, config)
mapper.load(item)
mapper.load(item, config)
```

*테이블 작업*(아래)은 일반적으로 사용되는 양식을 보여줍니다.

```
mapper.load(item)
mapper.load(item, config)
```


**테이블 작업**  

| 사용 사례: | V1 | V2 | 
| --- | --- | --- | 
|  DynamoDB 테이블에 Java POJO 쓰기 **DynamoDB 작업:** `PutItem`, `UpdateItem`   |  <pre>mapper.save(item)<br />mapper.save(item, config)<br />mapper.save(item, saveExpression, config)</pre> V1에서 `DynamoDBMapperConfig.SaveBehavior` 및 주석은 직접적으로 호출할 하위 수준 DynamoDB 메서드를 결정합니다. 일반적으로 `UpdateItem`은 `SaveBehavior.CLOBBER` 및 `SaveBehavior.PUT` 코드를 사용할 때를 제외하고 직접적으로 호출됩니다. 자동 생성된 키는 특별한 사용 사례이며 경우에 따라 `PutItem` 및 `UpdateItem`이 모두 사용됩니다.  |  <pre>table.putItem(putItemRequest)<br />table.putItem(item)<br />table.putItemWithResponse(item) //Returns metadata.<br /><br />updateItem(updateItemRequest)<br />table.updateItem(item)<br />table.updateItemWithResponse(item) //Returns metadata.</pre>  | 
|  DynamoDB 테이블에서 Java POJO로의 항목 읽기 **DynamoDB 작업:** `GetItem`  |  <pre>mapper.load(item)<br />mapper.load(item, config)</pre>  |  <pre>table.getItem(getItemRequest)<br />table.getItem(item)<br />table.getItem(key)<br />table.getItemWithResponse(key) //Returns POJO with metadata.</pre>  | 
|  DynamoDB 테이블에서 항목 삭제 **DynamoDB 작업:** `DeleteItem`  |  <pre>mapper.delete(item, deleteExpression, config)</pre>  |  <pre>table.deleteItem(deleteItemRequest)<br />table.deleteItem(item)<br />table.deleteItem(key)</pre>  | 
|  DynamoDB 테이블 또는 보조 인덱스 쿼리 및 페이지 매김 목록 반환 **DynamoDB 작업:** `Query`  |  <pre>mapper.query(Customer.class, queryExpression)<br />mapper.query(Customer.class, queryExpression, <br />                             mapperConfig)</pre>  |  <pre>table.query(queryRequest)<br />table.query(queryConditional)</pre> 동기식 응답에서 반환된 `PageIterable.stream()`(지연 로딩) 및 비동기식 응답에서 반환된 `PagePublisher.subscribe()` 사용  | 
|  DynamoDB 테이블 또는 보조 인덱스 쿼리 및 목록 반환 **DynamoDB 작업:** `Query`  |  <pre>mapper.queryPage(Customer.class, queryExpression)<br />mapper.queryPage(Customer.class, queryExpression, <br />                                 mapperConfig)</pre>  |  <pre>table.query(queryRequest)<br />table.query(queryConditional)</pre> 동기식 응답에서 반환된 `PageIterable.items()`(지연 로딩) 및 비동기식 응답에서 반환된 `PagePublisher.items.subscribe()` 사용  | 
|  DynamoDB 테이블 또는 보조 인덱스 스캔 및 페이지 매김 목록 반환 **DynamoDB 작업:** `Scan`  |  <pre>mapper.scan(Customer.class, scanExpression)<br />mapper.scan(Customer.class, scanExpression, <br />                            mapperConfig)</pre>  |  <pre>table.scan()<br />table.scan(scanRequest)</pre> 동기식 응답에서 반환된 `PageIterable.stream()`(지연 로딩) 및 비동기식 응답에서 반환된 `PagePublisher.subscribe()` 사용  | 
|  DynamoDB 테이블 또는 보조 인덱스 스캔 및 목록 반환 **DynamoDB 작업:** `Scan`  |  <pre>mapper.scanPage(Customer.class, scanExpression)<br />mapper.scanPage(Customer.class, scanExpression, <br />                                mapperConfig)</pre>  |  <pre>table.scan()<br />table.scan(scanRequest)</pre> 동기식 응답에서 반환된 `PageIterable.items()`(지연 로딩) 및 비동기식 응답에서 반환된 `PagePublisher.items.subscribe()` 사용  | 
|  배치의 여러 테이블에서 여러 항목 읽기 **DynamoDB 작업:** `BatchGetItem`  |  <pre>mapper.batchLoad(Arrays.asList(customer1, <br />                               customer2, <br />                               book1))<br />mapper.batchLoad(itemsToGet) <br />           // itemsToGet: Map<Class<?>, List<KeyPair>></pre>  |  <pre>enhancedClient.batchGetItem(batchGetItemRequest)<br /><br />enhancedClient.batchGetItem(r -> r.readBatches(<br />    ReadBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addGetItem(i -> i.key(k -> k.partitionValue(0)))<br />             .build(),<br />    ReadBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addGetItem(i -> i.key(k -> k.partitionValue(0)))<br />             .build()))<br /><br />// Iterate over pages with lazy loading or over all items <br />   from the same table.</pre>  | 
|  배치의 여러 테이블에 여러 항목 쓰기 **DynamoDB 작업:** `BatchWriteItem`  |  <pre>mapper.batchSave(Arrays.asList(customer1, <br />                               customer2, <br />                               book1)) </pre>  |  <pre>enhancedClient.batchWriteItem(batchWriteItemRequest)<br /><br />enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addPutItem(item1)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addPutItem(item2)<br />             .build()))</pre>  | 
|  배치의 여러 테이블에서 여러 항목 삭제 **DynamoDB 작업:** `BatchWriteItem`  |  <pre>mapper.batchDelete(Arrays.asList(customer1, <br />                                 customer2, <br />                                 book1)) </pre>  |  <pre>enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addDeleteItem(item1key)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addDeleteItem(item2key)<br />             .build()))</pre>  | 
|  배치에서 여러 항목 쓰기/삭제 **DynamoDB 작업:** `BatchWriteItem`  |  <pre>mapper.batchWrite(Arrays.asList(customer1, book1), <br />                  Arrays.asList(customer2)) </pre>  |  <pre>enhancedClient.batchWriteItem(r -> r.writeBatches(<br />    WriteBatch.builder(Record1.class)<br />             .mappedTableResource(mappedTable1)<br />             .addPutItem(item1)<br />             .build(),<br />    WriteBatch.builder(Record2.class)<br />             .mappedTableResource(mappedTable2)<br />             .addDeleteItem(item2key)<br />             .build()))</pre>  | 
|  트랜잭션 쓰기 수행 **DynamoDB 작업:** `TransactWriteItems`  |  <pre>mapper.transactionWrite(transactionWriteRequest)</pre>  |  <pre>enhancedClient.transactWriteItems(transasctWriteItemsRequest)</pre>  | 
|  트랜잭션 읽기 수행 **DynamoDB 작업:** `TransactGetItems`  |  <pre>mapper.transactionLoad(transactionLoadRequest)</pre>  |  <pre>enhancedClient.transactGetItems(transactGetItemsRequest) </pre>  | 
|  쿼리의 일치하는 항목 수 가져오기 **DynamoDB 작업:** `Select.COUNT`로 `Query`  |  <pre>mapper.count(Customer.class, queryExpression)</pre>  |  <pre>// Get the count from query results.<br />PageIterable<Customer> pageIterable =<br />    customerTable.query(QueryEnhancedRequest.builder()<br />        .queryConditional(queryConditional)<br />        .select(Select.COUNT)<br />        .build());<br />Iterator<Page<Customer>> iterator = pageIterable.iterator();<br />Page<Customer> page = iterator.next();<br />int count = page.count();<br /><br />// For a more concise approach, you can chain the method calls:<br />int count = customerTable.query(QueryEnhancedRequest.builder()<br />                .queryConditional(queryConditional)<br />                .select(Select.COUNT)<br />                .build())<br />            .iterator().next().count();</pre>  | 
|  스캔의 일치하는 항목 수 가져오기 **DynamoDB 작업:** `Select.COUNT`로 `Scan`  |  <pre>mapper.count(Customer.class, scanExpression)</pre>  |  <pre>// Get the count from scan results.<br />PageIterable<Customer> pageIterable =<br />    customerTable.scan(ScanEnhancedRequest.builder()<br />        .filterExpression(filterExpression)<br />        .select(Select.COUNT)<br />        .build());<br />Iterator<Page<Customer>> iterator = pageIterable.iterator();<br />Page<Customer> page = iterator.next();<br />int count = page.count();<br /><br />// For a more concise approach, you can chain the method calls:<br />int count = customerTable.scan(ScanEnhancedRequest.builder()<br />                .filterExpression(filterExpression)<br />                .select(Select.COUNT)<br />                .build())<br />            .iterator().next().count();</pre>  | 
|  DynamoDB에서 POJO 클래스에 해당하는 테이블 만들기 **DynamoDB 작업:** `CreateTable`  |  <pre>mapper.generateCreateTableRequest(Customer.class)</pre> 이전 문은 하위 수준 테이블 만들기 요청을 생성합니다. 사용자는 DynamoDB 클라이언트에서 `createTable`을 직접적으로 호출해야 합니다.  |  <pre>table.createTable(createTableRequest)<br /><br />table.createTable(r -> r.provisionedThroughput(defaultThroughput())<br />    .globalSecondaryIndices(<br />        EnhancedGlobalSecondaryIndex.builder()<br />            .indexName("gsi_1")<br />            .projection(p -> p.projectionType(ProjectionType.ALL))<br />            .provisionedThroughput(defaultThroughput())<br />            .build()));</pre>  | 
|  DynamoDB에서 병렬 스캔 수행 **DynamoDB 작업:** `Segment` 및 `TotalSegments` 파라미터로 `Scan`  |  <pre>mapper.parallelScan(Customer.class, <br />                    scanExpression, <br />                    numTotalSegments)</pre>  |  사용자는 작업자 스레드를 처리하고 각 세그먼트에 대해 `scan`을 직접적으로 호출해야 합니다. <pre>table.scan(r -> r.segment(0).totalSegments(5))</pre>  | 
|  Amazon S3를 DynamoDB와 통합하여 지능형 S3 링크 저장  |  <pre>mapper.createS3Link(bucket, key)<br />mapper.getS3ClientCache()</pre>  |  Amazon S3와 DynamoDB를 통합하므로 지원되지 않습니다.  | 

## 클래스 및 속성 매핑
<a name="dynamodb-mapping-schemas"></a>

V1과 V2 모두에서 bean 스타일 주석을 사용하여 클래스를 테이블에 매핑합니다. V2는 변경 불가능한 클래스 작업 등 특정 사용 사례에 대한 [스키마를 정의하는 다른 방법](ddb-en-client-adv-features.md#ddb-en-client-adv-features-schm-overview)도 제공합니다.

### bean 주석
<a name="dynamodb-mapping-schemas-annos"></a>

다음 테이블에는 V1 및 V2에 사용되는 특정 사용 사례별로 동등한 bean 주석이 나와 있습니다. `Customer` 클래스 시나리오는 파라미터를 설명하는 데 사용됩니다.

V2의 주석, 클래스, 열거는 Camel 대문자 규칙을 따르고 ‘DynamoDB’가 아닌 ‘DynamoDb’를 사용합니다.


| 사용 사례: | V1 | V2 | 
| --- | --- | --- | 
| 클래스를 테이블에 매핑 |  <pre>@DynamoDBTable (tableName ="CustomerTable")</pre>  | <pre>@DynamoDbBean<br />@DynamoDbBean(converterProviders = {...})</pre>테이블 이름은 DynamoDbEnhancedClient\$1table() 메서드를 직접적으로 호출할 때 정의됩니다. | 
| 클래스 멤버를 테이블 속성으로 지정  |  <pre>@DynamoDBAttribute(attributeName = "customerName")</pre>  |  <pre>@DynamoDbAttribute("customerName") </pre>  | 
| 클래스 멤버를 해시/파티션 키로 지정 |  <pre>@DynamoDBHashKey </pre>  |  <pre>@DynamoDbPartitionKey</pre>  | 
| 클래스 멤버를 범위/정렬 키로 지정 |  <pre>@DynamoDBRangeKey </pre>  |  <pre>@DynamoDbSortKey </pre>  | 
| 클래스 멤버를 보조 인덱스 해시/파티션 키로 지정 |  <pre>@DynamoDBIndexHashKey </pre>  |  <pre>@DynamoDbSecondaryPartitionKey </pre>  | 
| 클래스 멤버를 보조 인덱스 범위/정렬 키로 지정 |  <pre>@DynamoDBIndexRangeKey </pre>  |  <pre>@DynamoDbSecondarySortKey </pre>  | 
| 테이블에 매핑할 때 이 클래스 멤버 무시 |  <pre>@DynamoDBIgnore </pre>  |  <pre>@DynamoDbIgnore</pre>  | 
| 클래스 멤버를 자동 생성된 UUID 키 속성으로 지정 |  <pre>@DynamoDBAutoGeneratedKey</pre>  |  <pre>@DynamoDbAutoGeneratedUuid </pre> 이를 제공하는 확장 프로그램은 기본적으로 로드되지 않으므로 클라이언트 빌더에 확장 프로그램을 추가해야 합니다.  | 
| 클래스 멤버를 자동 생성된 타임스탬프 속성으로 지정 |  <pre>@DynamoDBAutoGeneratedTimestamp</pre>  |  <pre>@DynamoDbAutoGeneratedTimestampAttribute</pre> 이를 제공하는 확장 프로그램은 기본적으로 로드되지 않으므로 클라이언트 빌더에 확장 프로그램을 추가해야 합니다.  | 
| 클래스 멤버를 자동 증분 버전 속성으로 지정 |  <pre>@DynamoDBVersionAttribute</pre>  |  <pre>@DynamoDbVersionAttribute</pre> 이를 제공하는 확장 프로그램은 자동으로 로드됩니다.  | 
| 클래스 멤버를 사용자 지정 변환이 필요한 것으로 지정 |  <pre>@DynamoDBTypeConverted</pre>  |  <pre>@DynamoDbConvertedBy</pre>  | 
| 다른 속성 유형으로 저장할 클래스 멤버 지정 |  <pre>@DynamoDBTyped(<DynamoDBAttributeType>)</pre>  |  `AttributeConverter` 구현을 사용합니다. V2는 일반적인 Java 유형을 위한 많은 기본 제공 변환기를 지원합니다. 자체 사용자 지정 `AttributeConverter` 또는 `AttributeConverterProvider`를 구현할 수도 있습니다. 이 설명서의 [제어 속성 변환](ddb-en-client-adv-features-conversion.md) 섹션을 참조하세요.  | 
| DynamoDB 문서(JSON 형식 문서) 또는 하위 문서로 직렬화할 수 있는 클래스 지정  |  <pre>@DynamoDBDocument</pre>  | 향상된 문서 API 사용 다음 리소스를 참조하세요.[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html) | 

### V2 추가 주석
<a name="dynamodb-mapping-schemas-annos-v2-addnl"></a>


| 사용 사례: | V1 | V2 | 
| --- | --- | --- | 
| Java 값이 null인 경우 클래스 멤버를 null 속성으로 저장하지 않도록 지정 | 해당 사항 없음 |  <pre>@DynamoDbIgnoreNulls</pre>  | 
| 모든 속성이 null인 경우 클래스 멤버를 비어 있는 객체로 지정 | 해당 사항 없음 |  <pre>@DynamoDbPreserveEmptyObject</pre>  | 
| 클래스 멤버에 대한 특별 업데이트 작업 지정 | 해당 사항 없음 |  <pre>@DynamoDbUpdateBehavior</pre>  | 
| 변경할 수 없는 클래스 지정 | 해당 사항 없음 |  <pre>@DynamoDbImmutable</pre>  | 
| 클래스 멤버를 자동 증분 카운터 속성으로 지정 | 해당 사항 없음 |  <pre>@DynamoDbAtomicCounter</pre> 이 기능을 제공하는 확장 프로그램은 자동으로 로드됩니다.  | 

## 구성
<a name="dynamodb-mapping-configuration"></a>

V1에서는 일반적으로 `DynamoDBMapperConfig`의 인스턴스를 사용하여 특정 동작을 제어합니다. 매퍼를 만들거나 요청할 때 구성 객체를 제공할 수 있습니다. V2에서 구성은 작업에 대한 요청 객체에 따라 다릅니다.


| 사용 사례: | V1 | V1의 기본값 | V2 | 
| --- | --- | --- | --- | 
|  |  <pre>DynamoDBMapperConfig.builder()</pre>  |  |  | 
| 배치 로드/쓰기 재시도 전략 |  <pre>  .withBatchLoadRetryStrategy(loadRetryStrategy)</pre> <pre>  .withBatchWriteRetryStrategy(writeRetryStrategy)</pre>  | 실패한 항목 재시도 | 기본 DynamoDBClient에서 재시도 전략을 구성합니다. 이 설명서의 [에서 재시도 동작 구성 AWS SDK for Java 2.x](retry-strategy.md) 섹션을 참조하세요. | 
| 일관된 읽기 |  <pre>  .withConsistentReads(CONSISTENT)</pre>  | EVENTUAL | 기본적으로 일관된 읽기는 읽기 작업에 대해 false입니다. 요청 객체에서 .consistentRead(true)로 재정의합니다. | 
| 마샬러/언마샬러 세트가 포함된 변환 스키마 |  <pre>  .withConversionSchema(conversionSchema)</pre> 정적 구현에서는 구버전과 이전 버전과의 호환성을 제공합니다.  | V2\$1COMPATIBLE | 해당 사항 없음. 이는 DynamoDB(V1)의 최신 버전이 데이터 형식을 저장한 방식을 나타내는 레거시 기능이며, 이 동작은 향상된 클라이언트에서 유지되지 않습니다. DynamoDB V1의 동작 예제는 부울을 부울 대신 숫자로 저장합니다. | 
| 테이블 이름 |  <pre>  .withObjectTableNameResolver()<br />  .withTableNameOverride() <br />  .withTableNameResolver()</pre> 정적 구현에서 구버전과 이전 버전과의 호환성 제공  | 클래스에서 주석 또는 추측 사용 |  테이블 이름은 `DynamoDbEnhancedClient#table()` 메서드를 직접적으로 호출할 때 정의됩니다.  | 
| 페이지 매김 로드 전략 |  <pre>  .withPaginationLoadingStrategy(strategy)</pre>  옵션은 LAZY\$1`LOADING`, `EAGER_LOADING` 또는 `ITERATION_ONLY`입니다.  | LAZY\$1LOADING |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/dynamodb-mapping-api-changes.html)  | 
| 지표 수집 요청 |  <pre>  .withRequestMetricCollector(collector)</pre>  | null | 표준 DynamoDB 클라이언트를 구축할 때 ClientOverrideConfiguration에서 metricPublisher()를 사용합니다. | 
| 동작 저장 |  <pre>  .withSaveBehavior(SaveBehavior.CLOBBER) </pre> 옵션은 `UPDATE`, `CLOBBER`, `PUT`, `APPEND_SET`, `UPDATE_SKIP_NULL_ATTRIBUTES`입니다.  | UPDATE |  V2에서는 `putItem()` 또는 `updateItem()`을 명시적으로 직접 호출합니다. `CLOBBER or PUT`: v 2의 해당 작업은 `putItem()`을 직접적으로 호출합니다. 특정 `CLOBBER` 구성은 없습니다. `UPDATE`:에 해당 `updateItem()` `UPDATE_SKIP_NULL_ATTRIBUTES`:에 해당합니다`updateItem()`. 요청 설정 `ignoreNulls` 및 주석/태그 `DynamoDbUpdateBehavior`를 사용하여 업데이트 동작을 제어합니다. `APPEND_SET`: 지원되지 않음:  | 
| 유형 변환기 팩토리 |  <pre>  .withTypeConverterFactory(typeConverterFactory) </pre>  | 표준 유형 변환기 |  bean에 설정하는 수단 <pre>@DynamoDbBean(converterProviders = {ConverterProvider.class, <br />        DefaultAttributeConverterProvider.class})</pre>  | 

### 작업별 구성
<a name="dynamodb-mapping-configuration-per-op"></a>

V1에서 `query()` 등의 일부 작업은 작업에 제출된 ‘표현식’ 객체를 통해 고도로 구성할 수 있습니다. 예제:

```
DynamoDBQueryExpression<Customer> emailBwQueryExpr = new DynamoDBQueryExpression<Customer>()
    .withRangeKeyCondition("Email",
        new Condition()
            .withComparisonOperator(ComparisonOperator.BEGINS_WITH)
            .withAttributeValueList(
                new AttributeValue().withS("my")));

mapper.query(Customer.class, emailBwQueryExpr);
```

V2에서는 구성 객체를 사용하는 대신 빌더를 사용하여 요청 객체에 파라미터를 설정합니다. 예제:

```
QueryEnhancedRequest emailBw = QueryEnhancedRequest.builder()
    .queryConditional(QueryConditional
        .sortBeginsWith(kb -> kb
            .sortValue("my"))).build();

customerTable.query(emailBw);
```

## 조건
<a name="dynamodb-mapping-conditionals"></a>

V2에서 조건부 및 필터링 표현식은 조건과 이름 및 필터 매핑을 캡슐화하는 `Expression` 객체를 사용하여 표현됩니다.


| 사용 사례: | 운영 | V1 | V2 | 
| --- | --- | --- | --- | 
| 예상 속성 조건 | save(), delete(), query(), scan() |  <pre>new DynamoDBSaveExpression()<br />  .withExpected(Collections.singletonMap(<br />      "otherAttribute", new ExpectedAttributeValue(false)))<br />  .withConditionalOperator(ConditionalOperator.AND);</pre>  | 지원 종료되며 대신 ConditionExpression을 사용합니다. | 
| 조건 표현식 | delete() |  <pre>deleteExpression.setConditionExpression("zipcode = :zipcode")<br />deleteExpression.setExpressionAttributeValues(...)<br /></pre>  |  <pre>Expression conditionExpression =<br />    Expression.builder()<br />        .expression("#key = :value OR #key1 = :value1")<br />        .putExpressionName("#key", "attribute")<br />        .putExpressionName("#key1", "attribute3")<br />        .putExpressionValue(":value", AttributeValues.stringValue("wrong"))<br />        .putExpressionValue(":value1", AttributeValues.stringValue("three"))<br />        .build();<br /><br />DeleteItemEnhancedRequest request = DeleteItemEnhancedRequest.builder()<br />         .conditionExpression(conditionExpression).build();</pre>  | 
| 필터 표현식 | query(), scan() |  <pre>scanExpression<br />  .withFilterExpression("#statename = :state")<br />  .withExpressionAttributeValues(attributeValueMapBuilder.build())<br />  .withExpressionAttributeNames(attributeNameMapBuilder.build())<br /></pre>  |  <pre>Map<String, AttributeValue> values = singletonMap(":key", stringValue("value"));<br />Expression filterExpression =<br />    Expression.builder()<br />        .expression("name = :key")<br />        .expressionValues(values)<br />        .build();<br />QueryEnhancedRequest request = QueryEnhancedRequest.builder()<br />    .filterExpression(filterExpression).build();<br /></pre>  | 
| 쿼리에 대한 키 조건 표현식 | query() |  <pre>queryExpression.withKeyConditionExpression()</pre>  |  <pre>QueryConditional keyEqual = QueryConditional.keyEqualTo(b -> b<br />                .partitionValue("movie01"));<br /><br />QueryEnhancedRequest tableQuery = QueryEnhancedRequest.builder()<br />                .queryConditional(keyEqual)<br />                .build();</pre>  | 

## 유형 변환
<a name="dynamodb-mapping-type-conv"></a>

### 기본 변환기
<a name="dynamodb-mapping-type-conv-defaults"></a>

V2에서 SDK는 모든 일반 유형에 대한 기본 변환기 세트를 제공합니다. 전반적 공급자 수준과 단일 속성 모두에서 유형 변환기를 변경할 수 있습니다. [AttributeConverter](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/AttributeConverter.html) API 참조에서 사용 가능한 변환기 목록을 확인할 수 있습니다.

### 속성에 대한 사용자 지정 변환기 설정
<a name="dynamodb-mapping-type-conv-anno"></a>

V1에서는 `@DynamoDBTypeConverted`로 getter 메서드에 주석을 달아 Java 속성 유형과 DynamoDB 속성 유형 간에 변환되는 클래스를 지정할 수 있습니다. 예를 들어 Java `Currency` 유형과 DynamoDB 문자열 간에 변환되는 `CurrencyFormatConverter`는 다음 코드 조각과 같이 적용할 수 있습니다.

```
@DynamoDBTypeConverted(converter = CurrencyFormatConverter.class)
public Currency getCurrency() { return currency; }
```

이전 코드 조각과 동일한 V2가 아래에 나와 있습니다.

```
@DynamoDbConvertedBy(CurrencyFormatConverter.class)
public Currency getCurrency() { return currency; }
```

**참고**  
V1에서는 속성 자체, 유형 또는 사용자 정의 주석에 주석을 적용할 수 있으며, V2는 주석을 getter에만 적용할 수 있도록 지원합니다.

### 유형 변환기 팩토리 또는 공급자 추가
<a name="dynamodb-mapping-type-conv-factory"></a>

V1에서는 고유한 유형 변환기 세트를 제공하거나 구성에 유형 변환기 팩토리를 추가하여 관심 있는 유형을 재정의할 수 있습니다. 유형 변환기 팩토리는 `DynamoDBTypeConverterFactory`를 확장하며, 기본 세트에 대한 참조를 가져와서 확장하면 재정의가 수행됩니다. 다음은 이 작업을 수행하는 방법을 보여주는 Java 코드 조각입니다.

```
DynamoDBTypeConverterFactory typeConverterFactory =
    DynamoDBTypeConverterFactory.standard().override()
        .with(String.class, CustomBoolean.class, new DynamoDBTypeConverter<String, CustomBoolean>() {
            @Override
            public String convert(CustomBoolean bool) {
                return String.valueOf(bool.getValue());
            }
            @Override
            public CustomBoolean unconvert(String string) {
                return new CustomBoolean(Boolean.valueOf(string));
            }}).build();
DynamoDBMapperConfig config =
    DynamoDBMapperConfig.builder()
        .withTypeConverterFactory(typeConverterFactory)
        .build();
DynamoDBMapper mapperWithTypeConverterFactory = new DynamoDBMapper(dynamo, config);
```

V2는 `@DynamoDbBean` 주석을 통해 유사한 기능을 제공합니다. 단일 `AttributeConverterProvider` 또는 순서대로 정리된 `AttributeConverterProvider`의 체인을 제공할 수 있습니다. 자체 속성 변환기 공급자 체인을 제공하는 경우 기본 변환기 공급자가 재정의되고 해당 속성 변환기를 사용하려면 체인에 포함되어야 함을 참고하시기 바랍니다.

```
@DynamoDbBean(converterProviders = {
   ConverterProvider1.class, 
   ConverterProvider2.class,
   DefaultAttributeConverterProvider.class})
public class Customer {
  ...
}
```

이 안내서의 [속성 변환](ddb-en-client-adv-features-conversion.md#ddb-en-client-adv-features-conversion-example) 섹션에는 V2에 대한 전체 예제가 포함되어 있습니다.

# SDK for Java 버전 1과 버전 2 간의 문자열 처리 차이점
<a name="dynamodb-migration-string-handling"></a>

V1과 V2는 DynamoDB로 데이터를 전송할 때 비어 있는 문자열을 다르게 처리합니다.
+ **V1**: DynamoDB로 전송하기 전에 비어 있는 문자열을 null 값으로 변환합니다(속성 없음).
+ **V2**: 비어 있는 문자열을 DynamoDB에 실제 비어 있는 문자열 값으로 전송합니다.

**중요**  
V2로 마이그레이션한 후 DynamoDB에 비어 있는 문자열을 저장하지 않으려면 사용자 지정 변환기를 구현해야 합니다. 사용자 지정 변환기가 없으면 V2는 비어 있는 문자열을 DynamoDB 항목에 실제 비어 있는 문자열 속성으로 저장합니다. 이는 이러한 속성을 완전히 생략하는 V1의 동작과 다릅니다.

**Example 비어 있는 문자열 속성을 null로 변환하는 V2용 사용자 지정 변환기**  

```
/**
 * Custom converter that maintains V1 behavior by converting empty strings to null values
 * when writing to DynamoDB, ensuring compatibility with existing data. No attribute will be saved to DynamoDB.
 */
public class NullifyEmptyStringConverter implements AttributeConverter<String> {
    @Override
    public AttributeValue transformFrom(String value) {
        if (value == null || value.isEmpty()) {
            return AttributeValue.builder().nul(true).build();
        }
        return AttributeValue.builder().s(value).build();
    }

    @Override
    public String transformTo(AttributeValue attributeValue) {
        if (attributeValue.nul()) {
            return null;
        }
        return attributeValue.s();
    }

    @Override
    public EnhancedType<String> type() {
        return EnhancedType.of(String.class);
    }

    @Override
    public AttributeValueType attributeValueType() {
        return AttributeValueType.S;
    }
}

// V2 usage:
@DynamoDbBean
public class Customer {
    private String name;

    @DynamoDbConvertedBy(NullifyEmptyStringConverter.class)
    public String getName() {
        return name;
    }
}
```



# SDK for Java 버전 1과 버전 2의 낙관적 잠금 차이점
<a name="dynamodb-migrate-optimstic-locking"></a>

V1과 V2 모두 bean 클래스에 하나의 속성을 표시하여 버전 번호를 저장하는 속성 주석으로 낙관적 잠금을 구현합니다.


**낙관적 잠금 동작의 차이점**  

|  | V1 | V2 | 
| --- | --- | --- | 
| bean 클래스 주석 | @DynamoDBVersionAttribute | @DynamoDbVersionAttribute(V2는 소문자 ‘b’ 사용) | 
| 초기 저장 | 버전 번호 속성은 1로 설정됩니다. |  `@DynamoDbVersionAttribute(startAt = X)`로 설정된 버전 속성의 시작 값입니다. 기본값은 0입니다.  | 
| 업데이트 | 조건부 확인에서 업데이트 중인 객체의 버전 번호가 데이터베이스의 번호와 일치하는지 확인하면 버전 번호 속성이 1씩 증가합니다. |  조건부 확인에서 업데이트 중인 객체의 버전 번호가 데이터베이스의 번호와 일치하는지 확인하면 버전 번호 속성이 증분합니다. `@DynamoDbVersionAttribute(incrementBy = X)`로 설정된 `incrementBy` 옵션에 따라 증분하는 버전 번호 속성입니다. 기본값은 1입니다.  | 
| Delete | DynamoDBMapper는 삭제 중인 객체의 버전 번호가 데이터베이스의 버전 번호와 일치하는지 조건부 확인을 추가합니다. |  V2는 삭제 작업에 대한 조건을 자동으로 추가하지 않습니다. 삭제 동작을 제어하려면 조건 표현식을 수동으로 추가해야 합니다. 다음 예제에서 `recordVersion`은 bean의 버전 속성입니다. <pre>// 1. Read the item and get its current version.<br />Customer item = customerTable.getItem(Key.builder().partitionValue("someId").build());<br />AttributeValue currentVersion = item.getRecordVersion();<br /><br />// 2. Create conditional delete with the `currentVersion` value.<br />DeleteItemEnhancedRequest deleteItemRequest =<br />    DeleteItemEnhancedRequest.builder()<br />       .key(KEY)<br />       .conditionExpression(Expression.builder()<br />           .expression("recordVersion = :current_version_value")<br />           .putExpressionValue(":current_version_value", currentVersion)<br />           .build()).build();<br /><br />customerTable.deleteItem(deleteItemRequest);</pre>  | 
| 조건 확인을 사용한 트랜잭션 쓰기 | addConditionCheck 메서드에서 @DynamoDBVersionAttribute로 주석이 달린 bean 클래스는 사용할 수 없습니다. | transactWriteItems 요청에 대해 addConditionCheck 빌더 메서드의 @DynamoDbVersionAttribute 주석과 함께 bean 클래스를 사용할 수 있습니다. | 
| 비활성화 | 낙관적 잠금은  DynamoDBMapperConfig.SaveBehavior 열거 값을 UPDATE에서 CLOBBER로 변경하면 사용 해제할 수 있습니다. |  `@DynamoDbVersionAttribute` 주석을 사용하지 마세요.  | 

# SDK for Java 버전 1과 버전 2 간의 유용한 setter 차이점
<a name="dynamodb-migrate-fluent-setters"></a>

V1용 DynamoDB 매핑 API에서 유용한 setter와 버전 2.30.29 이후 V2에서 POJO를 사용할 수 있습니다.

예를 들어 다음 POJO는 `setName` 메서드에서 `Customer` 인스턴스를 반환합니다.

```
// V1

@DynamoDBTable(tableName ="Customer")
public class Customer{
  private String name;
  // Other attributes and methods not shown.
  public Customer setName(String name){
     this.name = name;
     return this;
  }
}
```

그러나 2.30.29 이전의 V2 버전을 사용하는 경우 `setName`은 `name` 값이 `null`인 `Customer` 인스턴스를 반환합니다.

```
// V2 prior to version 2.30.29.

@DynamoDbBean
public class Customer{
  private String name;
  // Other attributes and methods not shown.
  public Customer setName(String name){ 
     this.name = name;
     return this;  // Bug: returns this instance with a `name` value of `null`.
  }
}
```

```
// Available in V2 since version 2.30.29.

@DynamoDbBean
public class Customer{
  private String name;
  // Other attributes and methods not shown.
  public Customer setName(String name){ 
     this.name = name;
     return this;  // Returns this instance for method chaining with the `name` value set.
  }
}
```

# 버전 1과 버전 2 간의 API 차이점 문서화 AWS SDK for Java
<a name="dynamodb-mapping-document-api"></a>

문서 API는 DynamoDB 테이블에서 JSON 형식 문서를 단일 항목으로 사용할 수 있도록 지원합니다. V1 문서 API는 V2에 해당 API가 있지만, V1처럼 문서 API에 별도의 클라이언트를 사용하는 대신, V2에서는 DynamoDB 향상된 클라이언트에 문서 API 기능을 통합했습니다.

V1에서 [https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Item.html](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Item.html) 클래스는 DynamoDB 테이블의 비정형 레코드를 나타냅니다. V2에서 비정형 레코드는 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/EnhancedDocument.html) 클래스의 인스턴스로 표시됩니다. 프라이머리 키는 V2의 테이블 스키마와 V1의 항목 자체에 정의되어 있습니다.

아래 테이블에서는 V1과 V2의 문서 API를 비교합니다.


| 사용 사례: | V1 | V2 | 
| --- |--- |--- |
| Create a document client |  <pre>AmazonDynamoDB client = ... //Create a client.<br />DynamoDB documentClient = new DynamoDB(client);</pre>  |  <pre>// The V2 Document API uses the same DynamoDbEnhancedClient<br />// that is used for mapping POJOs.<br />DynamoDbClient standardClient = ... //Create a standard client.<br />DynamoDbEnhancedClient enhancedClient = ... // Create an enhanced client.<br /></pre>  | 
| Reference a table |  <pre>Table documentTable = docClient.documentClient("Person");</pre>  |  <pre>DynamoDbTable<EnhancedDocument> documentTable = enhancedClient.table("Person",  <br />        TableSchema.documentSchemaBuilder()<br />              .addIndexPartitionKey(TableMetadata.primaryIndexName(),"id", AttributeValueType.S)<br />              .attributeConverterProviders(AttributeConverterProvider.defaultProvider())<br />              .build());</pre>  | 
| **Work with semi-structured data** | 
| --- |
| Put item |  <pre>Item item = new Item()<br />      .withPrimaryKey("id", 50)<br />      .withString("firstName", "Shirley");<br />PutItemOutcome outcome = documentTable.putItem(item);</pre>  |  <pre>EnhancedDocument personDocument = EnhancedDocument.builder()<br />        .putNumber("id", 50)<br />        .putString("firstName", "Shirley")<br />        .build();<br />documentTable.putItem(personDocument);</pre>  | 
| Get item |  <pre>GetItemOutcome outcome = documentTable.getItemOutcome( "id", 50);<br />Item personDocFromDb = outcome.getItem();<br />String firstName = personDocFromDb.getString("firstName");<br /></pre>  |  <pre>EnhancedDocument personDocFromDb = documentTable<br />        .getItem(Key.builder()<br />            .partitionValue(50)<br />            .build()); <br />String firstName = personDocFromDb.getString("firstName");<br /></pre>  | 
| **Work with JSON items** | 
| --- |
| Convert a JSON structure to use it with the Document API |  <pre>// The 'jsonPerson' identifier is a JSON string. <br />Item item = new Item().fromJSON(jsonPerson);</pre>  |  <pre>// The 'jsonPerson' identifier is a JSON string.<br />EnhancedDocument document = EnhancedDocument.builder()<br />        .json(jsonPerson).build());</pre>  | 
| Put JSON |  <pre>documentTable.putItem(item)</pre>  |  <pre>documentTable.putItem(document);</pre>  | 
| Read JSON |  <pre>GetItemOutcome outcome = //Get item.<br />String jsonPerson = outcome.getItem().toJSON();</pre>  |  <pre>String jsonPerson = documentTable.getItem(Key.builder()<br />        .partitionValue(50).build())<br />        .fromJson();</pre>  | 

## 문서 API에 대한 API 참조 및 안내서
<a name="dynamodb-mapping-document-api-ref"></a>


|  | V1 | V2 | 
| --- | --- | --- | 
| API 참조 | [API 참조](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/package-summary.html) | [API 참조](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/document/package-summary.html) | 
| 문서 안내서 | [Amazon DynamoDB 개발자 안내서](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/JavaDocumentAPIItemCRUD.html) | [향상된 문서 API](ddb-en-client-doc-api.md)(이 안내서) | 

# V1 Xpec API에서 V2 표현식 API
<a name="ddb-v1-xspec-migrate"></a>

문서 중심 데이터로 작업할 표현식을 만드는 데 도움이 되는 V1에서 사용할 수 있는 표현식 사양(Xspec) API는 V2에서 사용할 수 없습니다. V2는 문서 중심 데이터와 object-to-item 매핑 데이터 모두에서 작동하는 표현식 API를 사용합니다.


****  

|  | V1 | V2 | 
| --- | --- | --- | 
| API 이름 | 표현식 사양(Xspec) API | 표현식 API | 
| 함께 작동 | [updateItem](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Table.html#updateItem-java.lang.String-java.lang.Object-com.amazonaws.services.dynamodbv2.xspec.UpdateItemExpressionSpec-) 및 [scan](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Table.html#scan-com.amazonaws.services.dynamodbv2.xspec.ScanExpressionSpec-) 등 문서 API [테이블](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/document/Table.html) 클래스의 메서드 |  DynamoDB 향상된 클라이언트의 두 API: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/ddb-v1-xspec-migrate.html) [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) 인스턴스를 획득한 후 두 유형의 API에 대해 다음을 수행합니다. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/ddb-v1-xspec-migrate.html) 요청 객체를 만들 때 `DynamoDbTable` 메서드에서 표현식을 사용합니다. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryEnhancedRequest.Builder.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/enhanced/dynamodb/model/QueryEnhancedRequest.Builder.html)의 `filterExpression` 메서드에서의 예제  | 
| 리소스 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/ddb-v1-xspec-migrate.html)  | 이 Java 개발자 안내서의 [표현식 정보](ddb-en-client-expressions.md) | 

# 암호화 라이브러리 마이그레이션
<a name="ddb-encryption-lib-migrate"></a>

DynamoDB가 Java SDK의 V2로 작동하도록 암호화 라이브러리를 마이그레이션하는 방법에 대한 자세한 내용은 [Amazon DynamoDB Encryption Client 개발자 안내서](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/ddb-java-migrate.html)를 참조하세요.

# 버전 1에서 버전 2로 자동 Amazon SQS 요청 배치 처리 변경 사항
<a name="migration-sqs-auto-batching"></a>

이 주제에서는 AWS SDK for Java의 버전 1과 버전 2 간에 Amazon SQS에 대한 자동 요청 배치 처리의 변경 사항을 자세히 설명합니다.

## 높은 수준의 변경 사항
<a name="migration-sqs-auto-batching-high-level-changes"></a>

 AWS SDK for Java 1.x는 요청 일괄 처리를 위해 명시적으로 초기화해야 하는 별도의 `[AmazonSQSBufferedAsyncClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sqs/buffered/AmazonSQSBufferedAsyncClient.html)` 클래스를 사용하여 클라이언트 측 버퍼링을 수행합니다.

는를 사용하여 버퍼링 기능을 AWS SDK for Java 2.x 간소화하고 개선합니다`[SqsAsyncBatchManager](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html)`. 이 인터페이스의 구현은 표준 `[SqsAsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/SqsAsyncClient.html)`와 직접 통합된 자동 요청 배치 처리 기능을 제공합니다. v2의 `SqsAsyncBatchManager`에 대해 알아보려면 이 안내서의 [에서 Amazon SQS에 자동 요청 일괄 처리 사용 AWS SDK for Java 2.x](sqs-auto-batch.md) 주제를 참조하세요.


| 변경 | v1 |  v2 | 
| --- | --- | --- | 
|    Maven 종속성  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>com.amazonaws</groupId><br />            <artifactId>aws-java-sdk-bom</artifactId><br />            <version>1.12.7821</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-java-sdk-sqs</artifactId><br />    </dependency><br /></dependencies><br /></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.31.152</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>sqs</artifactId><br />    </dependency><br /></dependencies></pre>  | 
| 패키지 이름 | com.amazonaws.services.sqs.buffered | software.amazon.awssdk.services.sqs.batchmanager | 
| 클래스 이름 |  `[AmazonSQSBufferedAsyncClient](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sqs/buffered/AmazonSQSBufferedAsyncClient.html)`  | [SqsAsyncBatchManager](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.html) | 

1 [최신 버전](https://central.sonatype.com/artifact/com.amazonaws/aws-java-sdk-bom). 2 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom).

## 자동 SQS 요청 배치 처리 사용
<a name="migration-sqs-auto-batching-using"></a>


| 변경 | v1 |  v2 | 
| --- | --- | --- | 
| 배치 관리자 만들기 |  <pre>AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();<br />AmazonSQSAsync bufferedSqs = new <br />            AmazonSQSBufferedAsyncClient(sqsAsync);</pre>  |  <pre>SqsAsyncClient asyncClient = SqsAsyncClient.create();<br />SqsAsyncBatchManager sqsAsyncBatchManager = <br />            asyncClient.batchManager();</pre>  | 
| 사용자 지정 구성을 사용하여 배치 관리자 만들기 |  <pre>AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();<br /><br />QueueBufferConfig queueBufferConfig = new QueueBufferConfig()<br />        .withMaxBatchOpenMs(200)<br />        .withMaxBatchSize(10)<br />        .withMinReceiveWaitTimeMs(1000)<br />        .withVisibilityTimeoutSeconds(20)<br />        .withReceiveMessageAttributeNames(messageAttributeValues);<br /><br />AmazonSQSAsync bufferedSqs = <br />        new AmazonSQSBufferedAsyncClient(sqsAsync, queueBufferConfig);</pre>  |  <pre>BatchOverrideConfiguration batchOverrideConfiguration = <br />    BatchOverrideConfiguration.builder()<br />        .sendRequestFrequency(Duration.ofMillis(200))<br />        .maxBatchSize(10)<br />        .receiveMessageMinWaitDuration(Duration.ofMillis(1000))<br />        .receiveMessageVisibilityTimeout(Duration.ofSeconds(20))<br />        .receiveMessageSystemAttributeNames(messageSystemAttributeNames)<br />        .receiveMessageAttributeNames(messageAttributeValues)<br />        .build();<br /><br />SqsAsyncBatchManager sqsAsyncBatchManager = SqsAsyncBatchManager.builder()<br />        .overrideConfiguration(batchOverrideConfiguration)<br />        .client(SqsAsyncClient.create())<br />        .scheduledExecutor(Executors.newScheduledThreadPool(8))<br />        .build();</pre>  | 
| 메시지 전송 |  <pre>Future<SendMessageResult> sendResultFuture = <br />        bufferedSqs.sendMessageAsync(new SendMessageRequest()<br />                .withQueueUrl(queueUrl)<br />                .withMessageBody(body));</pre>  |  <pre>CompletableFuture<SendMessageResponse> sendCompletableFuture = <br />        sqsAsyncBatchManager.sendMessage(<br />                SendMessageRequest.builder()<br />                        .queueUrl(queueUrl)<br />                        .messageBody(body)<br />                        .build());</pre>  | 
| 메시지 삭제 |  <pre>Future<DeleteMessageResult> deletResultFuture =<br />        bufferedSqs.deleteMessageAsync(new DeleteMessageRequest()<br />                .withQueueUrl(queueUrl));</pre>  |  <pre>CompletableFuture<DeleteMessageResponse> deleteResultCompletableFuture<br />        = sqsAsyncBatchManager.deleteMessage(<br />                DeleteMessageRequest.builder()<br />                        .queueUrl(queueUrl)<br />                        .build());</pre>  | 
| 메시지의 표시 여부 변경 |  <pre>Future<ChangeMessageVisibilityResult> changeVisibilityResultFuture =<br />        bufferedSqs.changeMessageVisibilityAsync<br />                (new ChangeMessageVisibilityRequest()<br />                        .withQueueUrl(queueUrl)<br />                        .withVisibilityTimeout(20));</pre>  |  <pre>CompletableFuture<ChangeMessageVisibilityResponse> changeResponseCompletableFuture<br />        = sqsAsyncBatchManager.changeMessageVisibility(<br />                ChangeMessageVisibilityRequest.builder()<br />                        .queueUrl(queueUrl)<br />                        .visibilityTimeout(20)<br />                        .build());</pre>  | 
| 메시지 수신 |  <pre>ReceiveMessageResult receiveResult =<br />        bufferedSqs.receiveMessage(<br />                new ReceiveMessageRequest()<br />                        .withQueueUrl(queueUrl));</pre>  |  <pre>CompletableFuture<ReceiveMessageResponse> <br />        responseCompletableFuture = sqsAsyncBatchManager.receiveMessage(<br />                ReceiveMessageRequest.builder()<br />                        .queueUrl(queueUrl)<br />                        .build());</pre>  | 

## 비동기식 반환 유형 차이점
<a name="migration-sqs-auto-batching-asyc-return-type"></a>


| 변경 | v1 |  v2 | 
| --- | --- | --- | 
| 반환 타입 | Future<ResultType> | CompletableFuture<ResponseType> | 
| 콜백 메커니즘 | 별도의 onSuccess 및 onError 메서드가 있는 AsyncHandler 필요 | whenComplete(), thenCompose(), thenApply() 등 JDK에서 제공하는 CompletableFuture API 사용 | 
| 예외 처리 | AsyncHandler\$1onError() 메서드 사용 | exceptionally(), handle(), whenComplete() 등 JDK에서 제공하는 CompletableFuture API 사용 | 
| 취소 | Future.cancel()을 통한 기본 지원 | 상위 CompletableFuture를 취소하면 체인의 모든 종속 future 자동 취소 | 

## 비동기식 완료 처리 차이점
<a name="migration-sqs-auto-batching-asyc-completion-handling"></a>


| 변경 | v1 |  v2 | 
| --- | --- | --- | 
| 응답 핸들러 구현 |  <pre>Future<ReceiveMessageResult> future = bufferedSqs.receiveMessageAsync(<br />        receiveRequest,<br />        new AsyncHandler<ReceiveMessageRequest, ReceiveMessageResult>() {<br />            @Override<br />            public void onSuccess(ReceiveMessageRequest request, <br />                              ReceiveMessageResult result) {<br />                List<Message> messages = result.getMessages();<br />                System.out.println("Received " + messages.size() + " messages");<br />                for (Message message : messages) {<br />                    System.out.println("Message ID: " + message.getMessageId());<br />                    System.out.println("Body: " + message.getBody());<br />                }<br />            }<br /><br />            @Override<br />            public void onError(Exception e) {<br />                System.err.println("Error receiving messages: " + e.getMessage());<br />                e.printStackTrace();<br />            }<br />        }<br />);</pre>  |  <pre>CompletableFuture<ReceiveMessageResponse> completableFuture = sqsAsyncBatchManager<br />               .receiveMessage(ReceiveMessageRequest.builder()<br />               .queueUrl(queueUrl).build())<br />        .whenComplete((receiveMessageResponse, throwable) -> {<br />            if (throwable != null) {<br />                System.err.println("Error receiving messages: " + throwable.getMessage());<br />                throwable.printStackTrace();<br />            } else {<br />                List<Message> messages = receiveMessageResponse.messages();<br />                System.out.println("Received " + messages.size() + " messages");<br />                for (Message message : messages) {<br />                    System.out.println("Message ID: " + message.messageId());<br />                    System.out.println("Body: " + message.body());<br />                }<br />            }<br />        });</pre>  | 

## 주요 구성 파라미터
<a name="migration-sqs-auto-batching-params"></a>


****  

| 파라미터 | v1 |  v2 | 
| --- | --- | --- | 
| 최대 배치 크기 | maxBatchSize(배치당 기본 요청 10개) | maxBatchSize(배치당 기본 요청 10개) | 
| 배치 대기 시간 | maxBatchOpenMs(기본값 200ms) | sendRequestFrequency(기본값 200ms) | 
| 표시 제한 시간 | visibilityTimeoutSeconds(대기열 기본값의 경우 -1) | receiveMessageVisibilityTimeout(기본 대기열) | 
| 최소 대기 시간 | longPollWaitTimeoutSeconds(longPoll이 true인 경우 20초) | receiveMessageMinWaitDuration(기본값 50ms) | 
| 메시지 속성 | ReceiveMessageRequest를 사용하여 설정 | receiveMessageAttributeNames(기본적으로 없음) | 
| 시스템 속성 | ReceiveMessageRequest를 사용하여 설정 | receiveMessageSystemAttributeNames(기본적으로 없음) | 
| 긴 폴링 | longPoll(기본값 true) | 서버가 메시지를 보낼 때까지 대기 중인 열린 연결을 방지하기 위해 지원되지 않음 | 
| 긴 폴링의 최대 대기 시간 | longPollWaitTimeoutSeconds(기본값 20초) | 서버가 메시지를 보낼 때까지 대기 중인 열린 연결을 방지하기 위해 지원되지 않음 | 
| 클라이언트 측에서 미리 가져와서 저장하는 수신 배치의 최대 개수 | maxDoneReceiveBatches(배치 10개) | 내부적으로 처리되므로 지원되지 않음 | 
| 동시에 처리되는 최대 활성 아웃바운드 배치 수 | maxInflightOutboundBatches(기본값 배치 5개) | 내부적으로 처리되므로 지원되지 않음 | 
| 동시에 처리되는 최대 활성 수신 배치 수 | maxInflightReceiveBatches(기본값 배치 10개) | 내부적으로 처리되므로 지원되지 않음 | 