데이터 이동 라이브러리를 사용하여 데이터 전송

참고 항목

이 문서에는 Azure Storage 데이터 이동 라이브러리의 버전 2.0.XX 작업 지침이 포함되어 있습니다. 버전 2.0.XX는 현재 유지 관리 모드이며 라이브러리는 데이터 무결성 및 보안 문제에 대한 수정 사항만 수신합니다. 새 기능이 추가되지 않으며 라이브러리에서 새 스토리지 서비스 버전을 지원하지 않습니다.

최신 데이터 이동 라이브러리의 베타 버전은 현재 개발 중입니다. 자세한 내용은 GitHub에서 .NET용 Azure Storage 데이터 이동 공통 클라이언트 라이브러리를 참조하세요.

Azure Storage 데이터 이동 라이브러리는 Blob 및 파일의 고성능 업로드, 다운로드 및 복사 작업을 위해 설계된 플랫폼 간 오픈 소스 라이브러리입니다. 데이터 이동 라이브러리는 .NET용 Azure Storage 클라이언트 라이브러리에서 사용할 수 없는 편리한 방법을 제공합니다. 이러한 방법에는 병렬 작업 수를 설정하고, 전송 진행률을 추적하며, 취소된 전송을 손쉽게 다시 시작하는 등의 기능이 포함됩니다.

이 라이브러리는 .NET Core를 사용하기 때문에 Windows, Linux 및 macOS용 .NET 앱을 빌드할 때 사용할 수 있습니다. .NET Core에 대한 자세한 내용은 .NET Core 설명서를 참조하세요. 또한 이 라이브러리는 전통적인 Windows용 .NET Framework 앱에서도 작동합니다.

이 문서에서는 Windows, Linux 및 macOS에서 실행되는 .NET Core 콘솔 애플리케이션을 만들고 다음 시나리오를 수행하는 방법을 보여 줍니다.

  • Blob Storage에 파일과 디렉터리를 업로드합니다.
  • 데이터를 전송할 때 수행할 병렬 작업 수를 정의합니다.
  • 데이터 전송 진행률을 추적합니다.
  • 취소된 데이터 전송을 다시 시작합니다.
  • URL에서 Blob Storage로 파일을 복사합니다.
  • Blob Storage 간에 복사합니다.

필수 조건

설정

  1. .NET Core SDK를 설치하려면 .NET Core 설치 가이드를 방문하세요. 사용자 환경을 선택할 때 명령줄 옵션을 선택합니다.
  2. 명령줄에서 프로젝트에 대한 디렉터리를 만듭니다. 이 디렉터리로 이동한 다음 dotnet new console -o <sample-project-name>를 입력하여 C# 콘솔 프로젝트를 만듭니다.
  3. Visual Studio Code에서 이 디렉터리를 엽니다. 이 단계는 Windows에서 code .를 입력하여 명령줄을 통해 빠르게 수행할 수 있습니다.
  4. Visual Studio Code Marketplace에서 C# 확장을 설치합니다. Visual Studio Code를 다시 시작합니다.
  5. 이 시점에서 두 가지 프롬프트가 표시됩니다. 하나는 “빌드 및 디버그에 필요한 자산”을 추가하는 것입니다. “예”를 클릭합니다. 또 다른 프롬프트는 해결되지 않은 종속성을 복원하는 것입니다. "복원"을 클릭합니다.
  6. .vscode 아래에서 launch.json을 수정하여 외부 터미널을 콘솔로 사용합니다. 이 설정은 "console": "externalTerminal"로 읽어야 합니다.
  7. Visual Studio Code를 사용하면 .NET Core 애플리케이션을 디버그할 수 있습니다. F5 키를 눌러 애플리케이션을 실행하고 설정이 작동하는지 확인합니다. 콘솔에 “Hello World!”가 표시되어야 합니다.

