

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

# SDK for Kotlin을 사용하여 Amazon S3 다중 리전 액세스 포인트 작업
<a name="use-services-s3-mrap"></a>

Amazon S3 다중 리전 액세스 포인트는 애플리케이션이 여러 AWS 리전리전에 있는 Amazon S3 버킷의 요청을 이행하는 데 사용할 수 있는 글로벌 엔드포인트를 제공합니다. 다중 리전 액세스 포인트를 사용하여 단일 리전에서 사용되는 것과 동일한 아키텍처로 다중 리전 애플리케이션을 구축하면 전 세계 어디에서나 해당 애플리케이션을 실행할 수 있습니다.

Amazon S3 사용 설명서에는 [다중 리전 액세스 포인트에 대한 자세한 배경 정보가 포함되어 있습니다](https://docs.aws.amazon.com//AmazonS3/latest/userguide/MultiRegionAccessPoints.html).

## 다중 리전 액세스 포인트 작업
<a name="mrap-s3control-config"></a>

다중 리전 액세스 포인트를 생성하려면 먼저 요청을 처리할 각 AWS 리전에 하나의 버킷을 지정합니다. 다음 코드 조각은 두 개의 버킷을 생성합니다.

### 버킷 생성
<a name="mrap-s3-create-buckets"></a>

다음 함수는 다중 리전 액세스 포인트와 함께 사용할 버킷 2개를 생성합니다. 한 버킷은 리전에 `us-east-1` 있고 다른 버킷은 리전에 있습니다`us-west-1`.

첫 번째 인수로 전달된 S3 클라이언트의 생성은 아래의 첫 번째 예제에 나와 있습니다[객체 및 다중 리전 액세스 포인트 작업](#mrap-s3client-config).

```
        suspend fun setUpTwoBuckets(
            s3: S3Client,
            bucketName1: String,
            bucketName2: String,
        ) {
            println("Create two buckets in different regions.")
            // The shared aws config file configures the default Region to be us-east-1.
            s3.createBucket(
                CreateBucketRequest {
                    bucket = bucketName1
                },
            )
            s3.waitUntilBucketExists {
                bucket = bucketName1
            }
            println("  Bucket [$bucketName1] created.")

            // Override the S3Client to work with us-west-1 for the second bucket.
            s3.withConfig {
                region = "us-west-1"
            }.use { s3West ->
                s3West.createBucket(
                    CreateBucketRequest {
                        bucket = bucketName2
                        createBucketConfiguration = CreateBucketConfiguration {
                            locationConstraint = BucketLocationConstraint.UsWest1
                        }
                    },
                )
                s3West.waitUntilBucketExists {
                    bucket = bucketName2
                }
                println("  Bucket [$bucketName2] created.")
            }
        }
```

Kotlin SDK의 [S3 제어 클라이언트](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3control/aws.sdk.kotlin.services.s3control/-s3-control-client/index.html)를 사용하여 다중 리전 액세스 포인트를 생성, 삭제 및 가져옵니다.

다음 코드 조각과 같이 S3 제어 아티팩트에 대한 종속성을 추가합니다. (*X.Y.Z* 링크로 이동하여 사용 가능한 최신 버전을 볼 수 있습니다.)

```
...
implementation(platform("aws.sdk.kotlin:bom:[https://github.com/awslabs/aws-sdk-kotlin/releases/latest](https://github.com/awslabs/aws-sdk-kotlin/releases/latest)"))
implementation("aws.sdk.kotlin:s3control")
...
```

다음 코드와 같이에서 AWS 리전 `us-west-2` 작동하도록 S3 제어 클라이언트를 구성합니다. 모든 S3 제어 클라이언트 작업은 `us-west-2` 리전을 대상으로 해야 합니다.

```
        suspend fun createS3ControlClient(): S3ControlClient {
            // Configure your S3ControlClient to send requests to US West (Oregon).
            val s3Control = S3ControlClient.fromEnvironment {
                region = "us-west-2"
            }
            return s3Control
        }
```

S3 제어 클라이언트를 사용하여 다음 코드와 같이 버킷 이름(이전에 생성됨)을 지정하여 다중 리전 액세스 포인트를 생성합니다.

```
    suspend fun createMrap(
        s3Control: S3ControlClient,
        accountIdParam: String,
        bucketName1: String,
        bucketName2: String,
        mrapName: String,
    ): String {
        println("Creating MRAP ...")
        val createMrapResponse: CreateMultiRegionAccessPointResponse =
            s3Control.createMultiRegionAccessPoint {
                accountId = accountIdParam
                clientToken = UUID.randomUUID().toString()
                details {
                    name = mrapName
                    regions = listOf(
                        Region {
                            bucket = bucketName1
                        },
                        Region {
                            bucket = bucketName2
                        },
                    )
                }
            }
        val requestToken: String? = createMrapResponse.requestTokenArn

        // Use the request token to check for the status of the CreateMultiRegionAccessPoint operation.
        if (requestToken != null) {
            waitForSucceededStatus(s3Control, requestToken, accountIdParam)
            println("MRAP created")
        }

        val getMrapResponse =
            s3Control.getMultiRegionAccessPoint(
                input = GetMultiRegionAccessPointRequest {
                    accountId = accountIdParam
                    name = mrapName
                },
            )
        val mrapAlias = getMrapResponse.accessPoint?.alias
        return "arn:aws:s3::$accountIdParam:accesspoint/$mrapAlias"
    }
```

다중 리전 액세스 포인트 생성은 비동기 작업이므로 즉시 응답에서 받은 토큰을 사용하여 생성 프로세스의 상태를 확인합니다. 상태 확인에서 성공 메시지가 반환되면 `GetMultiRegionAccessPoint` 작업을 사용하여 다중 리전 액세스 포인트의 별칭을 가져올 수 있습니다. 별칭은 객체 수준 작업에 필요한 ARN의 마지막 구성 요소입니다.

### 토큰을 사용하여 상태 확인
<a name="mrap-s3-control-poll"></a>

`DescribeMultiRegionAccessPointOperation`를 사용하여 마지막 작업의 상태를 확인합니다. `requestStatus` 값이 "SUCCEEDED"가 되면 다중 리전 액세스 포인트로 작업할 수 있습니다.

```
        suspend fun waitForSucceededStatus(
            s3Control: S3ControlClient,
            requestToken: String,
            accountIdParam: String,
            timeBetweenChecks: Duration = 1.minutes,
        ) {
            var describeResponse: DescribeMultiRegionAccessPointOperationResponse
            describeResponse = s3Control.describeMultiRegionAccessPointOperation(
                input = DescribeMultiRegionAccessPointOperationRequest {
                    accountId = accountIdParam
                    requestTokenArn = requestToken
                },
            )

            var status: String? = describeResponse.asyncOperation?.requestStatus
            while (status != "SUCCEEDED") {
                delay(timeBetweenChecks)
                describeResponse = s3Control.describeMultiRegionAccessPointOperation(
                    input = DescribeMultiRegionAccessPointOperationRequest {
                        accountId = accountIdParam
                        requestTokenArn = requestToken
                    },
                )
                status = describeResponse.asyncOperation?.requestStatus
                println(status)
            }
        }
```

## 객체 및 다중 리전 액세스 포인트 작업
<a name="mrap-s3client-config"></a>

[S3 클라이언트](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/-s3-client/index.html)를 사용하여 다중 리전 액세스 포인트의 객체로 작업합니다. 버킷의 객체에 사용하는 많은 작업은 다중 리전 액세스 포인트에서 사용할 수 있습니다. 자세한 내용과 전체 작업 목록은 [S3 작업과의 다중 리전 액세스 포인트 호환성을 참조하세요](https://docs.aws.amazon.com//AmazonS3/latest/userguide/MrapOperations.html#mrap-operations-support).

다중 리전 액세스 포인트를 사용하는 작업은 비대칭 SigV4(SigV4a) 서명 알고리즘으로 서명됩니다. SigV4a를 구성하려면 먼저 프로젝트에 다음 종속성을 추가합니다. (*X.Y.Z* 링크로 이동하여 사용 가능한 최신 버전을 볼 수 있습니다.)

```
...
implementation(platform("aws.sdk.kotlin:bom:[https://github.com/awslabs/aws-sdk-kotlin/releases/latest](https://github.com/awslabs/aws-sdk-kotlin/releases/latest)"))
implementation(platform("aws.smithy.kotlin:bom:[https://github.com/smithy-lang/smithy-kotlin/releases/latest](https://github.com/smithy-lang/smithy-kotlin/releases/latest)"))

implementation("aws.smithy.kotlin:aws-signing-default")
implementation("aws.smithy.kotlin:http-auth-aws")
implementation("aws.sdk.kotlin:s3")
...
```

종속성을 추가한 후 다음 코드와 같이 SigV4a 서명 알고리즘을 사용하도록 SS3 클라이언트를 구성합니다.

```
        suspend fun createS3Client(): S3Client {
            // Configure your S3Client to use the Asymmetric SigV4 (SigV4a) signing algorithm.
            val sigV4aScheme = SigV4AsymmetricAuthScheme(DefaultAwsSigner)
            val s3 = S3Client.fromEnvironment {
                authSchemes = listOf(sigV4aScheme)
            }
            return s3
        }
```

S3 클라이언트를 구성한 후 S3가 다중 리전 액세스 포인트에 대해 지원하는 작업은 동일하게 작동합니다. 유일한 차이점은 버킷 파라미터가 다중 리전 액세스 포인트의 ARN이어야 한다는 것입니다. ARN을 반환하는 `createMrap` 함수에서 앞서 설명한 것처럼 Amazon S3 콘솔에서 또는 프로그래밍 방식으로 ARN을 가져올 수 있습니다.

다음 코드 예제는 `GetObject` 작업에 사용되는 ARN을 보여줍니다.

```
    suspend fun getObjectFromMrap(
        s3: S3Client,
        mrapArn: String,
        keyName: String,
    ): String? {
        val request = GetObjectRequest {
            bucket = mrapArn // Use the ARN instead of the bucket name for object operations.
            key = keyName
        }

        var stringObj: String? = null
        s3.getObject(request) { resp ->
            stringObj = resp.body?.decodeToString()
            if (stringObj != null) {
                println("Successfully read $keyName from $mrapArn")
            }
        }
        return stringObj
    }
```