Share via


.NET용 Azure SDK를 사용한 페이지 매김

이 문서에서는 .NET용 Azure SDK 페이지 매김 기능을 사용하여 대량의 데이터 세트를 효율적이고 생산적으로 작업하는 방법을 알아봅니다. 페이지 매김은 대량의 데이터 세트를 페이지로 나눠 소비자가 더 적은 양의 데이터를 더 쉽게 반복할 수 있도록 하는 동작입니다. C# 8부터 비동기 스트림을 사용하여 스트림을 비동기적으로 만들고 사용할 수 있습니다. 비동기 스트림은 IAsyncEnumerable<T> 인터페이스를 기반으로 합니다. .NET용 Azure SDK는 AsyncPageable<T> 클래스를 사용하여 IAsyncEnumerable<T>의 구현을 노출합니다.

이 문서의 모든 샘플은 다음 NuGet 패키지를 사용합니다.

.NET용 Azure SDK 패키지의 최신 디렉터리는 Azure SDK 최신 릴리스를 참조하세요.

Pageable 반환 형식

.NET용 Azure SDK에서 인스턴스화된 클라이언트는 다음과 같은 Pageable 형식을 반환할 수 있습니다.

Type 설명
Pageable<T> 페이지에서 검색된 값 컬렉션
AsyncPageable<T> 페이지에서 비동기적으로 검색된 값 컬렉션

이 문서의 샘플 대부분은 AsyncPageable<T> 형식의 변형을 사용하는 비동기적입니다. I/O 바인딩된 작업에는 비동기 프로그래밍을 사용하는 것이 바람직합니다. 완벽한 사용 사례는 .NET용 Azure SDK의 비동기 API를 사용하는 것인데, 이러한 작업은 HTTP/S 네트워크 호출을 나타내기 때문입니다.

await foreach를 사용하여 AsyncPageable 반복

await foreach 구문을 사용하여 AsyncPageable<T>를 반복하려면 다음 예제를 살펴보세요.

async Task IterateSecretsWithAwaitForeachAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    await foreach (SecretProperties secret in allSecrets)
    {
        Console.WriteLine($"IterateSecretsWithAwaitForeachAsync: {secret.Name}");
    }
}

위의 C# 코드에서:

  • SecretClient.GetPropertiesOfSecretsAsync 메서드가 호출되고 AsyncPageable<SecretProperties> 개체를 반환합니다.
  • await foreach 루프에서 각 SecretProperties는 비동기적으로 생성됩니다.
  • secret이 구체화되면 해당 Name이 콘솔에 기록됩니다.

while를 사용하여 AsyncPageable 반복

await foreach 구문을 사용할 수 없는 경우 AsyncPageable<T>을 반복하려면 while 루프를 사용합니다.

async Task IterateSecretsWithWhileLoopAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    IAsyncEnumerator<SecretProperties> enumerator = allSecrets.GetAsyncEnumerator();
    try
    {
        while (await enumerator.MoveNextAsync())
        {
            SecretProperties secret = enumerator.Current;
            Console.WriteLine($"IterateSecretsWithWhileLoopAsync: {secret.Name}");
        }
    }
    finally
    {
        await enumerator.DisposeAsync();
    }
}

위의 C# 코드에서:

AsyncPageable 페이지 반복

서비스에서 값 페이지 수신을 제어하려면 AsyncPageable<T>.AsPages 메서드를 사용합니다.

async Task IterateSecretsAsPagesAsync()
{
    AsyncPageable<SecretProperties> allSecrets = client.GetPropertiesOfSecretsAsync();

    await foreach (Page<SecretProperties> page in allSecrets.AsPages())
    {
        foreach (SecretProperties secret in page.Values)
        {
            Console.WriteLine($"IterateSecretsAsPagesAsync: {secret.Name}");
        }

        // The continuation token that can be used in AsPages call to resume enumeration
        Console.WriteLine(page.ContinuationToken);
    }
}

위의 C# 코드에서:

  • SecretClient.GetPropertiesOfSecretsAsync 메서드가 호출되고 AsyncPageable<SecretProperties> 개체를 반환합니다.
  • AsyncPageable<T>.AsPages 메서드가 호출되고 IAsyncEnumerable<Page<SecretProperties>>를 반환합니다.
  • 각 페이지는 await foreach를 사용하여 비동기적으로 반복됩니다.
  • 각 페이지에는 동기 foreach를 사용하여 반복되는 IReadOnlyList<T>를 나타내는 Page<T>.Values 세트가 있습니다.
  • 또한 각 페이지에는 다음 페이지를 요청하는 데 사용될 수 있는 Page<T>.ContinuationToken이 포함되어 있습니다.

AsyncPageableSystem.Linq.Async 사용

System.Linq.Async 패키지는 IAsyncEnumerable<T> 형식에서 작동하는 LINQ 메서드 세트를 제공합니다. AsyncPageable<T>IAsyncEnumerable<T>을 구현하므로 System.Linq.Async를 사용하여 데이터를 쿼리하고 변환할 수 있습니다.