프로젝트에 데이터 이동 라이브러리 추가

  1. <project-name>.csproj 파일의 dependencies 섹션에 최신 버전의 데이터 이동 라이브러리를 추가합니다. 이 문서를 작성한 시점에서 해당 버전은 "Microsoft.Azure.Storage.DataMovement": "0.6.2"입니다.
  2. 프로젝트를 복원하기 위해 프롬프트가 표시됩니다. "복원" 단추를 클릭합니다. 또한 프로젝트 디렉터리의 루트에 dotnet restore 명령을 입력하여 명령줄에서 프로젝트를 복원할 수도 있습니다.

다음과 같이 <project-name>.csproj를 수정합니다.

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Storage.DataMovement" Version="0.6.2" />
        </ItemGroup>
    </Project>

애플리케이션의 기본 구조 설정

가장 먼저 수행할 작업은 애플리케이션의 "기본 구조" 코드를 설정하는 것입니다. 이 코드는 Storage 계정 이름과 계정 키를 묻는 메시지를 표시하고 해당 자격 증명을 사용하여 CloudStorageAccount 개체를 만듭니다. 이 개체는 모든 전송 시나리오에서 Storage 계정과 상호 작용하는 데 사용됩니다. 또한 이 코드는 실행하고자 하는 전송 작업의 유형도 선택하도록 요청합니다.

다음과 같이 Program.cs를 수정합니다.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using Microsoft.Azure.Storage.DataMovement;

namespace DMLibSample
{
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("Enter Storage account name:");
            string accountName = Console.ReadLine();

            Console.WriteLine("\nEnter Storage account key:");
            string accountKey = Console.ReadLine();

            string storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=" + accountName + ";AccountKey=" + accountKey;
            CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);

            ExecuteChoice(account);
        }

        public static void ExecuteChoice(CloudStorageAccount account)
        {
            Console.WriteLine("\nWhat type of transfer would you like to execute?\n1. Local file --> Azure Blob\n2. Local directory --> Azure Blob directory\n3. URL (e.g. Amazon S3 file) --> Azure Blob\n4. Azure Blob --> Azure Blob");
            int choice = int.Parse(Console.ReadLine());

            if(choice == 1)
            {
                TransferLocalFileToAzureBlob(account).Wait();
            }
            else if(choice == 2)
            {
                TransferLocalDirectoryToAzureBlobDirectory(account).Wait();
            }
            else if(choice == 3)
            {
                TransferUrlToAzureBlob(account).Wait();
            }
            else if(choice == 4)
            {
                TransferAzureBlobToAzureBlob(account).Wait();
            }
        }

        public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
        {

        }

        public static async Task TransferLocalDirectoryToAzureBlobDirectory(CloudStorageAccount account)
        {

        }

        public static async Task TransferUrlToAzureBlob(CloudStorageAccount account)
        {

        }

        public static async Task TransferAzureBlobToAzureBlob(CloudStorageAccount account)
        {

        }
    }
}

Blob에 로컬 파일 업로드

다음과 같이 GetSourcePathGetBlob 메서드를 Program.cs에 추가합니다.

public static string GetSourcePath()
{
    Console.WriteLine("\nProvide path for source:");
    string sourcePath = Console.ReadLine();

    return sourcePath;
}

public static CloudBlockBlob GetBlob(CloudStorageAccount account)
{
    CloudBlobClient blobClient = account.CreateCloudBlobClient();

    Console.WriteLine("\nProvide name of Blob container:");
    string containerName = Console.ReadLine();
    CloudBlobContainer container = blobClient.GetContainerReference(containerName);
    container.CreateIfNotExistsAsync().Wait();

    Console.WriteLine("\nProvide name of new Blob:");
    string blobName = Console.ReadLine();
    CloudBlockBlob blob = container.GetBlockBlobReference(blobName);

    return blob;
}

다음과 같이 TransferLocalFileToAzureBlob 메서드를 수정합니다.

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    Console.WriteLine("\nTransfer started...");
    await TransferManager.UploadAsync(localFilePath, blob);
    Console.WriteLine("\nTransfer operation complete.");
    ExecuteChoice(account);
}

