

 AWS SDK for .NET V3가 유지 관리 모드로 전환되었습니다.

[AWS SDK for .NET V4](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/welcome.html)로 마이그레이션하는 것이 좋습니다. 마이그레이션 방법에 대한 자세한 내용과 정보는 [유지 관리 모드 공지](https://aws.amazon.com/blogs/developer/aws-sdk-for-net-v3-maintenance-mode-announcement/)를 참조하세요.

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

# AWS SDK for .NET의 기능
<a name="net-dg-sdk-features"></a>

이 섹션에서는 애플리케이션을 만들 때 고려해야 할 수 있는 AWS SDK for .NET의 기능에 대한 정보를 제공합니다.

먼저 [프로젝트를 설정](net-dg-config.md)했는지 확인하세요.

코드 예제와 함께 특정 AWS 서비스용 소프트웨어 개발에 대한 자세한 내용은 [ AWS 서비스 작업](working-with-aws-services.md) 단원을 참조하세요. 추가 코드 예제는 [SDK for .NET 코드 예제](csharp_code_examples.md) 단원을 참조하세요.

**Topics**
+ [비동기식 API](sdk-net-async-api.md)
+ [재시도 및 제한 시간](retries-timeouts.md)
+ [페이지네이터](paginators.md)
+ [관찰성](observability.md)
+ [추가 도구](sdk-features-additional-tools.md)

# AWS.NET용 비동기식 API
<a name="sdk-net-async-api"></a>

AWS SDK for .NET는 비동기 구현을 위해 *작업 기반 비동기식 패턴(TAP)*을 사용합니다. TAP에 대한 자세한 내용은 docs.microsoft.com의 [작업 기반 비동기식 패턴(TAP)](https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap)을 참조하세요.

이 주제에서는 AWS 서비스 클라이언트에 대한 호출에서 TAP를 사용하는 방법의 개요를 제공합니다.

AWS SDK for .NET API의 비동기 메서드는 `Task` 클래스 또는 `Task<TResult>` 클래스를 기반으로 하는 작업입니다. [Task 클래스](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task), [Task<TResult> 클래스](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1)와 같은 클래스에 대한 자세한 내용은 docs.microsoft.com을 참조하세요.

코드에서 이러한 API 메서드를 호출할 때는 다음 예제와 같이 `async` 키워드로 선언된 함수 내에서 호출해야 합니다.

```
static async Task Main(string[] args)
{
  ...
  // Call the function that contains the asynchronous API method.
  // Could also call the asynchronous API method directly from Main
  //  because Main is declared async
  var response = await ListBucketsAsync();
  Console.WriteLine($"Number of buckets: {response.Buckets.Count}");
  ...
}

// Async method to get a list of Amazon S3 buckets.
private static async Task<ListBucketsResponse> ListBucketsAsync()
{
  ...
  var response = await s3Client.ListBucketsAsync();
  return response;
}
```

위 코드 조각에서 볼 수 있듯이 `async` 선언 시 선호되는 범위는 `Main` 함수입니다. 이 `async` 범위를 설정하면 AWS 서비스 클라이언트에 대한 모든 호출이 비동기식이어야 합니다. 어떤 이유로 `Main`을 비동기식으로 선언할 수 없는 경우 다음 예제와 같이 `async` 키워드를 `Main` 이외의 함수에서 사용한 다음 해당 함수에서 API 메서드를 호출할 수 있습니다.

```
static void Main(string[] args)
{
  ...
  Task<ListBucketsResponse> response = ListBucketsAsync();
  Console.WriteLine($"Number of buckets: {response.Result.Buckets.Count}");
  ...
}

// Async method to get a list of Amazon S3 buckets.
private static async Task<ListBucketsResponse> ListBucketsAsync()
{
  ...
  var response = await s3Client.ListBucketsAsync();
  return response;
}
```

이 패턴을 사용할 때 `Main`에서 필요한 특수 `Task<>` 구문에 유의해야 합니다. 또한 데이터를 가져오려면 응답의 **`Result`** 멤버를 사용해야 합니다.

AWS 서비스 클라이언트에 대한 비동기 호출의 전체 예는 [빠른 둘러보기](quick-start.md) 섹션([간단한 교차 플랫폼 앱](quick-start-s3-1-cross.md) 및 [간단한 Windows 기반 앱](quick-start-s3-1-winvs.md))과 [지침이 포함된 코드 예제개요 수준 라이브러리 및 프레임워크](tutorials-examples.md)에서 확인할 수 있습니다.

# 재시도 및 제한 시간
<a name="retries-timeouts"></a>

를 AWS SDK for .NET 사용하면 AWS 서비스에 대한 HTTP 요청의 재시도 횟수와 제한 시간 값을 구성할 수 있습니다. 재시도 횟수 및 제한 시간의 기본값이 해당 애플리케이션에 적절하지 않은 경우 특정 요구사항에 맞게 조정할 수 있지만, 그렇게 함으로써 해당 애플리케이션의 작동에 어떤 영향을 미칠지 먼저 이해하는 것이 중요합니다.

재시도 횟수 및 제한 시간에 어떤 값을 사용할지 결정하려면 다음 사항을 고려하십시오.
+ 네트워크 연결이 저하되거나 AWS 서비스에 연결할 수 없는 경우 AWS SDK for .NET 및 애플리케이션은 어떻게 응답해야 합니까? 호출이 신속하게 실패하길 원하는가, 아니면 호출이 사용자를 대신하여 계속 재시도하는 것이 적절한가?
+ 해당 애플리케이션은 응답이 필수적인 사용자 지향 애플리케이션이나 웹 사이트인가, 아니면 지연 시간 증가를 더 많이 허용하는 백그라운드 처리 작업인가?
+ 애플리케이션이 지연 시간이 짧은 안정적인 네트워크에 배포되는가, 아니면 연결성이 불안정한 원격 위치에 배포되는가?

## 재시도
<a name="retries"></a>

### 개요
<a name="w2aac11c13c11b5"></a>

는 서버 측 제한 또는 연결 끊김으로 인해 실패한 요청을 재시도할 AWS SDK for .NET 수 있습니다. 서비스 구성 클래스에는 서비스 클라이언트의 재시도 동작을 지정하는 데 사용할 수 있는 두 가지 속성이 있습니다. 서비스 구성 클래스는 [AWS SDK for .NET API 참조](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/)의 추상 [Amazon.Runtime.ClientConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TClientConfig.html) 클래스에서 다음과 같은 속성을 상속합니다.
+ `RetryMode`는 [Amazon.Runtime.RequestRetryMode](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TRequestRetryMode.html) 열거에 정의된 세 가지 재시도 모드 중 하나를 지정합니다.

  애플리케이션의 기본값은 `AWS_RETRY_MODE` 환경 변수 또는 공유 AWS 구성 파일의 *retry\$1mode* 설정을 사용하여 제어할 수 있습니다.
+ `MaxErrorRetry`는 서비스 클라이언트 수준에서 허용되는 재시도 횟수를 지정합니다. SDK는 작업이 실패하고 예외가 발생하기 전에 지정된 횟수만큼 작업을 재시도합니다.

  애플리케이션의 기본값은 `AWS_MAX_ATTEMPTS` 환경 변수 또는 공유 AWS 구성 파일의 *max\$1attempts* 설정을 사용하여 제어할 수 있습니다.

이러한 속성에 대한 자세한 설명은 [AWS SDK for .NET API 참조](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/)의 추상 [Amazon.Runtime.ClientConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TClientConfig.html) 클래스에서 확인할 수 있습니다. `RetryMode`의 각 값은 기본적으로 다음 표에 표시된 것처럼 `MaxErrorRetry`의 특정 값에 해당합니다.

|  |  |  | 
| --- |--- |--- |
| Legacy | 10 | 4 | 
| Standard | 10 | 2 | 
| Adaptive (experimental) | 10 | 2 | 

### 동작
<a name="w2aac11c13c11b9"></a>

**애플리케이션이 시작되는 시점**

애플리케이션이 시작되면 SDK에서 `RetryMode` 및 `MaxErrorRetry`의 기본값을 구성합니다. 이러한 기본값은 다른 값을 지정하지 않는 한 서비스 클라이언트를 생성할 때 사용됩니다.
+ 환경에 속성이 설정되지 않은 경우 `RetryMode`의 기본값은 레거시로 구성되고 `MaxErrorRetry`의 기본값은 위 표의 해당 값으로 구성됩니다.**
+ 환경에서 재시도 모드가 설정된 경우 해당 값이 `RetryMode`의 기본값으로 사용됩니다. 환경에 최대 오류 값도 설정되어 있지 않은 경우(다음 설명 참조) `MaxErrorRetry`의 기본값은 위 표의 해당 값으로 구성됩니다.
+ 환경에서 최대 오류 값이 설정된 경우 해당 값이 `MaxErrorRetry`의 기본값으로 사용됩니다. Amazon DynamoDB는 이 규칙의 예외입니다. `MaxErrorRetry`에 대한 DynamoDB의 기본 값은 항상 위 표의 값입니다.

**애플리케이션이 실행될 때**

서비스 클라이언트를 생성할 때 앞에서 설명한 대로 `RetryMode` 및 `MaxErrorRetry`의 기본값을 사용하거나 다른 값을 지정할 수 있습니다. 다른 값을 지정하려면 서비스 클라이언트를 생성할 때 [AmazonDynamoDBConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/DynamoDBv2/TDynamoDBConfig.html) 또는 [AmazonSQSConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/SQS/TSQSConfig.html)와 같은 서비스 구성 객체를 생성하여 포함시킵니다.

서비스 클라이언트가 생성된 이후에는 그 값을 바꿀 수 없습니다.

**고려 사항**

재시도가 이루어지면 해당 요청의 지연 시간이 늘어납니다. 총 요청 지연 시간 및 오류율에 대한 애플리케이션의 제한에 따라 재시도를 구성해야 합니다.

## 시간 초과
<a name="timeouts"></a>

를 AWS SDK for .NET 사용하면 서비스 클라이언트 수준 및 메서드 호출당 요청 제한 시간을 구성할 수 있습니다. 제한 시간을 구성하는 두 가지 메커니즘이 있으며, 이는 후속 섹션에서 다룹니다.
+ [비동기 직접 호출](#timeouts-async)을 사용하는 경우 메서드의 `CancellationToken` 파라미터를 사용할 수 있습니다.
+ [.NET Framework에서 동기 직접 호출](#timeouts-sync-framework)을 사용하는 경우 추상 [Amazon.Runtime.ClientConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TClientConfig.html) 클래스의 `Timeout` 및 `ReadWriteTimeout` 속성을 사용할 수 있습니다.

### 제한 시간에 `CancellationToken` 파라미터 사용
<a name="timeouts-async"></a>

를 AWS SDK for .NET 사용하면 `CancellationToken` 파라미터를 사용하여 비동기 호출에 대한 요청 제한 시간을 구성할 수 있습니다. 다음 코드 조각은 예제를 보여 줍니다. 요청이 10초 이내에 완료되지 않으면 코드에서 `System.Threading.Tasks.TaskCanceledException`이 발생합니다.

```
string bucketName = "amzn-s3-demo-bucket";
string path = "pathToBucket";
using (var amazonS3Client = new AmazonS3Client(new AmazonS3Config()))
{
    // Cancel request after 10 seconds
    CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(10000));
    CancellationToken cancellationToken = cancellationTokenSource.Token;
    ListObjectsV2Request listRequestV2 = new()
    {
        BucketName = bucketName,
        Prefix = path,
    };

    ListObjectsV2Response listResponseV2 = await amazonS3Client.ListObjectsV2Async(listRequestV2, cancellationToken);
}
```

### 제한 시간에 `Timeout` 및 `ReadWriteTimeout` 속성 사용
<a name="timeouts-sync-framework"></a>

**참고**  
`Timeout` 속성은 비동기 직접 호출에 영향을 주지 않습니다. 비동기 직접 호출을 사용하는 경우 [제한 시간에 `CancellationToken` 파라미터 사용](#timeouts-async)을 대신 참조하세요.

를 AWS SDK for .NET 사용하면 서비스 클라이언트 수준에서 요청 제한 시간 및 소켓 읽기/쓰기 제한 시간 값을 구성할 수 있습니다. 이러한 값은 추상 [Amazon.Runtime.ClientConfig](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TClientConfig.html) 클래스의 `Timeout` 및 `ReadWriteTimeout` 속성에 지정됩니다. 이러한 값은 AWS 서비스 클라이언트 객체에 의해 생성된 [HttpWebRequest](https://learn.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest) 객체의 `Timeout` 및 `ReadWriteTimeout` 속성으로 전달됩니다. `Timeout` 값은 100초, `ReadWriteTimeout` 값은 300초로 기본 설정되어 있습니다.

해당 네트워크의 지연 시간이 길거나 작업 재시도를 유발하는 조건이 존재하는 경우 제한 시간 및 재시도 횟수의 값을 높이면 일부 SDK 작업이 응답하지 않는 것처럼 보일 수 있습니다.

**참고**  
휴대용 클래스 라이브러리(PCL)를 대상으로 AWS SDK for .NET 하는의 버전은 클래스 대신 [HttpClient](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient) `HttpWebRequest` 클래스를 사용하며 [제한 시간](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout) 속성만 지원합니다.

다음은 기본 설정된 제한 시간 값에 대한 예외입니다. 제한 시간 값을 명시적으로 설정하면 이 값들은 무시됩니다.
+ `Timeout` 및 `ReadWriteTimeout`은 호출되는 메서드가 [AmazonS3Client.PutObjectAsync()](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/MS3PutObjectAsyncPutObjectRequestCancellationToken.html), [AmazonS3Client.UploadPartAsync()](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/MS3UploadPartAsyncUploadPartRequestCancellationToken.html), [AmazonGlacierClient.UploadArchiveAsync()](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Glacier/MGlacierUploadArchiveAsyncUploadArchiveRequestCancellationToken.html)와 같은 스트림을 업로드하는 경우 최대값으로 설정됩니다.
+ .NET Framework를 대상으로 AWS SDK for .NET 하는의 버전은 `Timeout` 및 `ReadWriteTimeout`를 모든 [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/TS3Client.html) 및 [AmazonGlacierClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Glacier/TGlacierClient.html) 객체의 최대값으로 설정합니다.
+ 휴대용 클래스 라이브러리(PCL) 및 .NET Core를 대상으로 AWS SDK for .NET 하는의 버전은 모든 [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/TS3Client.html) 및 [AmazonGlacierClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Glacier/TGlacierClient.html) 객체의 최대값`Timeout`으로 설정됩니다.

다음 예제에서는 *표준* 재시도 모드, 최대 3회의 재시도, 제한 시간 10초, 쓰기/읽기 제한 시간 10초를 지정하는 방법을 보여줍니다(해당하는 경우). [AmazonS3Client](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/TS3Client.html) 생성자에는 [AmazonS3Config](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/TS3Config.html) 객체가 제공됩니다.

```
var s3Client = new AmazonS3Client(
  new AmazonS3Config
  {
    Timeout = TimeSpan.FromSeconds(10),
    // NOTE: The following property is obsolete for
    //       versions of the AWS SDK for .NET that target .NET Core.
    ReadWriteTimeout = TimeSpan.FromSeconds(10),
    RetryMode = RequestRetryMode.Standard,
    MaxErrorRetry = 3
  });
```

# 페이지네이터
<a name="paginators"></a>

일부 AWS 서비스는 대량의 데이터를 수집 및 저장하는데, 이러한 데이터는 AWS SDK for .NET의 API 직접 호출을 사용하여 검색할 수 있습니다. 검색하려는 데이터 양이 단일 API 직접 호출로 너무 많아지면 *페이지 매김*을 사용하여 결과를 관리하기 쉬운 부분으로 나눌 수 있습니다.

페이지 매김을 수행할 수 있도록 SDK의 여러 서비스 클라이언트에 대한 요청 및 응답 객체는 *연속 토큰*(일반적으로 `NextToken`으로 이름이 지정됨)을 제공합니다. 이러한 서비스 클라이언트 중 일부는 **페이지네이터**도 제공합니다.

페이지네이터를 사용하면 루프, 상태 변수, 다중 API 직접 호출 등이 포함될 수 있는 연속 토큰의 오버헤드를 피할 수 있습니다. 페이지네이터를 사용하면 한 줄의 코드인 `foreach` 루프 선언을 통해 AWS 서비스에서 데이터를 검색할 수 있습니다. 데이터를 검색하는 데 여러 API 직접 호출이 필요한 경우 페이지네이터가 이를 자동으로 처리합니다.

## 페이지네이터는 어디서 찾을 수 있나요?
<a name="paginators-find-them"></a>

모든 서비스가 페이지네이터를 제공하는 것은 아닙니다. 서비스가 특정 API에 페이지네이터를 제공하는지 여부를 확인하는 한 가지 방법은 [AWS SDK for .NET API 참조](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/)에서 서비스 클라이언트 클래스의 정의를 살펴보는 것입니다.

예를 들어 [AmazonCloudWatchLogsClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TCloudWatchLogsClient.html) 클래스의 정의를 검토하면 `Paginators` 속성이 표시됩니다. 이는 Amazon CloudWatch Logs의 페이지네이터를 제공하는 속성입니다.

## 페이지네이터는 무엇을 제공합니까?
<a name="paginators-use-them"></a>

페이지네이터에는 전체 응답을 볼 수 있는 속성이 있습니다. 또한 일반적으로 응답의 가장 흥미로운 부분에 액세스할 수 있는 하나 이상의 속성이 포함되어 있는데, 이를 *핵심 결과*라고 합니다.

예를 들어 앞서 언급한 `AmazonCloudWatchLogsClient`에서 `Paginator` 객체에는 API 직접 호출에서 가져온 전체 [DescribeLogGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsResponse.html) 객체가 포함된 `Responses` 속성이 포함되어 있습니다. 이 `Responses` 속성에는 무엇보다도 로그 그룹 컬렉션이 포함되어 있습니다.

페이지네이터 객체에는 `LogGroups`로 이름이 지정된 하나의 주요 결과도 포함되어 있습니다. 이 속성은 응답의 로그 그룹 부분만 포함합니다. 이 주요 결과를 통해 많은 상황에서 코드를 줄이고 단순화할 수 있습니다.

## 동기 페이지 매김과 비동기 페이지 매김 비교
<a name="paginators-sync-async"></a>

페이지네이터는 동기 및 비동기 페이지 매김 메커니즘을 모두 제공합니다. .NET Framework 4.7.2(또는 그 이상) 프로젝트에서 동기화 페이지 매김을 사용할 수 있습니다. 비동기 페이지 매김은 .NET Core 프로젝트(.NET Core 3.1, .NET 5 등)에서 사용할 수 있습니다.

비동기 작업과 .NET Core가 권장되므로 다음 예제에서는 비동기 페이지 매김을 보여줍니다. 동기 페이지 매김 및 .NET Framework 4.7.2(또는 그 이상)를 사용하여 동일한 작업을 수행하는 방법에 대한 정보는 [페이지네이터에 관한 추가 고려 사항](#paginators-additional)의 예제 다음에 나와 있습니다.

## 예시
<a name="paginators-example"></a>

다음 예에서는 AWS SDK for .NET에서 로그 그룹 목록을 표시하는 방법을 보여줍니다. 반대로 이 예에서는 페이지 매김을 사용하거나 사용하지 않고 이 작업을 수행하는 방법을 보여줍니다. 나중에 보여드릴 전체 코드를 살펴보기 전에 다음 스니펫을 살펴보세요.

**페이지네이터가 없는 CloudWatch 로그 그룹 가져오기**

```
      // Loop as many times as needed to get all the log groups
      var request = new DescribeLogGroupsRequest{Limit = LogGroupLimit};
      do
      {
        Console.WriteLine($"Getting up to {LogGroupLimit} log groups...");
        var response = await cwClient.DescribeLogGroupsAsync(request);
        foreach(var logGroup in response.LogGroups)
        {
          Console.WriteLine($"{logGroup.LogGroupName}");
        }
        request.NextToken = response.NextToken;
      } while(!string.IsNullOrEmpty(request.NextToken));
```

**페이지네이터를 사용한 CloudWatch 로그 그룹 가져오기**

```
      // No need to loop to get all the log groups--the SDK does it for us behind the scenes
      var paginatorForLogGroups =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(var logGroup in paginatorForLogGroups.LogGroups)
      {
        Console.WriteLine(logGroup.LogGroupName);
      }
```

이 두 스니펫의 결과는 완전히 동일하므로 페이지네이터를 사용할 때의 이점을 분명히 확인할 수 있습니다.

**참고**  
전체 코드를 빌드하고 실행하기 전에 [환경과 프로젝트를 설정](net-dg-config.md)했는지 확인하세요.  
비동기 페이지네이터가 `IAsyncEnumerable` 인터페이스를 사용하기 때문에 [Microsoft.Bcl.AsyncInterfaces](https://www.nuget.org/packages/Microsoft.Bcl.AsyncInterfaces/) NuGet 패키지가 필요할 수도 있습니다.

### 전체 코드
<a name="paginators-complete-code"></a>

이 섹션에는 이 예제에 대한 관련 참조와 전체 코드가 나와 있습니다.

#### SDK 레퍼런스
<a name="w2aac11c15c23c19b5b1"></a>

NuGet 패키지:
+ [AWSSDK.CloudWatch](https://www.nuget.org/packages/AWSSDK.CloudWatch)

프로그래밍 요소:
+ 네임스페이스 [Amazon.CloudWatch](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatch/NCloudWatch.html)

  클래스 [AmazonCloudWatchLogsClient](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TCloudWatchLogsClient.html)
+ 네임스페이스 [Amazon.CloudWatchLogs.Model](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/NCloudWatchLogsModel.html)

  클래스 [DescribeLogGroupsRequest](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsRequest.html)

  클래스 [DescribeLogGroupsResponse](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TDescribeLogGroupsResponse.html)

  클래스 [LogGroup](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/CloudWatchLogs/TLogGroup.html)

#### 전체 코드
<a name="w2aac11c15c23c19b7b1"></a>

```
using System;
using System.Threading.Tasks;
using Amazon.CloudWatchLogs;
using Amazon.CloudWatchLogs.Model;

namespace CWGetLogGroups
{
  class Program
  {
    // A small limit for demonstration purposes
    private const int LogGroupLimit = 3;

    //
    // Main method
    static async Task Main(string[] args)
    {
      var cwClient = new AmazonCloudWatchLogsClient();
      await DisplayLogGroupsWithoutPaginators(cwClient);
      await DisplayLogGroupsWithPaginators(cwClient);
    }


    //
    // Method to get CloudWatch log groups without paginators
    private static async Task DisplayLogGroupsWithoutPaginators(IAmazonCloudWatchLogs cwClient)
    {
      Console.WriteLine("\nGetting list of CloudWatch log groups without using paginators...");
      Console.WriteLine("------------------------------------------------------------------");

      // Loop as many times as needed to get all the log groups
      var request = new DescribeLogGroupsRequest{Limit = LogGroupLimit};
      do
      {
        Console.WriteLine($"Getting up to {LogGroupLimit} log groups...");
        DescribeLogGroupsResponse response = await cwClient.DescribeLogGroupsAsync(request);
        foreach(LogGroup logGroup in response.LogGroups)
        {
          Console.WriteLine($"{logGroup.LogGroupName}");
        }
        request.NextToken = response.NextToken;
      } while(!string.IsNullOrEmpty(request.NextToken));
    }


    //
    // Method to get CloudWatch log groups by using paginators
    private static async Task DisplayLogGroupsWithPaginators(IAmazonCloudWatchLogs cwClient)
    {
      Console.WriteLine("\nGetting list of CloudWatch log groups by using paginators...");
      Console.WriteLine("-------------------------------------------------------------");

      // Access the key results; i.e., the log groups
      // No need to loop to get all the log groups--the SDK does it for us behind the scenes
      Console.WriteLine("\nFrom the key results...");
      Console.WriteLine("------------------------");
      IDescribeLogGroupsPaginator paginatorForLogGroups =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(LogGroup logGroup in paginatorForLogGroups.LogGroups)
      {
        Console.WriteLine(logGroup.LogGroupName);
      }

      // Access the full response
      // Create a new paginator, do NOT reuse the one from above
      Console.WriteLine("\nFrom the full response...");
      Console.WriteLine("--------------------------");
      IDescribeLogGroupsPaginator paginatorForResponses =
        cwClient.Paginators.DescribeLogGroups(new DescribeLogGroupsRequest());
      await foreach(DescribeLogGroupsResponse response in paginatorForResponses.Responses)
      {
        Console.WriteLine($"Content length: {response.ContentLength}");
        Console.WriteLine($"HTTP result: {response.HttpStatusCode}");
        Console.WriteLine($"Metadata: {response.ResponseMetadata}");
        Console.WriteLine("Log groups:");
        foreach(LogGroup logGroup in response.LogGroups) 
        {
          Console.WriteLine($"\t{logGroup.LogGroupName}");
        }
      }
    }
  }
}
```

## 페이지네이터에 관한 추가 고려 사항
<a name="paginators-additional"></a>
+ **페이지네이터는 두 번 이상 사용할 수 없음**

  코드의 여러 위치에 특정 AWS 페이지네이터를 적용한 결과가 필요한 경우 페이지네이터 객체를 두 번 이상 사용해서는 안 됩니다. 대신 필요할 때마다 새 페이지네이터를 만드세요. 이 개념은 `DisplayLogGroupsWithPaginators` 메서드의 이전 예제 코드에 나와 있습니다.
+ **동기식 페이지 매김**

  .NET Framework 4.7.2(또는 그 이상) 프로젝트에서 동기화 페이지 매김을 사용할 수 있습니다.
**주의**  
2024년 8월 15일부터 AWS SDK for .NET은 .NET Framework 3.5에 대한 지원을 종료하고 최소 .NET Framework 버전을 4.7.2로 변경합니다. 자세한 내용은 블로그 게시물 [AWS SDK for .NET의 .NET Framework 3.5 및 4.5 대상에 대한 중요 변경 사항](https://aws.amazon.com/blogs/developer/important-changes-coming-for-net-framework-3-5-and-4-5-targets-of-the-aws-sdk-for-net/)을 참조하세요.

  이를 확인하려면 .NET Framework 4.7.2(또는 이상) 프로젝트를 만들고 이전 코드를 여기에 복사하십시오. 다음 예제에 표시된 대로 두 개의 `foreach` 페이지네이터 호출에서 `await` 키워드를 제거하기만 하면 됩니다.

  ```
  /*await*/ foreach(var logGroup in paginatorForLogGroups.LogGroups)
  {
    Console.WriteLine(logGroup.LogGroupName);
  }
  ```

  프로젝트를 빌드하고 실행하면 비동기 페이지 매김으로 본 것과 동일한 결과를 확인할 수 있습니다.

# 관찰성
<a name="observability"></a>

관찰성은 시스템의 현재 상태를 내보내는 데이터에서 추론할 수 있는 범위입니다. 방출되는 데이터를 일반적으로 원격 측정이라고 합니다.

는 두 가지 일반적인 원격 측정 신호, 지표 및 추적과 로깅을 제공할 AWS SDK for .NET 수 있습니다. [TelemetryProvider](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TTelemetryProvider.html)를 연결하여 원격 측정 데이터를 관찰성 백엔드(예: [AWS X-Ray](https://docs.aws.amazon.com/xray/?icmpid=docs_homepage_devtools) 또는 [Amazon CloudWatch](https://docs.aws.amazon.com/cloudwatch/?icmpid=docs_homepage_mgmtgov))로 전송한 다음 조치를 취할 수 있습니다.

기본적으로 원격 측정 신호는 SDK에서 비활성화됩니다. 이 주제에서는 원격 측정 출력을 활성화하고 구성하는 방법을 설명합니다.

## 추가 리소스
<a name="observability-resources"></a>

관찰성 활성화 및 사용에 대한 자세한 내용은 다음 리소스를 참조하세요.
+ [OpenTelemetry](https://opentelemetry.io/)
+ 블로그 게시물 [Enhancing Observability in the AWS SDK for .NET with OpenTelemetry](https://aws.amazon.com/blogs/developer/enhancing-observability-in-the-aws-sdk-for-net-with-opentelemetry/).
+ 블로그 게시물 [Announcing the general availability of AWS .NET OpenTelemetry library](https://aws.amazon.com/blogs/dotnet/announcing-the-general-availability-of-aws-net-opentelemetry-libraries/).
+ [OpenTelemetry용 익스포터](https://opentelemetry.io/docs/languages/net/exporters/)
+ 의 관찰성 예제는 [Tools for PowerShell 사용 설명서](https://docs.aws.amazon.com/powershell/latest/userguide/)의 [관찰성을](https://docs.aws.amazon.com/powershell/latest/userguide/observability.html) AWS Tools for PowerShell참조하세요.

## `TelemetryProvider` 구성
<a name="observability-conf-telemetry-provider"></a>

다음 예제와 같이 모든 서비스 클라이언트 또는 개별 클라이언트에 대해 애플리케이션에서 `TelemetryProvider`를 전역적으로 구성할 수 있습니다. [원격 측정 공급자](observability-telemetry-providers.md) 섹션에는 SDK와 함께 제공되는 구현에 대한 정보를 포함하여 원격 측정 구현에 대한 정보가 포함되어 있습니다.

### 기본 글로벌 원격 측정 공급자 구성
<a name="observability-conf-telemetry-provider-global"></a>

기본적으로 모든 서비스 클라이언트는 전역적으로 사용 가능한 원격 측정 공급자를 사용하려고 시도합니다. 이렇게 하면 공급자를 한 번 설정할 수 있으며, 모든 클라이언트가 공급자를 사용합니다. 이 작업은 서비스 클라이언트를 생성하기 전에 한 번만 수행해야 합니다.

다음 코드 조각은 글로벌 원격 측정 공급자를 설정하는 방법을 보여 줍니다. 그런 다음 Amazon S3 서비스 클라이언트를 생성한 다음 실패하는 작업을 수행하려고 시도합니다. 코드는 애플리케이션에 추적 및 지표를 모두 추가합니다. 이 코드는 `OpenTelemetry.Exporter.Console` 및 `OpenTelemetry.Instrumentation.AWS`의 NuGet 패키지를 사용합니다.

**참고**  
인증 AWS IAM Identity Center 에를 사용하는 경우 `AWSSDK.SSO` 및 도 추가해야 합니다`AWSSDK.SSOOIDC`.

```
using Amazon.S3;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

Sdk.CreateTracerProviderBuilder()
    .ConfigureResource(e => e.AddService("DemoOtel"))
    .AddAWSInstrumentation()
    .AddConsoleExporter()
    .Build();

Sdk.CreateMeterProviderBuilder()
    .ConfigureResource(e => e.AddService("DemoOtel"))
    .AddAWSInstrumentation()
    .AddConsoleExporter()
    .Build();

var s3Client = new AmazonS3Client();

try
{
    var listBucketsResponse = await s3Client.ListBucketsAsync();
    // Attempt to delete a bucket that doesn't exist.
    var deleteBucketResponse = await s3Client.DeleteBucketAsync("amzn-s3-demo-bucket");
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Console.Read();
```

### 특정 서비스 클라이언트에 대한 원격 측정 공급자 구성
<a name="observability-conf-telemetry-provider-client"></a>

특정 원격 측정 공급자(글로벌 공급자 제외)를 사용하여 개별 서비스 클라이언트를 구성할 수 있습니다. 이렇게 하려면 서비스 클라이언트 생성자의 Config 객체 `TelemetryProvider` 클래스를 사용합니다. 예를 들어 [AmazonS3Config](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/S3/TS3Config.html)를 참조하고 `TelemetryProvider` 속성을 찾습니다. 사용자 지정 원격 측정 구현에 대한 자세한 내용은 [원격 측정 공급자](observability-telemetry-providers.md) 섹션을 참조하세요.

**Topics**
+ [추가 리소스](#observability-resources)
+ [`TelemetryProvider` 구성](#observability-conf-telemetry-provider)
+ [지표](observability-metrics.md)
+ [원격 측정 공급자](observability-telemetry-providers.md)

# 지표
<a name="observability-metrics"></a>

다음 표에는 SDK가 내보내는 원격 측정 지표가 나열되어 있습니다. 지표를 관찰할 수 있도록 [원격 측정 공급자를 구성](observability.md#observability-conf-telemetry-provider)합니다.


**어떤 지표가 내보내집니까?**  

| 메트릭 이름 | 단위 | 유형 | 속성 | 설명 | 
| --- | --- | --- | --- | --- | 
| client.call.duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 전체 통화 기간(재시도 및 요청 및 응답 본문을 보내거나 받는 시간 포함) | 
| client.uptime | s | 히스토그램(Histogram) | rpc.service | 클라이언트가 생성된 이후 경과한 시간 | 
| client.call.attempts | \$1attempt\$1 | MonotonicCounter | rpc.service, rpc.method | 개별 작업에 대한 시도 횟수 | 
| client.call.errors | \$1error\$1 | MonotonicCounter | rpc.service, rpc.method, exception.type | 작업의 오류 수 | 
| client.call.attempt\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 서비스에 연결하고, 요청을 보내고, HTTP 상태 코드 및 헤더를 다시 가져오는 데 걸리는 시간(전송 대기 시간 포함) | 
| client.call.resolve\$1endpoint\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 요청에 대한 엔드포인트(DNS가 아닌 엔드포인트 해석기)를 해결하는 데 걸리는 시간 | 
| client.call.serialization\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 메시지 본문을 직렬화하는 데 걸리는 시간 | 
| client.call.deserialization\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 메시지 본문을 역직렬화하는 데 걸리는 시간 | 
| client.call.auth.signing\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | 요청에 서명하는 데 걸리는 시간 | 
| client.call.auth.resolve\$1identity\$1duration | s | 히스토그램(Histogram) | rpc.service, rpc.method | ID 공급자로부터 ID(예: AWS 자격 증명 또는 보유자 토큰)를 획득하는 데 걸리는 시간 | 
| client.http.bytes\$1sent | By | MonotonicCounter | server.address | HTTP 클라이언트가 전송한 총 바이트 수 | 
| client.http.bytes\$1received | By | MonotonicCounter | server.address | HTTP 클라이언트가 수신한 총 바이트 수입니다. | 

다음은 열 설명입니다.
+ **지표 이름** - 내보낸 지표의 이름입니다.
+ **단위** - 지표의 측정 단위입니다. 단위는 [UCUM](https://unitsofmeasure.org/ucum) 대/소문자를 구분하는(‘c/s’) 표기법으로 제공됩니다.
+ **유형** - 지표를 캡처하는 데 사용되는 계측의 유형입니다.
+ **속성** - 지표와 함께 내보내지는 속성(차원) 세트입니다.
+ **설명** - 지표가 측정하는 항목에 대한 설명입니다.

# 원격 측정 공급자
<a name="observability-telemetry-providers"></a>

SDK는 [다음 섹션](observability-telemetry-providers-otel.md)에 설명된 원격 측정 공급자로 [OpenTelemetry](https://opentelemetry.io/)를 구현합니다.

특정 원격 측정 요구 사항이 있거나, 이미 원격 측정 솔루션을 염두에 두고 있거나, 원격 측정 데이터를 캡처하고 처리하는 방법을 세밀하게 제어해야 하는 경우 자체 원격 측정 공급자를 구현할 수도 있습니다.

[TelemetryProvider](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/Runtime/TTelemetryProvider.html) 클래스에 자체 구현을 등록합니다. 다음은 자체 `TracerProvider` 및 `MeterProvider`를 등록하는 방법의 간단한 예입니다.

```
using Amazon;
using Amazon.Runtime.Telemetry;
using Amazon.Runtime.Telemetry.Metrics;
using Amazon.Runtime.Telemetry.Tracing;

public class CustomTracerProvider : TracerProvider
{
    // Implement custom tracing logic here
}
public class CustomMeterProvider : MeterProvider
{
    // Implement custom metrics logic here
}

// Register custom implementations
AWSConfigs.TelemetryProvider.RegisterTracerProvider(new CustomTracerProvider());
AWSConfigs.TelemetryProvider.RegisterMeterProvider(new CustomMeterProvider());
```

**Topics**
+ [OpenTelemetry](observability-telemetry-providers-otel.md)

# OpenTelemetry 기반 원격 측정 공급자 구성
<a name="observability-telemetry-providers-otel"></a>

에는 OpenTelemetry 기반 원격 측정 공급자의 구현이 AWS SDK for .NET 포함되어 있습니다. 이 공급자를 글로벌 원격 측정 공급자로 설정하는 방법에 대한 자세한 내용은 [`TelemetryProvider` 구성](observability.md#observability-conf-telemetry-provider) 섹션을 참조하세요. 이 원격 측정 공급자를 사용하려면 프로젝트에 다음 리소스가 필요합니다.
+ [OpenTelemetry.Instrumentation.AWS](https://www.nuget.org/packages/OpenTelemetry.Instrumentation.AWS) NuGet 패키지입니다.
+ OTLP 또는 콘솔과 같은 원격 측정 익스포터입니다. 자세한 내용은 OpenTelemetry 설명서의 [익스포터](https://opentelemetry.io/docs/languages/net/exporters/) 섹션을 참조하세요.

SDK에 포함된 OpenTelemetry 구현은 HTTPS 요청, 자격 증명 및 압축에 대한 추적 양을 줄이도록 구성할 수 있습니다. 이렇게 하려면 다음과 같이 `SuppressDownstreamInstrumentation` 옵션을 `true`로 설정합니다.

```
Sdk.CreateTracerProviderBuilder()
    .ConfigureResource(e => e.AddService("DemoOtel"))
    .AddAWSInstrumentation(options => options.SuppressDownstreamInstrumentation = true)
    .AddConsoleExporter()
    .Build();
```

이 공급자에 대한 자세한 내용은 [ OpenTelemetry를 AWS SDK for .NET 사용하여의 관찰성 향상](https://aws.amazon.com/blogs/developer/enhancing-observability-in-the-aws-sdk-for-net-with-opentelemetry/) 블로그 게시물을 참조하세요.

# 추가 도구
<a name="sdk-features-additional-tools"></a>

다음은 .NET 애플리케이션을 쉽게 개발, 배포 및 유지 관리하는 데 사용할 수 있는 몇 가지 추가 도구입니다.

## AWS 배포 도구
<a name="sdk-features-deployment-tool"></a>

개발 머신에서 클라우드 네이티브 .NET Core 애플리케이션을 개발한 후에는 AWS Deploy Tool for .NET CLI를 사용하여 애플리케이션을 AWS에 보다 쉽게 배포할 수 있습니다.

자세한 내용은 [AWS에 애플리케이션 배포](deploying.md) 섹션을 참조하세요.

## .NET용 AWS 메시지 처리 프레임워크
<a name="sdk-features-msg-proc"></a>

Amazon SQS, Amazon SNS 또는 Amazon EventBridge와 같은 서비스를 사용하는 경우 .NET용 AWS 메시지 처리 프레임워크를 활용할 수 있습니다. 자세한 내용은 [.NET용 AWS 메시지 처리 프레임워크](msg-proc-fw.md) 섹션을 참조하세요.

## .NET Aspire와의 통합
<a name="sdk-features-aspire-integrations"></a>

.NET Aspire와의 통합을 활용하여 내부 개발 루프를 개선할 수 있습니다. 자세한 내용은 [AWS SDK for .NET에서 .NET Aspire와 AWS 통합](aspire-integrations.md) 섹션을 참조하세요.