

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

# AWS SDK for C\$1\$1 사용
<a name="programming-general"></a>

이 단원에서는 시작하기에서 다루는 것 AWS SDK for C\$1\$1외에도의 일반적인 [사용에 AWS SDK for C\$1\$1](getting-started.md) 대한 정보를 제공합니다.

서비스별 프로그래밍 예제는 [AWS SDK for C\$1\$1 코드 예제](programming-services.md)를 참조하세요.

**Topics**
+ [SDK 초기화 및 종료](basic-use.md)
+ [AWS 서비스 요청하기](using-service-client.md)
+ [비동기 프로그래밍](async-methods.md)
+ [유틸리티 모듈](utility-modules.md)
+ [메모리 관리](memory-management.md)
+ [오류 처리](error-handling.md)

# AWS SDK for C\$1\$1 초기화 및 종료
<a name="basic-use"></a>

AWS SDK for C\$1\$1를 사용하는 애플리케이션은 반드시 이를 초기화해야 합니다. 마찬가지로 애플리케이션이 종료되기 전에 SDK를 종료해야 합니다. 두 작업 모두 초기화 및 종료 프로세스와 이후 SDK 호출에 영향을 미치는 구성 옵션을 지원합니다.

AWS SDK for C\$1\$1를 사용하는 모든 애플리케이션에는 `aws/core/Aws.h` 파일이 포함되어야 합니다.

AWS SDK for C\$1\$1를 초기화하려면 `Aws::InitAPI`를 호출해야 합니다. 애플리케이션이 종료되기 전에 SDK를 종료하려면 `Aws::ShutdownAPI`를 호출해야 합니다. 각 메서드는 [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/struct_aws_1_1_s_d_k_options.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/struct_aws_1_1_s_d_k_options.html)의 인수를 허용합니다. SDK에 대한 다른 모든 호출은 이 두 메서드 호출 사이에 수행할 수 있습니다.

**`Aws::InitAPI`와 `Aws::ShutdownAPI` 사이에 수행되는 모든 AWS SDK for C\$1\$1 호출은 중괄호 쌍으로 묶거나, 두 메서드 사이에 호출되는 함수를 통해 간접적으로 호출해야 합니다.**

기본 스켈레톤 애플리케이션은 다음과 같습니다.

```
#include <aws/core/Aws.h>
int main(int argc, char** argv)
{
   Aws::SDKOptions options;
   Aws::InitAPI(options);
   {
      // make your SDK calls here.
   }
   Aws::ShutdownAPI(options);
   return 0;
}
```

**SDK for C\$1\$1 및 해당 종속성은 C\$1\$1 정적 객체를 사용하며 정적 객체 폐기 순서는 C\$1\$1 표준에 따라 결정되지 않습니다. 정적 변수 폐기 순서의 비결정성으로 인해 발생하는 메모리 문제를 방지하려면 `Aws::InitAPI` 및 `Aws::ShutdownAPI` 호출을 다른 정적 객체로 래핑하지 마세요. ** 

# AWS SDK for C\$1\$1를 사용하여 AWS 서비스 요청하기
<a name="using-service-client"></a>

 프로그래밍 방식으로 AWS 서비스에 액세스하기 위해 SDK는 각각의 AWS 서비스에 대해 클라이언트 클래스를 사용합니다. 예를 들어, 애플리케이션이 Amazon EC2에 액세스해야 하는 경우, 애플리케이션은 Amazon EC2 클라이언트 객체를 생성하여 해당 서비스와 인터페이스 합니다. 그런 다음 서비스 클라이언트를 사용하여 요청을 AWS 서비스에 보내면 됩니다.

AWS 서비스를 요청하려면 먼저 서비스 클라이언트를 생성하고 [구성](configuring.md)해야 합니다. 코드에 사용된 각 AWS 서비스에는 해당 서비스와 상호 작용하기 위한 자체 라이브러리와 전용 유형이 있습니다. 클라이언트는 서비스가 제공하는 각 API 작업마다 하나의 메서드를 노출합니다.