이 코드는 로컬 파일의 경로, 새 컨테이너 또는 기존 컨테이너의 이름 및 새 Blob의 이름을 입력하라는 메시지를 표시합니다. TransferManager.UploadAsync 메서드에서 이 정보를 사용하여 업로드를 수행합니다.

F5 키를 눌러 애플리케이션을 실행합니다. Microsoft Azure Storage Explorer로 스토리지 계정을 확인하여 업로드를 수행했는지 확인할 수 있습니다.

병렬 작업 수 설정

데이터 이동 라이브러리에서 제공하는 하나의 특징은 병렬 작업의 수를 설정하여 데이터 전송 처리량을 높일 수 있다는 것입니다. 기본적으로 데이터 이동 라이브러리는 병렬 작업 수를 8 * 컴퓨터 코어 수로 설정합니다.

저대역폭 환경에서는 많은 병렬 작업으로 인해 네트워크 연결에 과부하가 걸릴 수 있으며 실제로 작업이 완전히 완료되지 못할 수 있습니다. 사용 가능한 네트워크 대역폭에 따라 가장 적합한 설정을 결정하려면 해당 설정을 테스트해야 합니다.

병렬 작업 수를 설정할 수 있는 몇 가지 코드를 추가해 보겠습니다. 전송이 완료되는 데 걸리는 시간을 제어하는 코드도 추가해 보겠습니다.

다음과 같이 SetNumberOfParallelOperations 메서드를 Program.cs에 추가합니다.

public static void SetNumberOfParallelOperations()
{
    Console.WriteLine("\nHow many parallel operations would you like to use?");
    string parallelOperations = Console.ReadLine();
    TransferManager.Configurations.ParallelOperations = int.Parse(parallelOperations);
}

다음과 같이 SetNumberOfParallelOperations를 사용하도록 ExecuteChoice 메서드를 수정합니다.

public static void ExecuteChoice(CloudStorageAccount account)
{
    Console.WriteLine("\nWhat type of transfer would you like to execute?\n1. Local file --> Azure Blob\n2. Local directory --> Azure Blob directory\n3. URL (e.g. Amazon S3 file) --> Azure Blob\n4. Azure Blob --> Azure Blob");
    int choice = int.Parse(Console.ReadLine());

    SetNumberOfParallelOperations();

    if(choice == 1)
    {
        TransferLocalFileToAzureBlob(account).Wait();
    }
    else if(choice == 2)
    {
        TransferLocalDirectoryToAzureBlobDirectory(account).Wait();
    }
    else if(choice == 3)
    {
        TransferUrlToAzureBlob(account).Wait();
    }
    else if(choice == 4)
    {
        TransferAzureBlobToAzureBlob(account).Wait();
    }
}

다음과 같이 타이머를 사용하도록 TransferLocalFileToAzureBlob 메서드를 수정합니다.

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    Console.WriteLine("\nTransfer started...");
    Stopwatch stopWatch = Stopwatch.StartNew();
    await TransferManager.UploadAsync(localFilePath, blob);
    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

전송 진행률 추적

데이터를 전송하는 데 걸린 시간을 알면 도움이 됩니다. 하지만 전송 중인 진행 상황을 볼 수 있다면 전송 작업이 훨씬 더 효율적일 것입니다. 이 시나리오를 달성하려면 TransferContext 개체를 만들어야 합니다. TransferContext 개체는 SingleTransferContextDirectoryTransferContext의 두 가지 형식으로 제공됩니다. 전자는 단일 파일을 전송하기 위한 것이고 후자는 파일 디렉터리를 전송하기 위한 것입니다.

다음과 같이 GetSingleTransferContextGetDirectoryTransferContext 메서드를 Program.cs에 추가합니다.

public static SingleTransferContext GetSingleTransferContext(TransferCheckpoint checkpoint)
{
    SingleTransferContext context = new SingleTransferContext(checkpoint);

    context.ProgressHandler = new Progress<TransferStatus>((progress) =>
    {
        Console.Write("\rBytes transferred: {0}", progress.BytesTransferred );
    });

    return context;
}

