

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

# 버전 1.x에서 2.x로 마이그레이션 AWS SDK for Java
<a name="migration"></a>

The AWS SDK for Java 2.x는 Java 8 이상을 기반으로 구축된 1.x 코드 베이스의 주요 재작성입니다. 일관성 향상, 사용 편의성, 강력한 불변성 등 많은 업데이트가 포함되어 있습니다. 이 단원에서는 버전 2.x의 새로운 주요 기능을 설명하고 코드를 1.x에서 버전 2.x로 마이그레이션하는 방법에 대한 지침을 제공합니다.

**Topics**
+ [버전 2의 새 기능](#migration-whats-new)
+ [1.x 클라이언트를 사용하여 애플리케이션 찾기](migration-find-apps-using-v1.md)
+ [마이그레이션 방법](migration-howto.md)
+ [1.x와 2.x의 차이점](migration-whats-different.md)
+ [Java용 SDK 1.x와 2.x를 나란히 사용](migration-side-by-side.md)

## 버전 2의 새 기능
<a name="migration-whats-new"></a>
+ 고유한 HTTP 클라이언트를 구성할 수 있습니다. [HTTP 전송 구성](http-configuration.md)을 참조하세요.
+ 비동기식 클라이언트에는 비차단 I/O 지원 및 `CompletableFuture` 객체 반환 기능이 있습니다. [비동기 프로그래밍](asynchronous.md)을 참조하세요.
+ 여러 페이지를 반환하는 작업에는 자동으로 페이지가 매겨진 응답이 있습니다. 이렇게 하면 후속 페이지를 찾아 가져올 필요 없이 응답으로 수행할 작업에 대한 코드를 집중할 수 있습니다. [페이지 매김](pagination.md)을 참조하세요.
+  AWS Lambda 함수의 SDK 시작 시간 성능이 개선되었습니다. [SDK 시작 시간 성능 개선](lambda-optimize-starttime.md)을 참조하세요.
+ 버전 2.x는 요청을 생성하는 새로운 속기 방법을 지원합니다.  
**Example**  

  ```
  dynamoDbClient.putItem(request -> request.tableName(TABLE))
  ```

새 기능에 대한 자세한 내용과 특정 코드 예제를 보려면 이 가이드의 다른 단원을 참조하세요.
+  [빠른 시작](get-started.md) 
+  [설정](setup.md) 
+  [the AWS SDK for Java 2.x의 코드 예제 ](java_code_examples.md)
+  [SDK 사용](using.md) 
+  [에 대한 보안 AWS SDK for Java](security.md) 

# AWS SDK for Java 1.x 클라이언트를 사용하여 애플리케이션 찾기
<a name="migration-find-apps-using-v1"></a>

로 마이그레이션하기 전에 환경에서 SDK for Java 1.x 클라이언트를 사용하는 애플리케이션을 식별 AWS SDK for Java 2.x해야 합니다. CloudTrail 로그를 사용하여 SDK 사용량을 추적하거나, 애플리케이션 로그에서 사용 중단 경고를 검색하거나, 소스 코드 및 빌드 구성을 검사하거나, 배포 가능한 Java 아티팩트를 검사할 수 있습니다. 환경에서 사용 가능한 메서드를 사용합니다.

## CloudTrail Lake를 사용하여 1.x 클라이언트가 있는 애플리케이션 찾기
<a name="migration-find-v1-apps-with-cloudtrail"></a>

AWS CloudTrail Lake를 사용하면 CloudTrail에서 기록한 이벤트를 쿼리할 수 있습니다. 다음 단계에 따라 애플리케이션에서 사용하는 SDK 버전을 식별하는 데이터 레이크를 만듭니다.

1. CloudTrail 데이터 레이크를 만듭니다. 이벤트 데이터 스토어를 만들려면 [사용 설명서](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/query-event-data-store.html)를 참조하세요.

1. 데이터 스토어를 만든 후 레코드 콘텐츠를 검사합니다. 레코드 본문에는 요청된 작업, 타이밍 및 위치를 결정하는 필드가 포함되어 있습니다. 자세한 내용은 [CloudTrail 레코드 콘텐츠에 대한 사용 설명서](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)를 참조하세요.

1. 데이터에 대해 쿼리를 실행합니다. [사용 설명서에 따라 쿼리하고 쿼리 결과를 저장](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/query-run-query.html)합니다.

각 레코드의 *userAgent* 필드에는 요청된 SDK 버전이 포함되어 있습니다. 이 필드를 사용하여 SDK for Java 1.x를 사용하는 애플리케이션을 식별합니다.

다음 샘플 쿼리는 EventDatastoreID에 대해 2025년 6월 17일부터 SDK for Java 1.x로 만든 사용자 애플리케이션 및 타사 도구의 모든 요청을 찾습니다. `sample-Data-Store-Id` 

```
select userIdentity, eventSource, awsRegion,
    eventName, eventType, eventTime, userAgent,
    requestParameters, sourceIPAddress
 from sample-Data-Store-Id
where eventTime > '2025-06-17 00:00:00'
and userAgent like '%aws-sdk-java/1.%'
and userAgent not like '%aws-internal/%'
order by eventTime desc
```

쿼리 결과의 이벤트 콘텐츠 예제는 다음과 같습니다.

```
{
    "userIdentity": "{
         "type": "IAMUser",
         "principalId": "AIDAJ45Q7YFFAREXAMPLE",
         "arn": "arn:aws:iam::123456789012:user/Alice",
         "accountId": "123456789012",
         "accessKeyId": "",
         "userName": "Alice"
    }",
    "eventSource": "dynamodb.amazonaws.com",
    "awsRegion": "us-west-2",
    "eventName": "ListTables",
    "eventType": "AwsApiCall",
    "eventTime": "2025-07-01 02:23:52.000",
    "userAgent": "aws-sdk-java/1.12.746 Linux/5.10.240 OpenJDK/11.0.25+9-LTS ...",
    "requestParameters": "",
    "sourceIPAddress": "12.345.6.78"
}
```

이 정보를 사용하여 요청이 이루어진 때와 위치를 확인할 수 있습니다.

이 예제에서 DynamoDB `ListTables` 요청은 Alice라는 이름의 IAM 사용자 자격 증명을 사용하여 IP 주소(`12.345.6.78`)에서 `2025-07-01 02:23:52 (UTC)`에 생성됐습니다. *userAgent* 필드의 값은 요청이 JDK 11`1.12.746`이 설치된 Linux 시스템의 AWS SDK for Java 버전을 사용하여 이루어졌음을 보여줍니다.

 AWS CloudTrail 이벤트 레코드의 필드에 대한 설명은 [관리, 데이터 및 네트워크 활동 이벤트에 대한 CloudTrail 레코드 콘텐츠를 ](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)참조하세요.

계정에서 CloudTrail이 활성화되지 않은 경우 조직의 AWS 계정 관리자에게 문의하여 활성화하거나 다음 섹션에 설명된 대체 방법 중 하나를 사용합니다.

CloudTrail Lake는 수집된 데이터와 쿼리당 스캔된 데이터에 대해 요금을 부과합니다. 비용을 최소화하려면 쿼리를 특정 시간 범위 및 리전으로 필터링합니다. 현재 요금은 [AWS CloudTrail 요금](https://aws.amazon.com/cloudtrail/pricing/)을 참조하십시오.

## SDK 사용 중단에 대한 애플리케이션 경고 수준 로그 검색
<a name="migration-find-v1-apps-log-warning"></a>

버전 1.12.767(2024년 7월 30일 릴리스됨)부터 AWS SDK for Java 1.x는 애플리케이션 시작 시 사용 중단 경고를 내보냅니다. 애플리케이션 로그에서이 경고를 검색하여 SDK for Java 1.x를 사용하는 애플리케이션과 호스트를 식별할 수 있습니다.

경고의 정확한 표현은 SDK 버전에 따라 다릅니다.
+ 버전 1.12.767\$11.12.796:

  `WARNING: The AWS SDK for Java 1.x entered maintenance mode starting July 31, 2024 and will reach end of support on December 31, 2025...`
+ 버전 1.12.797 이상:

  `WARNING: The AWS SDK for Java 1.x reached end of support on December 31, 2025...`

후행은 경고 메시지가 추가 텍스트로 계속됨을 `...` 나타냅니다. 공통 접두사를 검색`The AWS SDK for Java 1.x`하여 경고 버전을 찾을 수 있습니다.

다음 예제에서는를 사용하여이 경고를 검색하는 방법을 보여줍니다`grep`.

```
grep -r "The AWS SDK for Java 1.x" /path/to/your/application/logs/
```

경고가 발견되면 `grep` 명령은 일치하는 로그 줄을 인쇄합니다. 경고가 없으면 애플리케이션이 Java 1.x용 SDK를 사용하지 않거나 1.12.767 이전 버전을 사용합니다. 이 경우이 문서에 설명된 다른 방법 중 하나를 사용합니다.

## 소스 코드 및 종속성 검색
<a name="migration-find-v1-apps-source-code"></a>

코드베이스를 검색하고 구성 파일을 빌드하여 AWS SDK for Java 1.x에 대한 참조를 찾을 수 있습니다. 키 식별자는 모든 SDK for Java 1.x 아티팩트에서 사용하는 `com.amazonaws` 그룹 ID입니다.

다음 예제에서는를 사용하여 일반적인 Java 프로젝트 파일에서 `com.amazonaws` 참조를 검색`grep`하는 방법을 보여줍니다.

**예: Java 소스 파일에서 SDK for Java 1.x 가져오기 검색(프로젝트 루트 디렉터리에서 실행)**

```
grep -r "import com.amazonaws" --include="*.java" .
```

출력 예시:

```
src/main/java/com/example/App.java:import com.amazonaws.services.s3.AmazonS3;
```

**참고**  
`com.amazonaws` 패키지는와 같이 SDK for Java 1.x에 속하지 않는 라이브러리에서도 사용됩니다`aws-lambda-java-core`. Java 1.x용 SDK에서 가져오기를 확인하려면 , `pom.xml` `build.gradle`또는 종속성 관리 구성의 해당 아티팩트 ID가 로 시작하는지 확인합니다`aws-java-sdk-`.

**예: SDK for Java 1.x 종속성을 위한 Maven `pom.xml` 파일 검색(프로젝트 루트 디렉터리에서 실행)**

```
grep -r "com.amazonaws" --include="pom.xml" .
```

출력 예시:

```
pom.xml:    <groupId>com.amazonaws</groupId>
```

**예: SDK for Java 1.x 종속성을 위한 Gradle 빌드 파일 검색(프로젝트 루트 디렉터리에서 실행)**

```
grep -r "com.amazonaws:aws-java-sdk" --include="*.gradle" .
```

출력 예시:

```
build.gradle:    implementation 'com.amazonaws:aws-java-sdk-s3:1.12.xxx'
```

위의 `grep` 명령은 소스 및 빌드 파일에서 직접 선언된 Java 1.x용 SDK 참조를 식별합니다. 하지만 애플리케이션 자체가 SDK에 의존하는 타사 라이브러리를 통해 Java 1.x용 SDK에 전이적으로 의존할 수도 있습니다. 빌드 도구의 종속성 트리를 사용하여 Java 1.x용 직접 및 전이 SDK 종속성을 모두 찾을 수 있습니다. 빌드 시스템과 일치하는 예제를 선택합니다.

**예: Maven을 사용하여 Java 1.x용 전이적 SDK 종속성을 모두 찾습니다(프로젝트 루트 디렉터리에서 실행).**

```
mvn dependency:tree -Dincludes=com.amazonaws
```

출력 예시:

```
[INFO] com.example:my-application:jar:1.0-SNAPSHOT
[INFO] +- com.amazonaws:aws-java-sdk-s3:jar:1.12.746:compile
[INFO] |  \- com.amazonaws:aws-java-sdk-core:jar:1.12.746:compile
[INFO] \- some.thirdparty:library:jar:2.3.1:compile
[INFO]    \- com.amazonaws:aws-java-sdk-dynamodb:jar:1.12.600:compile
```

`-Dincludes=com.amazonaws` 플래그는 트리를 필터링하여 SDK for Java 1.x 아티팩트만 표시합니다. 이 예제에서 `aws-java-sdk-s3`는 직접 종속성이지만에서 가져오는 전이적 종속성`aws-java-sdk-dynamodb`입니다`some.thirdparty:library`.

**예: Gradle을 사용하여 Java 1.x용 전이적 SDK 종속성을 모두 찾습니다(프로젝트 루트 디렉터리에서 실행).**

```
gradle dependencies --configuration runtimeClasspath | grep "com.amazonaws"
```

출력 예시:

```
+--- com.amazonaws:aws-java-sdk-s3:1.12.746
|    \--- com.amazonaws:aws-java-sdk-core:1.12.746
\--- com.amazonaws:aws-java-sdk-dynamodb:1.12.600
```

Gradle에는 Maven의와 동일한 기본 제공 종속성 필터가 `-Dincludes`없으므로 파이프스루가 가장 간단한 접근 방식`grep`입니다.

## 배포 가능한 Java 아티팩트 검사
<a name="migration-find-v1-apps-inspect-artifacts"></a>

배포 가능한 Java 아티팩트(JARs, WARs 또는 EARs)를 검사하여 애플리케이션과 함께 AWS SDK for Java 1.x가 패키징되었는지 확인할 수 있습니다. Java 아카이브 파일은 ZIP 형식 파일입니다. SDK for Java 1.x가 있는지 확인하려면 아카이브 `com/amazonaws/sdk/versionInfo.properties` 내에서 파일을 찾습니다. 이 파일은 `aws-java-sdk-core` 모듈에 포함되어 있으며 SDK 버전 번호를 포함합니다.

### `jar` 명령을 사용한 빠른 확인
<a name="migration-find-v1-apps-jar-command"></a>

모든 종속성 클래스가 최상위 수준에서 병합되는 uber-jar의 경우 아카이브 콘텐츠를 나열하고 버전 파일을 검색합니다.

다음 예제에서를 애플리케이션의 JAR 파일 경로`myapp.jar`로 바꿉니다.

```
jar -tf myapp.jar | grep 'versionInfo.properties'
```

SDK가 있는 경우 출력은 다음과 같습니다.

```
com/amazonaws/sdk/versionInfo.properties
```

환경에서 `jar` 명령을 사용할 수 없는 경우(예: JRE 전용 또는 최소 컨테이너 이미지) `unzip -l` 대신를 사용할 수 있습니다.

```
unzip -l myapp.jar | grep 'versionInfo.properties'
```

버전을 인쇄하려면:

```
unzip -p myapp.jar com/amazonaws/sdk/versionInfo.properties
```

출력 예시:

```
platform=java
version=1.12.xxx
```

**참고**  
위의 명령은 uber-jars에서 최상위 항목만 검색합니다. SDK 클래스는 얇은 JARs(종속성이 외부인 경우) 또는 중첩된 JARs(예: `lib/` 또는 아래의 WARs, EARs 또는 Lambda 패키지의 클래스) 내에서 찾을 수 없습니다`WEB-INF/lib/`. 씬 JARs 경우 빌드 구성(`pom.xml`, `build.gradle`) 또는 종속성 트리를 대신 확인합니다. 중첩된 JARs 경우 디스크로 추출하지 않고 ZIP 아카이브를 재귀적으로 읽을 수 있는 도구를 사용하여 번들링된 JARs을 검색합니다.

# 코드를 AWS SDK for Java 1.x에서 2.x로 마이그레이션하는 방법
<a name="migration-howto"></a>

몇 가지 방법으로 기존 SDK for Java 1.x 애플리케이션을 마이그레이션할 수 있습니다.

1. [마이그레이션 도구](migration-tool.md)를 사용한 자동 접근 방식

1. 1.x 가져오기를 2.x 가져오기로 점진적으로 대체하는 [수동 접근](migration-steps.md) 방식입니다.

먼저 마이그레이션 도구를 사용하는 것이 좋습니다. 1.x에서 2.x 코드로 일상적인 대체 작업의 대부분을 자동화합니다.

도구로 [모든 기능을 마이그레이션할 수 없으므로](migration-tool.md#migration-tool-limitations) 도구를 실행한 후 나머지 v1 코드를 검색해야 합니다. 도구를 통해 마이그레이션되지 않은 코드를 찾으면 [단계별 설명](migration-steps.md)(수동 접근 방식)을 따르고 [마이그레이션 가이드 문서](migration-whats-different.md)를 사용하여 마이그레이션을 완료합니다.

**Topics**
+ [마이그레이션 도구](migration-tool.md)
+ [단계별 설명](migration-steps.md)

# AWS SDK for Java 마이그레이션 도구
<a name="migration-tool"></a>

AWS SDK for Java는 SDK for Java 1.x(V1) 코드를 2.x(V2)로 마이그레이션하는 작업을 자동화하는 데 도움이 되는 마이그레이션 도구를 제공합니다. 이 도구는 오픈 소스, 소스 코드 리팩터링 도구인 [OpenRewrite](https://docs.openrewrite.org/)를 사용하여 마이그레이션을 수행합니다. OpenRewrite는 코드 수정 규칙(다른 명칭: ‘레시피’)을 사용하여 소스 코드를 V1에서 V2 구문 및 패턴으로 자동으로 업데이트합니다.

도구는 SDK 서비스 클라이언트 및 [S3 Transfer Manager](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferManager.html) 상위 수준 라이브러리에 대한 코드 수정 규칙을 지원합니다. V1의 [https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.html](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.html)에서 V2로의 [DynamoDB 향상된 클라이언트 API](dynamodb-enhanced-client.md)와 같은 다른 상위 수준 API에 대한 코드 수정 규칙은 지원되지 않습니다.

제한 사항에 대한 자세한 내용은 [이 페이지의 마지막 부분](#migration-tool-limitations)을 참조하세요. 수동 마이그레이션 단계에서 지원되지 않는 일반적인 코드 패턴의 자세한 예제는 [지원되지 않는 코드 패턴](migration-tool-unsupported-patterns.md)을 참조하세요.

## 마이그레이션 도구 사용
<a name="migration-tool-use"></a>

### Maven 프로젝트 마이그레이션
<a name="migration-tool-use-maven"></a>

아래 설명에 따라 [OpenRewrite Maven 플러그인 도구](https://docs.openrewrite.org/reference/rewrite-maven-plugin)를 사용하여 SDK for Java 1.x Maven 기반 프로젝트를 마이그레이션합니다.

1. Maven 프로젝트의 루트 디렉터리로 이동

   터미널(명령줄) 창을 열고 Maven 기반 애플리케이션의 루트 디렉터리로 이동합니다.

1. 플러그인의 `rewrite-maven-plugin` 명령 실행

   `dryRun` 및 `run`의 2가지 모드(Maven 목표) 중에서 선택할 수 있습니다.

   **`dryRun`**** 모드**

   `dryRun` 모드에서 플러그인은 콘솔 출력에 diff 로그를 생성하고 `target/rewrite` 폴더에 `rewrite.patch`라는 패치 파일을 생성합니다. 이 모드를 사용하면 소스 코드 파일을 변경하지 않으므로 변경할 내용을 미리 볼 수 있습니다.

   다음 예제에서는 `dryRun` 모드에서 플러그인을 호출하는 방법을 보여줍니다.

   ```
   mvn org.openrewrite.maven:rewrite-maven-plugin:<rewrite-plugin-version>*:dryRun \
     -Drewrite.recipeArtifactCoordinates=software.amazon.awssdk:v2-migration:<sdkversion>** \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   \$1*<rewrite-plugin-version>*을 이 [테스트 파일](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)에 표시된 `rewriteMavenPluginVersion` 값으로 교체합니다.

   \$1\$1*<sdkversion>*을 2.x SDK 버전으로 교체합니다. [Maven Central](https://central.sonatype.com/artifact/software.amazon.awssdk/v2-migration)에서 최신 버전을 확인하세요.
**중요**  
다른 버전이 작동하지 않을 수 있으므로 [테스트 파일](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)에 표시된 버전의 `rewrite-maven-plugin`을 사용해야 합니다.

   `dryRun` 모드의 콘솔 출력은 다음 출력과 유사해야 합니다.

   ```
   [WARNING] These recipes would make changes to project/src/test/resources/maven/before/pom.xml:
   [WARNING]     software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   [WARNING]         software.amazon.awssdk.v2migration.UpgradeSdkDependencies
   [WARNING]             org.openrewrite.java.dependencies.AddDependency: {groupId=software.amazon.awssdk, artifactId=apache-client, version=2.27.0, onlyIfUsing=com.amazonaws.ClientConfiguration}
   [WARNING]             org.openrewrite.java.dependencies.AddDependency: {groupId=software.amazon.awssdk, artifactId=netty-nio-client, version=2.27.0, onlyIfUsing=com.amazonaws.ClientConfiguration}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-bom, newGroupId=software.amazon.awssdk, newArtifactId=bom, newVersion=2.27.0}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-s3, newGroupId=software.amazon.awssdk, newArtifactId=s3, newVersion=2.27.0}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-sqs, newGroupId=software.amazon.awssdk, newArtifactId=sqs, newVersion=2.27.0}
   [WARNING] These recipes would make changes to project/src/test/resources/maven/before/src/main/java/foo/bar/Application.java:
   [WARNING]     software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   [WARNING]         software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
   [WARNING]             software.amazon.awssdk.v2migration.ConstructorToFluent
   [WARNING]         software.amazon.awssdk.v2migration.S3StreamingResponseToV2
   [WARNING]         software.amazon.awssdk.v2migration.ChangeSdkType
   [WARNING]         software.amazon.awssdk.v2migration.ChangeSdkCoreTypes
   [WARNING]             software.amazon.awssdk.v2migration.ChangeExceptionTypes
   [WARNING]                 org.openrewrite.java.ChangeType: {oldFullyQualifiedTypeName=com.amazonaws.AmazonClientException, newFullyQualifiedTypeName=software.amazon.awssdk.core.exception.SdkException}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRequestId(), newMethodName=requestId}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getErrorCode(), newMethodName=awsErrorDetails().errorCode}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getServiceName(), newMethodName=awsErrorDetails().serviceName}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getErrorMessage(), newMethodName=awsErrorDetails().errorMessage}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRawResponse(), newMethodName=awsErrorDetails().rawResponse().asByteArray}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRawResponseContent(), newMethodName=awsErrorDetails().rawResponse().asUtf8String}
   [WARNING]                 org.openrewrite.java.ChangeType: {oldFullyQualifiedTypeName=com.amazonaws.AmazonServiceException, newFullyQualifiedTypeName=software.amazon.awssdk.awscore.exception.AwsServiceException}
   [WARNING]         software.amazon.awssdk.v2migration.NewClassToBuilderPattern
   [WARNING]             software.amazon.awssdk.v2migration.NewClassToBuilder
   [WARNING]             software.amazon.awssdk.v2migration.V1SetterToV2
   [WARNING]         software.amazon.awssdk.v2migration.V1GetterToV2
   ...
   [WARNING]         software.amazon.awssdk.v2migration.V1BuilderVariationsToV2Builder
   [WARNING]         software.amazon.awssdk.v2migration.NewClassToBuilderPattern
   [WARNING]             software.amazon.awssdk.v2migration.NewClassToBuilder
   [WARNING]             software.amazon.awssdk.v2migration.V1SetterToV2
   [WARNING]         software.amazon.awssdk.v2migration.HttpSettingsToHttpClient
   [WARNING]         software.amazon.awssdk.v2migration.WrapSdkClientBuilderRegionStr
   [WARNING] Patch file available:
   [WARNING]     project/src/test/resources/maven/before/target/rewrite/rewrite.patch
   [WARNING] Estimate time saved: 20m
   [WARNING] Run 'mvn rewrite:run' to apply the recipes.
   ```

   **`run`**** 모드**

   플러그인을 `run` 모드에서 실행할 경우 디스크의 소스 코드를 수정하여 변경 사항을 적용합니다. 명령을 실행하기 전에 소스 코드의 백업이 있는지 확인합니다.

   다음 예제에서는 `run` 모드에서 플러그인을 호출하는 방법을 보여줍니다.

   ```
   mvn org.openrewrite.maven:rewrite-maven-plugin:<rewrite-plugin-version>*:run \
     -Drewrite.recipeArtifactCoordinates=software.amazon.awssdk:v2-migration:<sdkversion>** \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   \$1*<rewrite-plugin-version>*을 이 [테스트 파일](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)에 표시된 `rewriteMavenPluginVersionvalue`로 교체합니다.

   \$1\$1*<sdkversion>*을 2.x SDK 버전으로 교체합니다. [Maven Central](https://central.sonatype.com/artifact/software.amazon.awssdk/v2-migration)에서 최신 버전을 확인하세요.

   명령을 실행한 후 애플리케이션을 컴파일하고 테스트를 실행하여 변경 사항을 확인합니다.

### Gradle 프로젝트 마이그레이션
<a name="migration-tool-use-gradle"></a>

아래 설명에 따라 [OpenRewrite Gradle 플러그인](https://docs.openrewrite.org/reference/gradle-plugin-configuration) 도구를 사용하여 SDK for Java 1.x Gradle 기반 프로젝트를 마이그레이션합니다.

1. Gradle 프로젝트의 루트 디렉터리로 이동

   터미널(명령줄) 창을 열고 Gradle 기반 애플리케이션의 루트 디렉터리로 이동합니다.

1. Gradle init 스크립트 만들기

   디렉터리에 다음 콘텐츠로 `init.gradle`이라는 파일을 만듭니다.

   ```
   initscript {
       repositories {
           maven { url "https://plugins.gradle.org/m2" }
       }
       dependencies {
           classpath("org.openrewrite:plugin:<rewrite-plugin-version>*")
       }
   }
   
   rootProject {
       plugins.apply(org.openrewrite.gradle.RewritePlugin)
       dependencies {
           rewrite("software.amazon.awssdk:v2-migration:latest.release")
       }
   
       afterEvaluate {
           if (repositories.isEmpty()) {
               repositories {
                   mavenCentral()
               }
           }
       }
   }
   ```

   \$1*<rewrite-plugin-version>*을 이 [테스트 파일](https://github.com/aws/aws-sdk-java-v2/blob/master/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/gradle/before/init.gradle#L6)에 표시된 버전으로 교체합니다.

1. `rewrite` 명령 실행

   Maven 플러그인과 마찬가지로 `dryRun` 또는 `run` 모드에서 Gradle 플러그인을 실행할 수 있습니다.

   **`dryRun` 모드**

   다음 예제에서는 `dryRun` 모드에서 플러그인을 호출하는 방법을 보여줍니다.

   ```
   gradle rewriteDryRun --init-script init.gradle \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   **`run` 모드**

   다음 예제에서는 `run` 모드에서 플러그인을 호출하는 방법을 보여줍니다.

   ```
   gradle rewriteRun --init-script init.gradle \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

## 현재 제한 사항
<a name="migration-tool-limitations"></a>

마이그레이션은 V2와 동일하게 업데이트되는 코드 수정 규칙을 통해 대부분의 V1 코드를 지원하지만, 일부 클래스와 메서드는 적용되지 않습니다. 이러한 클래스 및 메서드의 경우 [단계별 설명](migration-steps.md)에 따라 코드를 수동으로 마이그레이션합니다.

일부 지원되지 않는 코드 수정 규칙의 경우 마이그레이션 도구는 다음으로 시작하는 주석을 추가할 수 있습니다.

```
/*AWS SDK for Java v2 migration: Transform for ...
```

주석 다음에 도구는 메서드 또는 클래스의 V2 버전의 일반 스터브를 출력합니다. 예를 들어 다음 출력에서 마이그레이션 도구는 V1 S3 클라이언트의 `setBucketLifecycleConfiguration` 메서드를 마이그레이션하려고 시도했습니다.

```
/*AWS SDK for Java v2 migration: Transform for setBucketLifecycleConfiguration method not supported. 
Please manually migrate your code by using builder pattern, update from BucketLifecycleConfiguration.Rule 
to LifecycleRule, StorageClass to TransitionStorageClass, and adjust imports and names.*/
s3.putBucketLifecycleConfiguration(
        PutBucketLifecycleConfigurationRequest.builder()
            .bucket(bucketName)
            .lifecycleConfiguration(BucketLifecycleConfiguration.builder()
                .build())
            .build());
```

아래 목록의 링크를 클릭하면 코드를 수동으로 마이그레이션하는 데 도움이 되는 마이그레이션 정보로 이동합니다.
+ [버전 1과 버전 2 간의 S3 클라이언트 차이점 AWS SDK for Java](migration-s3-client.md)
+ [S3 Transfer Manager](migration-s3-transfer-manager.md)(TransferManager)
+ [DynamoDB 객체 매핑](migration-ddb-mapper.md)(DynamoDBMapper)
+ [EC2 메타데이터 유틸리티](migration-imds.md)(EC2MetadataUtils)
+ [웨이터](migration-waiters.md)(AmazonDynamoDBWaiters)
+ [IAM 정책 빌더](migration-iam-policy-builder.md)(정책)
+ [CloudFront 사전 서명](migration-cloudfront-presigning.md)(CloudFrontUrlSigner, CloudFrontCookieSigner)
+ [S3 이벤트 알림](migration-s3-event-notification.md)(S3EventNotification)
+ SDK 지표 게시([1.x 설명서](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/generating-sdk-metrics.html), [2.x 설명서](metrics.md))
+ [지원되지 않는 코드 패턴](migration-tool-unsupported-patterns.md) - 수동 마이그레이션이 필요한 일반적인 코드 패턴의 세부 예제

# 마이그레이션 도구의 지원되지 않는 코드 패턴
<a name="migration-tool-unsupported-patterns"></a>

마이그레이션 도구는 대부분의 v1 코드를 v2로 자동 변환합니다. 그러나 일부 코드 패턴은 수동 마이그레이션이 필요합니다. 이 주제에서는 지원되지 않는 가장 일반적인 패턴의 세부 예제를 제공하고 이를 수동으로 변환하는 방법을 보여줍니다.

다음 패턴 목록이 전부는 아닙니다. 마이그레이션 도구를 실행한 후에도 코드가 컴파일되지 않으면 [단계별 마이그레이션 설명](migration-steps.md)에 따라 나머지 v1 코드를 수동으로 마이그레이션합니다.

## 파라미터를 사용하여 객체 생성자 요청
<a name="request-pojo-constructors"></a>

요청 POJO(Amazon S3 제외)의 경우 마이그레이션 도구는 setter 메서드만 변환합니다. 이 도구는 파라미터가 있는 생성자를 지원하지 않습니다.

**지원되는 패턴: setter를 사용하여 객체 요청(작성자 파라미터 없음)**

이전(원래 v1 코드):

```
import com.amazonaws.services.sqs.model.SendMessageRequest;

SendMessageRequest request = new SendMessageRequest().withMessageBody("Hello World");
request.setQueueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue");
```

이후(마이그레이션 도구 결과):

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;

SendMessageRequest request = SendMessageRequest.builder()
    .messageBody("Hello World").build();
request = request.toBuilder()
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue").build();
```

**지원되지 않는 패턴: 파라미터를 사용하여 객체 생성자 요청**

마이그레이션 도구는 파라미터가 있는 생성자를 변환할 수 없습니다.

수동 마이그레이션 전, 마이그레이션 도구 사용 후:

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest; // Import updated to v2.

// This pattern requires manual migration.
SendMessageRequest request = new SendMessageRequest(
    "https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", 
    "Hello World");
```

마이그레이션 도구는 가져오기를 v2로 변환하지만 생성자 코드는 변경되지 않고 빌더 패턴을 사용하려면 수동 업데이트가 필요합니다.

수동 마이그레이션 후:

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;

SendMessageRequest request = SendMessageRequest.builder()
    .messageBody("Hello World")
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue")
    .build();
```

## 개별 파라미터가 있는 서비스 클라이언트 메서드
<a name="service-client-method-overloads"></a>

마이그레이션 도구는 요청 객체(Amazon S3 제외) 대신 개별 파라미터를 사용하는 서비스 클라이언트 메서드를 변환할 수 없습니다.

이전(v1 코드):

```
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;

AmazonSQS sqs = new AmazonSQSClient();
// The following v1 method takes individual parameters.
sqs.sendMessage("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", "Hello World");
```

이후(마이그레이션 도구 결과 - 컴파일되지 않음):

```
import software.amazon.awssdk.services.sqs.SqsClient;  // Import updated to v2.
// No import statement for the v2 request POJO.

SqsClient sqs = SqsClient.builder().build();

// Does not compile–v2 methods only accept request POJOs.
sqs.sendMessage("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", "Hello World");
```

요청 객체를 사용하려면 메서드 인수를 수동으로 업데이트해야 합니다.

```
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.SendMessageRequest; // Add manually.

SqsClient sqs = SqsClient.builder().build();

// Corrected v2 code.
SendMessageRequest request = SendMessageRequest.builder()
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue")
    .messageBody("Hello World")
    .build();
sqs.sendMessage(request);
```

## 요청 제한 시간 메서드
<a name="request-pojo-timeout-configuration"></a>

마이그레이션 도구는 요청 객체에 제한 시간을 설정하는 메서드를 변환하지 않습니다.

이전(v1 코드):

```
import com.amazonaws.services.sqs.model.SendMessageRequest;

SendMessageRequest request = new SendMessageRequest();
request.setSdkRequestTimeout(7);
```

이후(마이그레이션 도구 결과 - 컴파일되지 않음):

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;  // Import updated to v2.

SendMessageRequest request = SendMessageRequest.builder().build();

// Does not compile.
request.setSdkRequestTimeout(7);
```

v2의 `overrideConfiguration` 메서드를 사용하려면 수동으로 마이그레이션해야 합니다.

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
import java.time.Duration;

SendMessageRequest request = SendMessageRequest.builder().build();

// Corrected v2 code.
request = request.toBuilder()
    .overrideConfiguration(o -> o.apiCallTimeout(Duration.ofSeconds(7)))
    .build();
```

## 파라미터가 있는 서비스 클라이언트 생성자
<a name="service-client-constructors-with-args"></a>

마이그레이션 도구는 비어 있는 서비스 클라이언트 생성자를 변환하지만 자격 증명 또는 구성과 같은 파라미터를 허용하는 생성자는 변환할 수 없습니다.

이전(v1 코드):

```
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;

AWSCredentials awsCredentials = new BasicAWSCredentials("akid", "skid");
AmazonSQS sqs = new AmazonSQSClient(awsCredentials);
```

이후(마이그레이션 도구 결과 - 컴파일되지 않음):

```
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.services.sqs.SqsClient;  // Import updated to v2.

AwsCredentials awsCredentials = AwsBasicCredentials.create("akid", "skid");

// Does not compile.
SqsClient sqs = new SqsClient(awsCredentials);
```

빌더 패턴을 사용하려면 서비스 클라이언트 생성자를 수동으로 업데이트해야 합니다.

```
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;  // Add manually.
import software.amazon.awssdk.services.sqs.SqsClient;

AwsCredentials awsCredentials = AwsBasicCredentials.create("akid", "skid");

// Corrected v2 code.
SqsClient sqs = SqsClient.builder()
    .credentialsProvider(StaticCredentialsProvider.create(awsCredentials))
    .build();
```

# 마이그레이션에 대한 단계별 설명(예제 포함)
<a name="migration-steps"></a>

이 섹션에서는 현재 SDK for Java v1.x를 사용하는 애플리케이션을 SDK for Java 2.x로 마이그레이션하기 위한 단계별 안내서를 제공합니다. 첫 번째 부분에서는 단계에 대한 개요와 마이그레이션의 세부 예제를 제공합니다.

여기에서 다루는 단계는 애플리케이션이 모델 기반 서비스 클라이언트를 AWS 서비스 사용하여를 호출하는 일반적인 사용 사례의 마이그레이션을 설명합니다. [S3 Transfer Manager](migration-s3-transfer-manager.md) 또는 [CloudFront 사전 서명](migration-cloudfront-presigning.md)과 같은 개괄적인 API를 사용하는 코드를 마이그레이션해야 하는 경우 [AWS SDK for Java 1.x와 2.x의 차이점](migration-whats-different.md) 목차 아래의 섹션을 참조하세요.



여기에 설명된 접근 방식은 제안입니다. 다른 기법을 사용하고 IDE의 코드 편집 기능을 활용하여 동일한 결과를 얻을 수 있습니다.

## 단계 개요
<a name="migration-steps-overview"></a>

### 1. 먼저 SDK for Java 2.x BOM을 추가합니다.
<a name="migration-steps-overview-step1"></a>

SDK for Java 2.x의 Maven BOM(Bill of Materials) 요소를 POM 파일에 추가하면 필요한 모든 v2 종속성이 동일한 버전인지 확인할 수 있습니다. POM에는 v1 및 v2 종속성이 모두 포함될 수 있습니다. 이렇게 하면 코드를 한 번에 모두 변경하는 대신 점진적으로 마이그레이션할 수 있습니다.

#### SDK for Java 2.x BOM
<a name="drt_b5n_q1c"></a>

```
<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>
```

Maven 중앙 리포지토리에서 [최신 버전](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)을 확인해 보세요.

### 2. v1 클래스 가져오기 문에 대한 파일 검색
<a name="migration-steps-overview-step2"></a>

애플리케이션의 파일에서 v1 가져오기에 사용되는 SERVICE\$1ID를 스캔하면 사용된 고유한 SERVICE\$1ID를 확인할 수 있습니다. SERVICE\$1ID는의 짧고 고유한 이름입니다 AWS 서비스. 예를 들어 `cognitoidentity`는 Amazon Cognito 자격 증명의 SERVICE\$1ID입니다.

### 3. v1 가져오기 문에서 v2 Maven 종속성 확인
<a name="migration-steps-overview-step3"></a>

모든 고유한 v1 SERVICE\$1ID를 찾은 후 [Maven artifactId 매핑에 대한 패키지 이름](#migration-serviceid-artifactid-mapping)을 참조하여 v2 종속성에 해당하는 Maven 아티팩트를 확인할 수 있습니다.

### 4. POM 파일에 v2 종속성 요소 추가
<a name="migration-steps-overview-step4"></a>

3단계에서 확인한 종속성 요소로 Maven POM 파일을 업데이트합니다.

### 5. Java 파일에서 v1 클래스를 v2 클래스로 점진적으로 변경합니다.
<a name="migration-steps-overview-step5"></a>

v1 클래스를 v2 클래스로 대체할 때 생성자 대신 빌더를 사용하고 유용한 getter 및 setter를 사용하는 등 v2 API를 지원하는 데 필요한 변경 사항을 적용합니다.

### 6. POM에서 v1 Maven 종속성 제거 및 파일에서 v1 가져오기
<a name="migration-steps-overview-step6"></a>

v2 클래스를 사용하도록 코드를 마이그레이션한 후 파일에서 남은 v1 가져오기와 빌드 파일에서 모든 종속성을 제거합니다.

### 7. v2 API 개선 사항을 사용하도록 코드 리팩터링
<a name="migration-steps-overview-step7"></a>

코드가 성공적으로 컴파일되고 테스트를 통과하면 다른 HTTP 클라이언트 또는 페이지 매김 도구를 사용하여 코드를 단순화하는 등 v2 개선 사항을 활용할 수 있습니다. 이 단계는 선택 사항입니다.

## 마이그레이션 예제
<a name="migration-steps-example"></a>

이 예제에서는 SDK for Java v1을 사용하고 여러 AWS 서비스에 액세스하는 애플리케이션을 마이그레이션합니다. 5단계에서 다음 v1 메서드를 자세히 살펴봅니다. 이는 8개의 메서드가 포함된 클래스의 한 가지 메서드이며 애플리케이션에는 32개의 클래스가 있습니다.

### 마이그레이션할 v1 메서드
<a name="v1-snippet-collapsed"></a>

Java 파일에서 v1 SDK 가져오기만 아래에 나열됩니다.

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.AmazonEC2Exception;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceStateName;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
...
private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds) {
    List<Instance> runningInstances = new ArrayList<>();
    try {
        DescribeInstancesRequest request = new DescribeInstancesRequest()
                .withInstanceIds(instanceIds);
        DescribeInstancesResult result;
        do {
            // DescribeInstancesResponse is a paginated response, so use tokens with multiple requests.
            result = ec2.describeInstances(request);
            request.setNextToken(result.getNextToken());   // Prepare request for next page.
            for (final Reservation r : result.getReservations()) {
                for (final Instance instance : r.getInstances()) {
                    LOGGER.info("Examining instanceId: "+ instance.getInstanceId());
                    // if instance is in a running state, add it to runningInstances list.
                    if (RUNNING_STATES.contains(instance.getState().getName())) {
                        runningInstances.add(instance);
                    }
                }
            }
        } while (result.getNextToken() != null);
    } catch (final AmazonEC2Exception exception) {
        // if instance isn't found, assume its terminated and continue.
        if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) {
            LOGGER.info("Instance probably terminated; moving on.");
        } else {
            throw exception;
        }
    }
    return runningInstances;
}
```

### 1. v2 Maven BOM 추가
<a name="migration-steps-example-step1"></a>

`dependencyManagement` 섹션의 다른 종속성과 함께 SDK for Java 2.x용 Maven BOM을 POM에 추가합니다. POM 파일에 SDK v1용 BOM이 있는 경우 지금은 그대로 둡니다. 이후 단계에서 제거됩니다.

#### 시작 시 POM 종속성 관리
<a name="migration-example-boms"></a>

```
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.example</groupId>             <!--Existing dependency in POM. -->
      <artifactId>bom</artifactId>
      <version>1.3.4</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    ...
    <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-bom</artifactId>  <!--Existing v1 BOM dependency. -->
      <version>1.11.1000</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    ...
    <dependency>
      <groupId>software.amazon.awssdk</groupId>  <!--Add v2 BOM dependency. -->
      <artifactId>bom</artifactId>
      <version>2.27.21</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>
```

### 2. v1 클래스 가져오기 문에 대한 파일 검색
<a name="migration-steps-example-step2"></a>

애플리케이션의 코드를 검색하여 `import com.amazonaws.services`의 고유한 발생을 찾습니다. 이를 통해 프로젝트에서 사용하는 v1 종속성을 확인할 수 있습니다. 애플리케이션에 v1 종속성이 나열된 Maven POM 파일이 있는 경우 이 정보를 대신 사용할 수 있습니다.

이 예제에서는 [`ripgrep`(rg)](https://github.com/BurntSushi/ripgrep) 명령을 사용하여 코드 베이스를 검색합니다.

코드 베이스의 루트에서 다음 `ripgrep` 명령을 실행합니다. `ripgrep`가 가져오기 문을 찾은 후 `cut`, `sort` 및 `uniq` 명령으로 파이프 처리되어 SERVICE\$1ID를 격리합니다.

```
rg --no-filename 'import\s+com\.amazonaws\.services' | cut -d '.' -f 4 | sort | uniq
```

이 애플리케이션의 경우 다음 SERVICE\$1ID가 콘솔에 로그됩니다.

```
autoscaling
cloudformation
ec2
identitymanagement
```

이는 `import` 문에 사용된 다음 패키지 이름 각각이 한 번 이상 발생했음을 나타냅니다. 이 목적에 따라 개별 클래스 이름은 중요하지 않습니다. 사용되는 SERVICE\$1ID를 찾기만 하면 됩니다.

```
com.amazonaws.services.autoscaling.*
com.amazonaws.services.cloudformation.*
com.amazonaws.services.ec2.*
com.amazonaws.services.identitymanagement.*
```

### 3. v1 가져오기 문에서 v2 Maven 종속성 확인
<a name="migration-steps-example-step3"></a>

2단계에서 격리한 v1용 SERVICE\$1ID를 예로 들면 `autoscaling` 및 `cloudformation`은 대부분 동일한 v2 SERVICE\$1ID에 매핑할 수 있습니다. v2 Maven artifactId는 대부분의 경우 SERVICE\$1ID와 일치하므로 POM 파일에 종속성 블록을 추가하는 데 필요한 정보가 포함됩니다.

다음 테이블은 v2 종속성을 확인하는 방법을 보여줍니다.


| v1 SERVICE\$1ID는 ...에 매핑됩니다.패키지 이름 | v2 SERVICE\$1ID는 ...에 매핑됩니다.패키지 이름 | v2 Maven 종속성 | 
| --- | --- | --- | 
|  **ec2** `com.amazonaws.services.ec2.*`  |  **ec2** `software.amazon.awssdk.services.ec2.*`  |  <pre><dependency><br />  <groupId>software.amazon.awssdk</groupId><br />  <artifactId>ec2</artifactId><br /></dependency></pre>  | 
|  **Autoscaling** `com.amazonaws.services.autoscaling.*`  |  **Autoscaling** `software.amazon.awssdk.services.autoscaling.*`  |  <pre><dependency><br />  <groupId>software.amazon.awssdk</groupId><br />  <artifactId>autoscaling</artifactId><br /></dependency></pre>  | 
| cloudformation`com.amazonaws.services.cloudformation.*` | cloudformation`software.amazon.awssdk.cloudformation.*` |  <pre><dependency><br />  <groupId>software.amazon.awssdk</groupId><br />  <artifactId>cloudformation</artifactId><br /></dependency></pre>  | 
| identitymanagement\$1`com.amazonaws.services.identitymanagement.*` | iam\$1`software.amazon.awssdk.iam.*` |  <pre><dependency><br />  <groupId>software.amazon.awssdk</groupId><br />  <artifactId>iam</artifactId><br /></dependency></pre>  | 

\$1 `iam` 매핑에 대한 `identitymanagement`는 SERVICE\$1ID가 버전 간에 다른 예외입니다. Maven 또는 Gradle이 v2 종속성을 해결할 수 없는 경우 [Maven artifactId 매핑에 대한 패키지 이름](#migration-serviceid-artifactid-mapping) 예외는 섹션을 참조하세요.

### 4. POM 파일에 v2 종속성 요소 추가
<a name="migration-steps-example-step4"></a>

3단계에서는 POM 파일에 추가해야 하는 4개의 종속성 블록을 확인했습니다. 1단계에서 BOM을 지정했으므로 버전을 추가할 필요가 없습니다. 가져오기가 추가되면 POM 파일에 다음과 같은 종속성 요소가 포함됩니다.

```
    ...
  <dependencies>
    ...
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>autoscaling</artifactId>
    </dependency>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>iam</artifactId>
    </dependency>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>cloudformation</artifactId>
    </dependency>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>ec2</artifactId>
    </dependency>
    ...
  </dependencies>
    ...
```

### 5. Java 파일에서 v1 클래스를 v2 클래스로 점진적으로 변경합니다.
<a name="migration-steps-example-step5"></a>

마이그레이션하는 메서드에서 다음을 확인합니다.
+ `com.amazonaws.services.ec2.AmazonEC2Client`의 EC2 서비스 클라이언트입니다.
+ 여러 EC2 모델 클래스가 사용됩니다. 예: `DescribeInstancesRequest` 및 `DescribeInstancesResult`

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.AmazonEC2Exception;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesRequest;
import com.amazonaws.services.ec2.model.DescribeInstancesResult;
import com.amazonaws.services.ec2.model.Instance;
import com.amazonaws.services.ec2.model.InstanceStateName;
import com.amazonaws.services.ec2.model.Reservation;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;
...
private static List<Instance> getRunningInstances(AmazonEC2Client ec2, List<String> instanceIds)
    List<Instance> runningInstances = new ArrayList<>();
    try {
        DescribeInstancesRequest request = new DescribeInstancesRequest()
                .withInstanceIds(instanceIds);
        DescribeInstancesResult result;
        do {
            // DescribeInstancesResponse is a paginated response, so use tokens with multiple re
            result = ec2.describeInstances(request);
            request.setNextToken(result.getNextToken());   // Prepare request for next page.
            for (final Reservation r : result.getReservations()) {
                for (final Instance instance : r.getInstances()) {
                    LOGGER.info("Examining instanceId: "+ instance.getInstanceId());
                    // if instance is in a running state, add it to runningInstances list.
                    if (RUNNING_STATES.contains(instance.getState().getName())) {
                        runningInstances.add(instance);
                    }
                }
            }
        } while (result.getNextToken() != null);
    } catch (final AmazonEC2Exception exception) {
        // if instance isn't found, assume its terminated and continue.
        if (exception.getErrorCode().equals(NOT_FOUND_ERROR_CODE)) {
            LOGGER.info("Instance probably terminated; moving on.");
        } else {
            throw exception;
        }
    }
    return runningInstances;
}
...
```

목표는 모든 v1 가져오기를 v2 가져오기로 대체하는 것입니다. 한 번에 하나의 클래스를 진행합니다.

#### a. 가져오기 문 또는 클래스 이름 교체
<a name="migration-example-step5-substep1"></a>

`describeRunningInstances` 메서드의 첫 번째 파라미터는 v1 `AmazonEC2Client` 인스턴스입니다. 다음 중 하나를 수행하세요.
+ `com.amazonaws.services.ec2.AmazonEC2Client`에 대한 가져오기를 `software.amazon.awssdk.services.ec2.Ec2Client`로 대체하고 `AmazonEC2Client`를 `Ec2Client`로 변경합니다.
+ 파라미터 유형을 `Ec2Client`로 변경하고 IDE가 올바른 가져오기를 표시하도록 합니다. 클라이언트 이름이 `AmazonEC2Client` 및 `Ec2Client`와 다르기 때문에 IDE는 v2 클래스를 가져오라는 메시지를 표시합니다. 클래스 이름이 두 버전에서 동일한 경우에는 이 접근 방식이 작동하지 않습니다.

#### b. v1 모델 클래스를 v2와 동등한 클레스로 교체
<a name="migration-example-step5-substep2"></a>

v2 `Ec2Client`를 변경한 후 IDE를 사용하면 다음 문에 컴파일 오류가 표시됩니다.

```
                    result = ec2.describeInstances(request);
```

컴파일 오류는 v1의 `DescribeInstancesRequest` 인스턴스를 v2 `Ec2Client` `describeInstances` 메서드의 파라미터로 사용하여 발생합니다. 수정하려면 다음의 대체 또는 가져오기 문을 만듭니다.


| 대체 | with | 
| --- | --- | 
|  <pre>import com.amazonaws.services.ec2.model.DescribeInstancesRequest</pre>  |  <pre>import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest</pre>  | 

#### c. v1 생성자를 v2 빌더로 변경합니다.
<a name="migration-example-step5-substep3"></a>

[v2 클래스에 생성자가 없기](migration-whats-different.md#immutable-classes) 때문에 컴파일 오류가 계속 표시됩니다. 수정하려면 다음 변경 사항을 적용합니다.


| 변경 | to | 
| --- | --- | 
|  <pre>final DescribeInstancesRequest request = new DescribeInstancesRequest()<br />        .withInstanceIds(instanceIdsCopy);</pre>  |  <pre>final DescribeInstancesRequest request = DescribeInstancesRequest.builder()<br />        .instanceIds(instanceIdsCopy)<br />        .build();</pre>  | 

#### d. v1 `*Result` 응답 객체를 v2 `*Response`에 상응하는 객체로 교체
<a name="migration-example-step5-substep4"></a>

v1과 v2의 일관된 차이점은 [v2의 모든 응답 객체가 `*Result` 대신 `*Response`로 끝나는 것](migration-whats-different.md#model-classname-changes)입니다. v1 `DescribeInstancesResult` 가져오기를 v2 가져오기인 `DescribeInstancesResponse`로 교체합니다.

#### d. API 변경 사항 적용
<a name="migration-example-step5-substep5"></a>

다음 문은 몇 가지 변경 사항이 필요합니다.

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

v2에서 [setter 메서드](migration-whats-different.md#setter-getter-methods)는 `set`를 사용하거나 `prefix`와 함께 사용하지 않습니다. 또한 접두사가 `get`인 getter 메서드는 SDK for Java 2.x에서 삭제됩니다.

`request` 인스턴스 등의 모델 클래스는 v2에서 변경할 수 없으므로 빌더로 새 `DescribeInstancesRequest`를 만들어야 합니다.

v2에서 문은 다음과 같습니다.

```
request = DescribeInstancesRequest.builder()
        .nextToken(result.nextToken())
        .build();
```

#### d. 메서드가 v2 클래스로 컴파일될 때까지 반복합니다.
<a name="migration-example-step5-substep6"></a>

나머지 코드를 계속 진행합니다. v1 가져오기를 v2 가져오기로 교체하고 컴파일 오류를 수정합니다. [v2 API 참조](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/package-summary.html) 및 필요에 따라 [다른 참조](migration-whats-different.md)를 참고합니다.

이 단일 메서드를 마이그레이션하면 다음의 v2 코드가 포함됩니다.

```
import com.amazonaws.ClientConfiguration;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.RegionUtils;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.ec2.model.AmazonEC2Exception;
import com.amazonaws.services.ec2.model.CreateTagsRequest;
import com.amazonaws.services.ec2.model.InstanceStateName;
import com.amazonaws.services.ec2.model.Tag;
import com.amazonaws.services.ec2.model.TerminateInstancesRequest;

import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.Reservation;
...
private static List<Instance> getRunningInstances(Ec2Client ec2, List<String> instanceIds) {
    List<Instance> runningInstances = new ArrayList<>();
        try {
            DescribeInstancesRequest request = DescribeInstancesRequest.builder()
                    .instanceIds(instanceIds)
                    .build();
            DescribeInstancesResponse result;
            do {
                // DescribeInstancesResponse is a paginated response, so use tokens with multiple re
                result = ec2.describeInstances(request);
                request = DescribeInstancesRequest.builder()   // Prepare request for next page.
                        .nextToken(result.nextToken())
                        .build();
                for (final Reservation r : result.reservations()) {
                    for (final Instance instance : r.instances()) {
                        // if instance is in a running state, add it to runningInstances list.
                        if (RUNNING_STATES.contains(instance.state().nameAsString())) {
                            runningInstances.add(instance);
                        }
                    }
                }
            } while (result.nextToken() != null);
        } catch (final Ec2Exception exception) {
            // if instance isn't found, assume its terminated and continue.
            if (exception.awsErrorDetails().errorCode().equals(NOT_FOUND_ERROR_CODE)) {
                    LOGGER.info("Instance probably terminated; moving on.");
            } else {
                throw exception;
            }
        }
        return runningInstances;
    }
...
```

8가지 메서드로 Java 파일의 단일 메서드를 마이그레이션하기 때문에 파일을 작업할 때 v1과 v2 가져오기가 혼합되어 있습니다. 단계를 수행할 때 마지막 6개의 가져오기 문을 추가했습니다.

모든 코드를 마이그레이션하면 더 이상 v1 가져오기 문이 없습니다.

### 6. POM에서 v1 Maven 종속성 제거 및 파일에서 v1 가져오기
<a name="migration-steps-example-step6"></a>

파일의 모든 v1 코드를 마이그레이션하면 다음과 같은 v2 SDK 가져오기 문이 있습니다.

```
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.regions.ServiceMetadata;
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.CreateTagsRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesRequest;
import software.amazon.awssdk.services.ec2.model.DescribeInstancesResponse;
import software.amazon.awssdk.services.ec2.model.Ec2Exception;
import software.amazon.awssdk.services.ec2.model.Instance;
import software.amazon.awssdk.services.ec2.model.InstanceStateName;
import software.amazon.awssdk.services.ec2.model.Reservation;
import software.amazon.awssdk.services.ec2.model.Tag;
import software.amazon.awssdk.services.ec2.model.TerminateInstancesRequest;
```

애플리케이션의 *모든* 파일을 마이그레이션하면 더 이상 POM 파일에 v1 종속성이 필요하지 않습니다. 모든 v1 종속성 블록을 사용하는 경우 `dependencyManagement` 섹션에서 v1 BOM을 제거합니다.

### 7. v2 API 개선 사항을 사용하도록 코드 리팩터링
<a name="migration-steps-example-step7"></a>

마이그레이션 중인 코드 조각의 경우 v2 페이지 매김 도구를 필요에 따라 사용하고 SDK가 더 많은 데이터에 대한 토큰 기반 요청을 관리하도록 할 수 있습니다.

전체 `do`절을 다음으로 교체할 수 있습니다.

```
                DescribeInstancesIterable responses = ec2.describeInstancesPaginator(request);

                responses.reservations().stream()
                        .forEach(reservation -> reservation.instances()
                                .forEach(instance -> {
                                    if (RUNNING_STATES.contains(instance.state().nameAsString())) {
                                        runningInstances.put(instance.instanceId(), instance);
                                    }
                                }));
```

## Maven artifactId 매핑에 대한 패키지 이름
<a name="migration-serviceid-artifactid-mapping"></a>

Maven 또는 Gradle 프로젝트를 SDK for Java의 v1에서 v2로 마이그레이션할 때 빌드 파일에 추가할 종속성을 파악해야 합니다. [마이그레이션에 대한 단계별 설명(예제 포함)](#migration-steps)(3단계)에 설명된 접근 방식은 가져오기 문의 패키지 이름을 시작점으로 사용하여 빌드 파일에 추가할 종속성(artifactId)을 결정합니다.

이 주제의 정보를 사용하여 v1 패키지 이름을 v2 artifactId로 매핑합니다.

### 패키지 이름 및 Maven artifactId에 사용되는 일반적인 이름 지정 규칙
<a name="migration-naming-convention"></a>

다음 테이블에는 SDK가 주어진 SERVICE\$1ID에 사용하는 일반적인 이름 지정 규칙이 나와 있습니다. SERVICE\$1ID는의 고유 식별자입니다 AWS 서비스. 예를 들어 Amazon S3 서비스의 SERVICE\$1ID는 `s3`이고 `cognitoidentity`는 Amazon Cognito 자격 증명의 SERVICE\$1ID입니다.


| v1 패키지 이름(가져오기 문) | v1 artifactId | v2 artifactId | v2 패키지 이름(가져오기 문) | 
| --- | --- | --- | --- | 
| com.amazonaws.services.SERVICE\$1ID | aws-java-sdk-SERVICE\$1ID | SERVICE\$1ID | software.amazon.awssdk.services.SERVICE\$1ID | 
|   | 
| Amazon Cognito 자격 증명의 예(SERVICE\$1ID: cognitoidentity) | 
| com.amazonaws.services.cognitoidentity | aws-java-sdk-cognitoidentity | cognitoidentity | software.amazon.awssdk.services.cognitoidentity | 

### SERVICE\$1ID 차이점
<a name="migration-serviceid-diffs"></a>

#### v1 내
<a name="migration-serviceid-diffs-withinv1"></a>

경우에 따라 SERVICE\$1ID는 패키지 이름과 동일한 서비스의 artifactId 간에 다릅니다. 예를 들어 다음 테이블의 CloudWatch Metrics 행은 `metrics`이 패키지 이름의 SERVICE\$1ID이지만 `cloudwatchmetrics`은 artifactId의 SERVICE\$1ID임을 보여줍니다.

#### v2 내
<a name="migration-serviceid-diffs-withinv2"></a>

패키지 이름 및 artifactId에 사용되는 SERVICE\$1ID에는 차이가 없습니다.

#### v1 및 v2 차이
<a name="migration-serviceid-diffs-btwv1v2"></a>

대부분의 서비스에서 v2의 SERVICE\$1ID는 패키지 이름과 artifactId 모두에서 v1의 SERVICE\$1ID와 동일합니다. 이전 테이블과 같이 `cognitoedentity` SERVICE\$1ID를 예로 들 수 있습니다. 그러나 다음 테이블과 같이 일부 SERVICE\$1ID는 SDK 간에 다릅니다.

v1 열 중 하나에 있는 **boldface SERVICE\$1ID**는 v2에 사용된 SERVICE\$1ID와 다르다는 것을 나타냅니다.


| 서비스 이름 | v1 패키지 이름 | v1 artifactId | v2 artifactId | v2 패키지 이름 | 
| --- | --- | --- | --- | --- | 
|  |  모든 패키지 이름은 첫 번째 행에 표시된 대로 `com.amazonaws.services`로 시작합니다.  |  모든 artifactId는 첫 번째 행과 같이 태그로 묶입니다.  |  모든 artifactId는 첫 번째 행과 같이 태그로 묶입니다.  |  모든 패키지 이름은 첫 번째 행에 표시된 대로 `software.amazon.awssdk`로 시작합니다.  | 
|  | 
| API Gateway | com.amazonaws.services.apigateway | <artifactId>aws-java-sdk-api-gateway</artifactId> | <artifactId>apigateway</artifactId> | software.amazon.awssdk.services.apigateway | 
| 앱 레지스트리 | appregistry | appregistry | servicecatalogappregistry | servicecatalogappregistry | 
| Application Discovery | applicationdiscovery | discovery | applicationdiscovery | applicationdiscovery | 
| 증강형 AI 런타임 | augmentedairuntime | augmentedairuntime | sagemakera2iruntime | sagemakera2iruntime | 
| Certificate Manager | certificatemanager | acm | acm | acm | 
| CloudControl API | cloudcontrolapi | cloudcontrolapi | cloudcontrol | cloudcontrol | 
| cloudsearch | cloudsearchv2 | cloudsearch | cloudsearch | cloudsearch | 
| CloudSearch 도메인 | cloudsearchdomain | cloudsearch | cloudsearchdomain | cloudsearchdomain | 
| CloudWatch Events | cloudwatchevents | 이벤트 | cloudwatchevents | cloudwatchevents | 
| CloudWatch Evidently | cloudwatchevidently | cloudwatchevidently | evidently | evidently | 
| CloudWatch Logs | 로그 | 로그 | cloudwatchlogs | cloudwatchlogs | 
| CloudWatch 지표 | 지표 | cloudwatchmetrics | cloudwatch | cloudwatch | 
| CloudWatch Rum | cloudwatchrum | cloudwatchrum | rum | rum | 
| Cognito 자격 증명 공급자 | cognitoidp | cognitoidp | cognitoidentityprovider | cognitoidentityprovider | 
| 캠페인 연결 | connectcampaign | connectcampaign | connectcampaigns | connectcampaigns | 
| Wisdom 연결 | connectwisdom | connectwisdom | wisdom | wisdom | 
| Database Migration Service | databasemigrationservice | dms | databasemigration | databasemigration | 
| DataZone | datazone | datazoneexternal | datazone | datazone | 
| DynamoDB | dynamodbv2 | dynamodb | dynamodb | dynamodb | 
| Elastic File System | elasticfilesystem | efs | efs | efs | 
| Elastic Map Reduce | elasticmapreduce | emr | emr | emr | 
| Glue DataBrew | gluedatabrew | gluedatabrew | databrew | databrew | 
| IAM Roles Anywhere | iamrolesanywhere | iamrolesanywhere | rolesanywhere | rolesanywhere | 
| 자격 증명 관리 | identitymanagement | iam | iam | iam | 
| IoT 데이터 | iotdata | iot | iotdataplane | iotdataplane | 
| Kinesis Analytics | kinesisanalytics | kinesis | kinesisanalytics | kinesisanalytics | 
| Kinesis Firehose | kinesisfirehose | kinesis | firehose | firehose | 
| Kinesis 비디오 신호 채널 | kinesisvideosignalingchannels | kinesisvideosignalingchannels | kinesisvideosignaling | kinesisvideosignaling | 
| Lex | lexruntime | 어휘 | lexruntime | lexruntime | 
| Lookout For Vision | lookoutforvision | lookoutforvision | lookoutvision | lookoutvision | 
| Mainframe Modernization | mainframemodernization | mainframemodernization | m2 | m2 | 
| Marketplace Metering | marketplacemetering | marketplacemeteringservice | marketplacemetering | marketplacemetering | 
| 관리형 Grafana | managedgrafana | managedgrafana | grafana | grafana | 
| Mechanical Turk | mturk | mechanicalturkrequester | mturk | mturk | 
| Migration Hub Strategy Recommendations | migrationhubstrategyrecommendations | migrationhubstrategyrecommendations | migrationhubstrategy | migrationhubstrategy | 
| Nimble Studio | nimblestudio | nimblestudio | nimble | nimble | 
| Private 5G | private5g | private5g | privatenetworks | privatenetworks | 
| Prometheus | prometheus | prometheus | amp | amp | 
| 휴지통 | recyclebin | recyclebin | rbin | rbin | 
| Redshift 데이터 API | redshiftdataapi | redshiftdataapi | redshiftdata | redshiftdata | 
| Route 53 | route53domains | route53 | route53domains | route53domains | 
| Sage Maker Edge Manager | sagemakeredgemanager | sagemakeredgemanager | sagemakeredge | sagemakeredge | 
| 보안 토큰 | securitytoken | sts | sts | sts | 
| 서버 마이그레이션 | servermigration | servermigration | sms | sms | 
| 간단한 이메일 | simpleemail | ses | ses | ses | 
| 간단한 이메일 V2 | simpleemailv2 | sesv2 | sesv2 | sesv2 | 
| Simple Systems Management | simplesystemsmanagement | ssm | ssm | ssm | 
| 단순 워크플로 | simpleworkflow | simpleworkflow | swf | swf | 
| 단계 함수 | stepfunctions | stepfunctions | sfn | sfn | 

# 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개) | 내부적으로 처리되므로 지원되지 않음 | 

# Java용 SDK 1.x와 2.x를 나란히 사용
<a name="migration-side-by-side"></a>

프로젝트에서 AWS SDK for Java의 두 버전을 모두 사용할 수 있습니다.

다음은 버전 1.x의 Amazon S3와 버전 2.27.21의 DynamoDB을 사용하는 프로젝트의 `pom.xml` 파일 예제입니다.

**Example POM의 예제**  
이 예제는 SDK 1.x 및 2.x 버전을 모두 사용하는 프로젝트의 `pom.xml` 파일 항목을 보여줍니다.  

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-bom</artifactId>
            <version>1.12.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <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>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-s3</artifactId>
    </dependency>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>dynamodb</artifactId>
    </dependency>
</dependencies>
```