클라이언트 클래스의 네임스페이스는 `Aws::Service::ServiceClient` 규칙을 따릅니다. 예를 들어 AWS Identity and Access Management(IAM)의 클라이언트 클래스는 `Aws::IAM::IAMClient`이고 Amazon S3의 클라이언트 클래스는 `Aws::S3::S3Client`입니다.

모든 AWS 서비스의 모든 클라이언트 클래스는 스레드 세이프입니다.

클라이언트 클래스를 인스턴스화할 때 AWS 자격 증명을 제공해야 합니다. 자격 증명은 코드, 환경 또는 공유 AWS `config` 파일 및 공유 `credentials` 파일에서 제공할 수 있습니다. 자격 증명에 대한 자세한 내용은 [권장 IAM Identity Center 인증을 설정하기 위한 지침](credentials.md)을 참조하거나 [사용 가능한 다른 자격 증명 공급자](credproviders.md)를 사용하세요.

# 를 사용한 비동기 프로그래밍 AWS SDK for C\$1\$1
<a name="async-methods"></a>

## 비동기식 SDK 메서드
<a name="asynchronous-sdk-methods"></a>

많은 메서드에 대해 SDK for C\$1\$1는 동기식 버전과 비동기식 버전을 모두 제공합니다. 이름에 `Async` 접미사가 포함된 메서드는 비동기식입니다. 예를 들어 Amazon S3 메서드 `PutObject`는 동기식이고 `PutObjectAsync`는 비동기식입니다.

모든 비동기 작업과 마찬가지로, 비동기 SDK 메서드는 기본 태스크가 완료되기 전에 반환됩니다. 예를 들어 `PutObjectAsync` 메서드는 파일을 Amazon S3 버킷에 업로드하는 작업을 완료하기 전에 반환됩니다. 업로드 작업이 계속되는 동안 애플리케이션은 다른 비동기 메서드 직접 호출을 포함하여 다른 작업을 수행할 수 있습니다. 연결된 콜백 함수가 간접적으로 호출될 때 비동기 작업이 완료되었다는 알림이 애플리케이션에 전송됩니다.

다음 섹션에서는 `PutObjectAsync` 비동기식 메서드 직접 호출을 보여주는 코드 예제를 설명합니다. 각 섹션은 예제의 [전체 소스 파일](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_object_async.cpp)에서 개별 부분을 집중적으로 다룹니다.

## SDK 비동기식 메서드 직접 호출
<a name="calling-sdk-asynchronous-methods"></a>

일반적으로 SDK 메서드의 비동기 버전은 다음 인수를 허용합니다.
+ 동기식 버전과 동일한 요청 유형 객체에 대한 참조.
+ 응답 핸들러 콜백 함수에 대한 참조. 이 콜백 함수는 비동기 작업이 완료되면 간접적으로 호출됩니다. 인수 중 하나에는 작업의 결과가 포함됩니다.
+ `AsyncCallerContext` 객체에 대한 `shared_ptr`(선택 사항). 이 객체는 응답 핸들러 콜백에 전달됩니다. 여기에는 텍스트 정보를 콜백에 전달하는 데 사용할 수 있는 UUID 속성이 포함됩니다.

아래에 표시된 `uploadFileAsync` 메서드는 Amazon S3 버킷에 파일을 비동기적으로 업로드하는 SDK의 Amazon S3 `PutObjectAsync` 메서드를 설정하고 직접적으로 호출합니다.

함수는 `S3Client` 객체 및 `PutObjectRequest` 객체에 대한 참조를 수신합니다. 함수가 이러한 참조를 메인 함수로부터 수신하는 이유는 비동기 직접 호출이 지속되는 전체 기간 동안 이 객체들이 존재하도록 보장해야 하기 때문입니다.

`AsyncCallerContext` 객체에 대한 `shared_ptr`이 할당됩니다. 해당 객체의 `UUID` 속성은 Amazon S3 객체 이름으로 설정됩니다. 시연을 위해 응답 핸들러 콜백은 속성에 액세스하여 해당 값을 출력합니다.

`PutObjectAsync` 직접 호출에는 응답 핸들러 콜백 함수 `uploadFileAsyncFinished`에 대한 참조 인수가 포함됩니다. 이 콜백 함수는 다음 섹션에서 자세히 살펴봅니다.