List<T>로 변환

ToListAsync를 사용하여 AsyncPageable<T>List<T>로 변환합니다. 데이터가 단일 페이지로 반환되지 않는 경우 이 메서드를 수행하는 데 여러 번의 서비스 호출이 수행될 수 있습니다.

async Task ToListAsync()
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    List<SecretProperties> secretList = await allSecrets.ToListAsync();

    secretList.ForEach(secret =>
        Console.WriteLine($"ToListAsync: {secret.Name}"));
}

위의 C# 코드에서:

  • SecretClient.GetPropertiesOfSecretsAsync 메서드가 호출되고 AsyncPageable<SecretProperties> 개체를 반환합니다.
  • ToListAsync 메서드가 대기되어 새 List<SecretProperties> 인스턴스를 구체화합니다.

처음 N개 요소 사용

TakeAsyncPageable의 처음 N개 요소를 가져오는 데만 사용할 수 있습니다. Take를 사용하면 N개 항목을 가져오는 데 최소 서비스 호출 수가 필요합니다.

async Task TakeAsync(int count = 30)
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    await foreach (SecretProperties secret in allSecrets.Take(count))
    {
        Console.WriteLine($"TakeAsync: {secret.Name}");
    }
}

추가 메서드

System.Linq.Async는 동기 Enumerable 클래스와 같은 기능을 제공하는 다른 메서드를 제공합니다. 이러한 메서드의 예로는 Select, Where, OrderBy, GroupBy가 있습니다.

클라이언트 쪽 평가 주의

System.Linq.Async 패키지를 사용하는 경우 LINQ 작업이 클라이언트에서 실행되는지 주의해야 합니다. 다음 쿼리는 단지 개수를 세기 위해 ‘모든’ 항목을 페치합니다.

// ⚠️ DON'T DO THIS! 😲
int expensiveSecretCount =
    await client.GetPropertiesOfSecretsAsync()
        .CountAsync();

Warning

같은 경고가 Where와 같은 연산자에도 적용됩니다. 사용 가능한 경우 항상 서버 쪽 데이터 필터링, 집계 또는 프로젝션을 사용하세요.

관찰 가능한 시퀀스로

System.Linq.Async 패키지는 주로 IAsyncEnumerable<T> 시퀀스에 관찰자 패턴 기능을 제공하는 데 사용됩니다. 비동기 스트림은 풀을 기반으로 합니다. 해당 항목이 반복되므로 사용 가능한 다음 항목이 ‘풀링’됩니다. 이 접근 방식은 푸시 기반의 관찰자 패턴과 병치됩니다. 항목이 사용 가능해지면 관찰자 역할을 하는 구독자에게 ‘푸시’됩니다. System.Linq.Async 패키지는 IAsyncEnumerable<T>IObservable<T>로 변환할 수 있는 ToObservable 확장 메서드를 제공합니다.

IObserver<SecretProperties> 구현을 상상해 보세요.

sealed file class SecretPropertyObserver : IObserver<SecretProperties>
{
    public void OnCompleted() =>
        Console.WriteLine("Done observing secrets");

    public void OnError(Exception error) =>
        Console.WriteLine($"Error observing secrets: {error}");

    public void OnNext(SecretProperties secret) =>
        Console.WriteLine($"Observable: {secret.Name}");
}

다음과 같이 ToObservable 확장 메서드를 사용할 수 있습니다.

IDisposable UseTheToObservableMethod()
{
    AsyncPageable<SecretProperties> allSecrets =
        client.GetPropertiesOfSecretsAsync();

    IObservable<SecretProperties> observable = allSecrets.ToObservable();

    return observable.Subscribe(
        new SecretPropertyObserver());
}

위의 C# 코드에서:

  • SecretClient.GetPropertiesOfSecretsAsync 메서드가 호출되고 AsyncPageable<SecretProperties> 개체를 반환합니다.
  • ToObservable() 메서드는 AsyncPageable<SecretProperties> 인스턴스에서 호출되어 IObservable<SecretProperties>를 반환합니다.
  • observable은 구독되어 관찰자 구현을 전달하고 구독을 호출자에게 반환합니다.
  • 구독은 IDisposable입니다. 삭제되면 구독이 종료됩니다.

Pageable 반복

Pageable<T>는 일반 foreach 루프와 함께 사용할 수 있는 AsyncPageable<T>의 동기 버전입니다.

void IterateWithPageable()
{
    Pageable<SecretProperties> allSecrets = client.GetPropertiesOfSecrets();

    foreach (SecretProperties secret in allSecrets)
    {
        Console.WriteLine($"IterateWithPageable: {secret.Name}");
    }
}

Important

이 동기 API를 사용할 수 있지만, 더 나은 환경을 위해 비동기 API 대안을 사용하세요.

참고 항목