public static DirectoryTransferContext GetDirectoryTransferContext(TransferCheckpoint checkpoint)
{
    DirectoryTransferContext context = new DirectoryTransferContext(checkpoint);

    context.ProgressHandler = new Progress<TransferStatus>((progress) =>
    {
        Console.Write("\rBytes transferred: {0}", progress.BytesTransferred );
    });

    return context;
}

다음과 같이 GetSingleTransferContext를 사용하도록 TransferLocalFileToAzureBlob 메서드를 수정합니다.

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    Console.WriteLine("\nTransfer started...\n");
    Stopwatch stopWatch = Stopwatch.StartNew();
    await TransferManager.UploadAsync(localFilePath, blob, null, context);
    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

취소된 전송 다시 시작

데이터 이동 라이브러리에서 제공하는 또 다른 편리한 기능은 취소된 전송을 다시 시작할 수 있는 기능입니다. c를 입력하여 전송을 일시적으로 취소할 수 있는 코드를 추가한 다음 3초 후에 전송을 다시 시작해 보겠습니다.

다음과 같이 TransferLocalFileToAzureBlob를 수정합니다.

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.UploadAsync(localFilePath, blob, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.UploadAsync(localFilePath, blob, null, context);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

지금까지 checkpoint 값은 항상 null로 설정되어 있었습니다. 이제 전송을 취소하면 전송의 마지막 검사점을 검색한 다음 전송 컨텍스트에서 새로운 이 검사점을 사용합니다.

로컬 디렉터리를 Blob Storage로 전송

데이터 이동 라이브러리에서 한 번에 파일 하나만 전송 가능하다면 충족스럽지 못할 것입니다. 다행히도 그렇지는 않습니다. 데이터 이동 라이브러리는 파일의 디렉터리와 모든 해당 하위 디렉터리를 전송할 수 있는 기능을 제공합니다. 이렇게 수행할 수 있는 몇 가지 코드를 추가해 보겠습니다.

먼저 다음과 같이 GetBlobDirectory 메서드를 Program.cs에 추가합니다.

public static CloudBlobDirectory GetBlobDirectory(CloudStorageAccount account)
{
    CloudBlobClient blobClient = account.CreateCloudBlobClient();

    Console.WriteLine("\nProvide name of Blob container. This can be a new or existing Blob container:");
    string containerName = Console.ReadLine();
    CloudBlobContainer container = blobClient.GetContainerReference(containerName);
    container.CreateIfNotExistsAsync().Wait();

    CloudBlobDirectory blobDirectory = container.GetDirectoryReference("");

    return blobDirectory;
}

그런 후 다음과 같이 TransferLocalDirectoryToAzureBlobDirectory을 수정합니다.

public static async Task TransferLocalDirectoryToAzureBlobDirectory(CloudStorageAccount account)
{
    string localDirectoryPath = GetSourcePath();
    CloudBlobDirectory blobDirectory = GetBlobDirectory(account);
    TransferCheckpoint checkpoint = null;
    DirectoryTransferContext context = GetDirectoryTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    UploadDirectoryOptions options = new UploadDirectoryOptions()
    {
        Recursive = true
    };

    try
    {
        task = TransferManager.UploadDirectoryAsync(localDirectoryPath, blobDirectory, options, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetDirectoryTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.UploadDirectoryAsync(localDirectoryPath, blobDirectory, options, context);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

이 메서드와 단일 파일 업로드 메서드 간에는 몇 가지 차이점이 있습니다. 현재 TransferManager.UploadDirectoryAsync와 이전에 만든 getDirectoryTransferContext 메서드를 사용하고 있습니다. 또한 업로드 작업에 options 값도 제공하므로 업로드 시 하위 디렉터리를 포함하도록 나타낼 수 있습니다.

URL에서 Blob으로 파일 복사

이제 URL에서 Azure Blob으로 파일을 복사할 수 있는 코드를 추가해 보겠습니다.

다음과 같이 TransferUrlToAzureBlob를 수정합니다.

public static async Task TransferUrlToAzureBlob(CloudStorageAccount account)
{
    Uri uri = new Uri(GetSourcePath());
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.CopyAsync(uri, blob, CopyMethod.ServiceSideAsyncCopy, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.CopyAsync(uri, blob, CopyMethod.ServiceSideAsyncCopy, null, context, cancellationSource.Token);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

이 기능의 중요한 사용 사례 중 하나로 다른 클라우드 서비스(예: AWS)에서 Azure로 데이터를 이동해야 하는 경우가 있습니다. 이때 리소스에 액세스할 수 있는 URL이 있으면 TransferManager.CopyAsync 메서드를 사용하여 해당 리소스를 Azure Blob으로 쉽게 이동할 수 있습니다. 또한 이 메서드는 CopyMethod 매개 변수를 사용합니다. 다음 표에는 이 매개 변수에 사용 가능한 옵션이 나와 있습니다.

멤버 이름 설명
SyncCopy 0 원본에서 메모리로 데이터를 다운로드하고 메모리에서 대상으로 데이터를 업로드합니다. 현재, 한 Azure Storage 리소스에서 다른 Azure Storage 리소스로 복사할 때만 사용할 수 있습니다.
ServiceSideAsyncCopy 1 복사를 수행할 수 있도록 Azure Storage에 복사 시작 요청을 보냅니다. 복사가 완료될 때까지 복사 작업 진행률을 모니터링합니다.
ServiceSideSyncCopy 2 URL에서 블록 배치, URL에서 블록 추가 또는 URL에서 페이지 배치를 사용하여 각 청크의 콘텐츠를 복사합니다.

blob 복사

데이터 이동 라이브러리에서 제공하는 또 다른 기능은 한 Azure Storage 리소스에서 다른Azure Storage 리소스로 복사하는 기능입니다.

다음과 같이 TransferAzureBlobToAzureBlob를 수정합니다.

public static async Task TransferAzureBlobToAzureBlob(CloudStorageAccount account)
{
    CloudBlockBlob sourceBlob = GetBlob(account);
    CloudBlockBlob destinationBlob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.CopyAsync(sourceBlob, destinationBlob, CopyMethod.SyncCopy, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.CopyAsync(sourceBlob, destinationBlob, CopyMethod.SyncCopy, null, context, cancellationSource.Token);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

이 예제에서는 TransferManager.CopyAsync의 부울 매개 변수를 CopyMethod.SyncCopy로 설정하여 동기 복사를 수행하려고 한다는 것을 나타냅니다. 즉 리소스를 로컬 시스템에 먼저 다운로드한 다음 Azure Blob으로 업로드합니다. 동기 복사 옵션은 복사 작업을 일관된 속도로 수행하도록 보장하는 좋은 방법입니다. 반면에 비동기 서버 쪽 복사 속도는 서버에서 사용할 수 있는 네트워크 대역폭에 따라 다르며 변동될 수 있습니다. 그러나 동기 복사는 비동기 복사에 비해 추가적인 송신 비용이 발생할 수 있습니다. 원본 스토리지 계정과 동일한 지역에 있는 Azure VM에서 동기 복사를 사용하여 송신 비용이 발생하지 않도록 하는 것이 좋습니다.

이제 데이터 이동 애플리케이션이 완료되었습니다. 전체 코드 샘플은 GitHub에서 사용할 수 있습니다.

다음 단계

Azure Storage 데이터 이동 라이브러리 참조 문서.

Azure Storage Explorer를 사용하여 Azure Blob Storage 리소스를 관리합니다. Azure Storage ExplorerAzure Blob Storage 리소스를 관리할 수 있도록 해주는 Microsoft의 독립 실행형 무료 앱입니다. Azure Storage Explorer를 사용하면 Blob 컨테이너 및 Blob에 대한 액세스를 관리할 뿐만 아니라 Blob 컨테이너 및 Blob을 시각적으로 만들고 읽고 업데이트하며 삭제할 수 있습니다.