```
bool AwsDoc::S3::uploadFileAsync(const Aws::S3::S3Client &s3Client,
                                Aws::S3::Model::PutObjectRequest &request,
                                const Aws::String &bucketName,
                                const Aws::String &fileName) {
    request.SetBucket(bucketName);
    request.SetKey(fileName);

    const std::shared_ptr<Aws::IOStream> input_data =
            Aws::MakeShared<Aws::FStream>("SampleAllocationTag",
                                          fileName.c_str(),
                                          std::ios_base::in | std::ios_base::binary);

    if (!*input_data) {
        std::cerr << "Error: unable to open file " << fileName << std::endl;
        return false;
    }

    request.SetBody(input_data);

    // Create and configure the context for the asynchronous put object request.
    std::shared_ptr<Aws::Client::AsyncCallerContext> context =
            Aws::MakeShared<Aws::Client::AsyncCallerContext>("PutObjectAllocationTag");
    context->SetUUID(fileName);

    // Make the asynchronous put object call. Queue the request into a 
    // thread executor and call the uploadFileAsyncFinished function when the
    // operation has finished. 
    s3Client.PutObjectAsync(request, uploadFileAsyncFinished, context);

    return true;
}
```

비동기 작업의 리소스는 작업이 완료될 때까지 존재해야 합니다. 예를 들어, 클라이언트 및 요청 객체는 애플리케이션에서 작업 완료 알림을 수신할 때까지 존재해야 합니다. 애플리케이션 자체는 비동기 작업이 완료되기 전까지 종료될 수 없습니다.

이러한 이유로 `uploadFileAsync` 메서드는 `uploadFileAsync` 메서드 내에서 `S3Client` 및 `PutObjectRequest` 객체를 생성하고 로컬 변수에 저장하는 대신, 이들 객체에 대한 참조를 허용합니다.

이 예시에서 `PutObjectAsync` 메서드는 비동기 작업을 시작한 직후 호출자에게 반환되므로, 업로드 작업이 진행되는 동안 호출 체인이 추가 작업을 수행할 수 있습니다.

클라이언트가 `uploadFileAsync` 메서드의 로컬 변수에 저장된 경우 메서드가 반환될 때 범위를 벗어나게 됩니다. 그러나 클라이언트 객체는 비동기 작업이 완료될 때까지 계속 존재해야 합니다.

## 비동기 작업 완료 알림
<a name="notification-of-the-completion-of-an-asynchronous-operation"></a>

비동기 작업이 완료되면 애플리케이션 응답 핸들러 콜백 함수가 간접적으로 호출됩니다. 이 알림에는 작업 결과가 포함됩니다. 결과는 메서드의 동기식 대응 메서드에서 반환하는 것과 동일한 결과 유형 클래스에 포함됩니다. 코드 예제에서 결과는 `PutObjectOutcome` 객체에 있습니다.

예제의 응답 핸들러 콜백 함수 `uploadFileAsyncFinished`는 다음과 같습니다. 비동기 작업이 성공 또는 실패했는지 확인합니다. `std::condition_variable`을을 사용하여 애플리케이션 스레드에 비동기 작업이 완료되었음을 알립니다.

```
// A mutex is a synchronization primitive that can be used to protect shared
// data from being simultaneously accessed by multiple threads.
std::mutex AwsDoc::S3::upload_mutex;

// A condition_variable is a synchronization primitive that can be used to
// block a thread, or to block multiple threads at the same time.
// The thread is blocked until another thread both modifies a shared
// variable (the condition) and notifies the condition_variable.
std::condition_variable AwsDoc::S3::upload_variable;
```

```
void uploadFileAsyncFinished(const Aws::S3::S3Client *s3Client,
                            const Aws::S3::Model::PutObjectRequest &request,
                            const Aws::S3::Model::PutObjectOutcome &outcome,
                            const std::shared_ptr<const Aws::Client::AsyncCallerContext> &context) {
    if (outcome.IsSuccess()) {
        std::cout << "Success: uploadFileAsyncFinished: Finished uploading '"
                  << context->GetUUID() << "'." << std::endl;
    } else {
        std::cerr << "Error: uploadFileAsyncFinished: " <<
                  outcome.GetError().GetMessage() << std::endl;
    }

    // Unblock the thread that is waiting for this function to complete.
    AwsDoc::S3::upload_variable.notify_one();
}
```

비동기 작업이 완료되면 이와 관련된 리소스를 해제할 수 있습니다. 원하는 경우 애플리케이션을 종료할 수도 있습니다.

다음 코드는 애플리케이션에서 `uploadFileAsync` 및 `uploadFileAsyncFinished` 메서드를 사용하는 방법을 보여줍니다.

애플리케이션에서는 비동기 작업이 완료될 때까지 `S3Client` 및 `PutObjectRequest` 객체가 계속 존재하도록 해당 객체를 할당합니다. `uploadFileAsync`를 직접적으로 호출한 후 애플리케이션은 원하는 작업을 수행할 수 있습니다. 단순화를 위해 이 예제에서는 `std::mutex` 및 `std::condition_variable`을 사용하여 응답 핸들러 콜백으로 업로드 작업 완료 알림이 전달될 때까지 대기합니다.

```
int main(int argc, char* argv[])
{
    if (argc != 3)
    {
        std::cout << R"(
Usage:
    run_put_object_async <file_name> <bucket_name>
Where:
    file_name - The name of the file to upload.
    bucket_name - The name of the bucket to upload the object to.
)" << std::endl;
        return 1;
    }

    const Aws::SDKOptions options;
    Aws::InitAPI(options);
    {
        const Aws::String fileName = argv[1];
        const Aws::String bucketName = argv[2];

        // A unique_lock is a general-purpose mutex ownership wrapper allowing
        // deferred locking, time-constrained attempts at locking, recursive
        // locking, transfer of lock ownership, and use with
        // condition variables.
        std::unique_lock<std::mutex> lock(AwsDoc::S3::upload_mutex);

        // Create and configure the Amazon S3 client.
        // This client must be declared here, as this client must exist
        // until the put object operation finishes.
        const Aws::S3::S3ClientConfiguration config;
        // Optional: Set to the AWS Region in which the bucket was created (overrides config file).
        // config.region = "us-east-1";

        const Aws::S3::S3Client s3Client(config);

        // Create the request object.
        // This request object must be declared here, because the object must exist
        // until the put object operation finishes.
        Aws::S3::Model::PutObjectRequest request;

        AwsDoc::S3::uploadFileAsync(s3Client, request, bucketName, fileName);

        std::cout << "main: Waiting for file upload attempt..." <<
                  std::endl << std::endl;

        // While the put object operation attempt is in progress,
        // you can perform other tasks.
        // This example simply blocks until the put object operation
        // attempt finishes.
        AwsDoc::S3::upload_variable.wait(lock);

        std::cout << std::endl << "main: File upload attempt completed."
                  << std::endl;
    }
    Aws::ShutdownAPI(options);

    return 0;
}
```

[전체 예제](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/cpp/example_code/s3/put_object_async.cpp)는 Github에서 확인하세요.

# AWS SDK for C\$1\$1에서 사용 가능한 유틸리티 모듈
<a name="utility-modules"></a>

AWS SDK for C\$1\$1에는 C\$1\$1로 AWS 애플리케이션을 개발하는 복잡성을 줄여주는 다양한 [유틸리티 모듈](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/namespace_aws_1_1_utils.html)이 포함되어 있습니다.

## HTTP 스택
<a name="http-stack"></a>

HTTP 스택은 연결 풀링을 제공하고, 스레드 세이프를 제공하며, 필요에 따라 재사용할 수 있습니다. 자세한 내용은 [AWS 클라이언트 구성](client-config.md)을 참조하세요.


****  

|  |  | 
| --- |--- |
|  헤더  |   [https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/http](https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/http)   | 
|  API 설명서  |   [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/namespace_aws_1_1_http.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/namespace_aws_1_1_http.html)   | 

## 문자열 유틸리티
<a name="string-utils"></a>

핵심 문자열 함수입니다(예: `trim`, `lowercase`, 숫자 변환).


****  

|  |  | 
| --- |--- |
|  헤더  |   [https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/StringUtils.h](https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/StringUtils.h)   | 
|  API 설명서  |   [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_string_utils.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_string_utils.html)   | 

## 해싱 유틸리티
<a name="hashing-utils"></a>

해싱 함수입니다(`SHA256`, `MD5`, `Base64`, `SHA256_HMAC`).


****  

|  |  | 
| --- |--- |
|  헤더  |   [https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/HashingUtils.h](https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/HashingUtils.h)   | 
|  API 설명서  |   [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_hashing_utils.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_hashing_utils.html)   | 

## JSON 파서
<a name="json-parser"></a>

완벽하게 작동하면서도 경량인 JSON 파서입니다(*`cJSON`*의 얇은 래퍼).


****  

|  |  | 
| --- |--- |
|  헤더  |   [https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h](https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/json/JsonSerializer.h)   | 
|  API 설명서  |   [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_json_1_1_json_value.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/class_aws_1_1_utils_1_1_json_1_1_json_value.html)   | 

## XML 파서
<a name="xml-parser"></a>

경량 XML 파서입니다(*`tinyxml2`*의 얇은 래퍼). [RAII 패턴](http://en.cppreference.com/w/cpp/language/raii)이 인터페이스에 추가되었습니다.


****  

|  |  | 
| --- |--- |
|  헤더  |   [https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h](https://github.com/aws/aws-sdk-cpp/tree/master/aws-cpp-sdk-core/include/aws/core/utils/xml/XmlSerializer.h)   | 
|  API 설명서  |   [https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/namespace_aws_1_1_utils_1_1_xml.html](https://docs.aws.amazon.com/sdk-for-cpp/latest/api/aws-cpp-sdk-core/html/namespace_aws_1_1_utils_1_1_xml.html)   | 

# 의 메모리 관리 AWS SDK for C\$1\$1
<a name="memory-management"></a>

는 라이브러리에서 메모리 할당 및 할당 해제를 제어하는 방법을 AWS SDK for C\$1\$1 제공합니다.

**참고**  
사용자 지정 메모리 관리는 정의된 컴파일 시간 상수 `USE_AWS_MEMORY_MANAGEMENT`를 사용하여 빌드된 라이브러리 버전을 사용하는 경우에만 사용할 수 있습니다.  
컴파일 시간 상수 없이 빌드된 라이브러리 버전을 사용하는 경우에는 `InitializeAWSMemorySystem`과 같은 글로벌 메모리 시스템 함수가 작동하지 않으며, 대신 글로벌 `new` 및 `delete` 함수가 사용됩니다.

컴파일 시간 상수에 대한 자세한 내용은 [STL, AWS 문자열 및 벡터를 참조하세요](#stl-and-aws-strings-and-vectors).

## 메모리 할당 및 할당 해제
<a name="allocating-and-deallocating-memory"></a>

 **메모리를 할당하거나 할당 해제하려면** 

1. 하위 클래스 `MemorySystemInterface`: `aws/core/utils/memory/MemorySystemInterface.h`.

   ```
   class MyMemoryManager : public Aws::Utils::Memory::MemorySystemInterface
   {
   public:
       // ...
       virtual void* AllocateMemory(
           std::size_t blockSize, std::size_t alignment,
           const char *allocationTag = nullptr) override;
       virtual void FreeMemory(void* memoryPtr) override;
   };
   ```
**참고**  
필요에 따라 `AllocateMemory`에 대한 유형 서명을 변경할 수 있습니다.

1. `Aws::SDKOptions` 구조체를 사용하여 사용자 지정 메모리 관리자 사용을 구성합니다. 구조체의 인스턴스를 `Aws::InitAPI`로 전달합니다. 애플리케이션을 종료하기 전에 동일한 인스턴스로 `Aws::ShutdownAPI`를 직접 호출하여 SDK를 종료해야 합니다.

   ```
   int main(void)
   {
     MyMemoryManager sdkMemoryManager;
     SDKOptions options;
     options.memoryManagementOptions.memoryManager = &sdkMemoryManager;
     Aws::InitAPI(options);
   
     // ... do stuff
   
     Aws::ShutdownAPI(options);
   
     return 0;
   }
   ```

## STL, AWS 문자열 및 벡터
<a name="stl-and-aws-strings-and-vectors"></a>

메모리 관리자로 초기화되면 AWS SDK for C\$1\$1 는 메모리 관리자에 대한 모든 할당 및 할당 해제를 연기합니다. 메모리 관리자가 없는 경우 SDK는 글로벌 new 및 delete를 사용합니다.

사용자 지정 STL 할당기를 사용하는 경우 할당 정책과 일치하도록 모든 STL 객체의 유형 서명을 변경해야 합니다. SDK 구현 및 인터페이스에서는 STL이 주로 사용되므로, SDK 내에서 단일 접근 방식을 채택할 경우 기본 STL 객체를 SDK로 직접 전달하거나 STL 할당을 제어하는 것이 제한될 수 있습니다. 대안으로, 내부적으로는 사용자 지정 할당기를 사용하고 인터페이스에서는 표준 및 사용자 지정 STL 객체를 허용하는 하이브리드 접근 방식은 메모리 문제 조사에 더 어려움을 초래할 수 있습니다.

해결 방법은 메모리 시스템의 컴파일 시간 상수 `USE_AWS_MEMORY_MANAGEMENT`를 사용하여 SDK에서 사용하는 STL 유형을 제어하는 것입니다.

컴파일 시간 상수가 활성화된 경우(켜짐) 유형은 AWS 메모리 시스템에 연결된 사용자 지정 할당자를 사용하여 STL 유형으로 확인됩니다.

컴파일 시간 상수가 비활성화(꺼짐)된 경우 모든 `Aws::*` 유형은 해당하는 기본 `std::*` 유형으로 확인됩니다.

 **SDK의 `AWSAllocator.h` 파일에서 가져온 코드 예제** 

```
#ifdef USE_AWS_MEMORY_MANAGEMENT

template< typename T >
class AwsAllocator : public std::allocator< T >
{
   ... definition of allocator that uses AWS memory system
};

#else

template< typename T > using Allocator = std::allocator<T>;

#endif
```

예제 코드에서 `AwsAllocator`는 컴파일 시간 상수에 따라 사용자 지정 할당기 또는 기본 할당기일 수 있습니다.

 **SDK의 `AWSVector.h` 파일에서 가져온 코드 예제** 

```
template<typename T> using Vector = std::vector<T, Aws::Allocator<T>>;
```

예제 코드에서는 `Aws::*` 유형을 정의합니다.

컴파일 시간 상수가 활성화된 경우(켜짐) 유형은 사용자 지정 메모리 할당 및 AWS 메모리 시스템을 사용하여 벡터에 매핑됩니다.

컴파일 시간 상수가 비활성화(꺼짐)된 경우 유형은 기본 유형 파라미터를 사용하는 일반 `std::vector`에 매핑됩니다.

유형 별칭 지정은 컨테이너, 문자열 스트림, 문자열 버퍼 등 메모리 할당을 수행하는 SDK의 모든 `std::` 유형에 사용됩니다. 는 이러한 유형을 AWS SDK for C\$1\$1 사용합니다.

## 남아 있는 문제
<a name="remaining-issues"></a>

메모리 할당은 SDK에서 제어할 수 있지만, STL 유형은 여전히 모델 객체 `initialize` 및 `set` 메서드에 대한 문자열 파라미터를 통해 퍼블릭 인터페이스의 주요 비중을 차지합니다. STL을 사용하지 않고 문자열과 컨테이너를 대신 사용한다면 서비스 직접 호출을 수행할 때마다 많은 임시 객체를 생성해야 합니다.

STL이 아닌 방식으로 서비스 직접 호출을 수행할 때 발생하는 임시 객체와 할당을 대부분 제거하기 위해 다음과 같이 구현했습니다.
+ 문자열을 사용하는 모든 Init/Set 함수에는 `const char*`를 사용하는 오버로드가 있습니다.
+ 컨테이너(맵/벡터)를 사용하는 모든 Init/Set 함수에는 단일 항목을 사용하는 add 변형이 있습니다.
+ 바이너리 데이터를 사용하는 모든 Init/Set 함수에는 데이터 포인터와 `length` 값을 사용하는 오버로드가 있습니다.
+ (선택 사항) 문자열을 사용하는 모든 Init/Set 함수에는 0 종단이 아닌 `const char*` 및 `length` 값을 사용하는 오버로드가 있습니다.

## 네이티브 SDK 개발자 및 메모리 제어
<a name="native-sdk-developers-and-memory-controls"></a>

SDK 코드에서는 다음 규칙을 따릅니다.
+ `new` 및 `delete`를 대신해서 `Aws::New<>` 및 `Aws::Delete<>`를 사용합니다.
+ `new[]` 및 `delete[]`를 대신해서 `Aws::NewArray<>` 및 `Aws::DeleteArray<>`를 사용합니다.
+ `std::make_shared`을 대신해서 `Aws::MakeShared`를 사용합니다.
+ 단일 객체에 대한 고유 포인터에 `Aws::UniquePtr`을 사용합니다. 고유 포인터를 생성하려면 `Aws::MakeUnique` 함수를 사용합니다.
+ 객체 배열에 대한 고유 포인터에 `Aws::UniqueArray`를 사용합니다. 고유 포인터를 생성하려면 `Aws::MakeUniqueArray` 함수를 사용합니다.
+ STL 컨테이너를 직접 사용하지 말고, `Aws::` typedef 중 하나를 사용하거나 원하는 컨테이너에 대한 typedef를 추가합니다. 예제:

  ```
  Aws::Map<Aws::String, Aws::String> m_kvPairs;
  ```
+ SDK로 전달되어 관리되는 모든 외부 포인터에 `shared_ptr`을 사용합니다. 객체 할당 방식과 일치하는 폐기 정책으로 공유 포인터를 초기화해야 합니다. SDK가 포인터를 정리하지 않을 것으로 예상되는 경우 원시 포인터를 사용할 수 있습니다.

# AWS SDK for C\$1\$1에서 오류 처리
<a name="error-handling"></a>

AWS SDK for C\$1\$1는 예외를 사용하지 않지만 코드에 예외를 사용할 수 있습니다. 모든 서비스 클라이언트는 결과와 오류 코드가 포함된 결과 객체를 반환합니다.

 **오류 조건 처리 예제** 

```
bool CreateTableAndWaitForItToBeActive()
{
  CreateTableRequest createTableRequest;
  AttributeDefinition hashKey;
  hashKey.SetAttributeName(HASH_KEY_NAME);
  hashKey.SetAttributeType(ScalarAttributeType::S);
  createTableRequest.AddAttributeDefinitions(hashKey);
  KeySchemaElement hashKeySchemaElement;
  hashKeySchemaElement.WithAttributeName(HASH_KEY_NAME).WithKeyType(KeyType::HASH);
  createTableRequest.AddKeySchema(hashKeySchemaElement);
  ProvisionedThroughput provisionedThroughput;
  provisionedThroughput.SetReadCapacityUnits(readCap);
  provisionedThroughput.SetWriteCapacityUnits(writeCap);
  createTableRequest.WithProvisionedThroughput(provisionedThroughput);
  createTableRequest.WithTableName(tableName);

  CreateTableOutcome createTableOutcome = dynamoDbClient->CreateTable(createTableRequest);
  if (createTableOutcome.IsSuccess())
  {
     DescribeTableRequest describeTableRequest;
     describeTableRequest.SetTableName(tableName);
     bool shouldContinue = true;
     DescribeTableOutcome outcome = dynamoDbClient->DescribeTable(describeTableRequest);

     while (shouldContinue)
     {
         if (outcome.GetResult().GetTable().GetTableStatus() == TableStatus::ACTIVE)
         {
            break;
         }
         else
         {
            std::this_thread::sleep_for(std::chrono::seconds(1));
         }
     }
     return true;
  }
  else if(createTableOutcome.GetError().GetErrorType() == DynamoDBErrors::RESOURCE_IN_USE)
  {
     return true;
  }

  return false;
}
```