본문 바로가기
C#

C#에서 비동기 프로그래밍 다루기 ⚡️💻

by 다다면체 2024. 12. 17.
728x90
반응형
반응형

비동기 프로그래밍은 현대 소프트웨어 개발에서 필수적인 기술입니다. 🌟 특히 네트워크 호출, 파일 처리, 데이터베이스 작업처럼 시간이 오래 걸리는 작업을 효율적으로 처리하려면 비동기적 접근이 필요하죠. 이번 글에서는 C#의 async와 await 키워드, Task Parallel Library(TPL), 그리고 비동기 프로그래밍을 활용한 성능 최적화 방법을 친절히 안내해 드리겠습니다! 😊


1. async와 await 키워드 사용법

C#에서 비동기 작업은 async와 await 키워드를 사용해 구현됩니다. async는 메서드가 비동기 작업을 수행할 것을 나타내며, await는 비동기 작업이 완료될 때까지 기다립니다.

기본 예제: 비동기 메서드 작성

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("작업 시작");
        string result = await LongRunningOperation();
        Console.WriteLine(result);
        Console.WriteLine("작업 종료");
    }

    static async Task<string> LongRunningOperation()
    {
        await Task.Delay(3000); // 3초 대기
        return "작업 완료";
    }
}

이 코드는 3초 동안 대기한 후 "작업 완료"를 반환합니다. 비동기 메서드는 실행 중 다른 작업을 블로킹하지 않으므로 UI가 멈추지 않거나 서버가 더 많은 요청을 처리할 수 있습니다. 🎉


2. 비동기 메서드와 멀티스레딩의 차이점

비동기 프로그래밍과 멀티스레딩은 서로 다릅니다. 🙌

  • 비동기 프로그래밍은 작업을 논리적으로 나누어 동시 실행되도록 관리합니다. 실제로는 단일 스레드에서 실행되더라도 작업을 비동기적으로 처리합니다.
  • 멀티스레딩은 여러 스레드를 생성해 작업을 병렬로 처리합니다.

주요 차이

특징비동기 프로그래밍멀티스레딩

목적 작업 효율성 증대 (I/O 바운드) CPU 사용 극대화 (CPU 바운드)
구현 난이도 상대적으로 쉬움 복잡함 (스레드 동기화 필요)
성능 최적화 대상 네트워크 호출, 파일 I/O 병렬 계산, 데이터 처리

3. Task와 Task Parallel Library(TPL)

C#의 Task는 비동기 작업을 표현하는 기본 단위입니다. Task Parallel Library(TPL)는 Task를 사용해 병렬 작업을 쉽게 관리할 수 있도록 돕는 라이브러리입니다. 🚀

Task 기본 사용법

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        Task<int> task = ComputeSumAsync(10);
        Console.WriteLine("다른 작업 수행 중...");
        int result = await task;
        Console.WriteLine($"결과: {result}");
    }

    static async Task<int> ComputeSumAsync(int n)
    {
        return await Task.Run(() => {
            int sum = 0;
            for (int i = 1; i <= n; i++)
            {
                sum += i;
            }
            return sum;
        });
    }
}

위 코드에서는 Task.Run을 사용해 CPU 바운드 작업을 비동기적으로 실행합니다.

TPL로 병렬 작업 처리

TPL은 병렬 처리를 위한 다양한 기능을 제공합니다. 💡

예제: 병렬 작업 실행

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        var task1 = Task.Run(() => DoWork("작업 1"));
        var task2 = Task.Run(() => DoWork("작업 2"));

        await Task.WhenAll(task1, task2);
        Console.WriteLine("모든 작업 완료");
    }

    static void DoWork(string taskName)
    {
        Console.WriteLine($"{taskName} 시작");
        Task.Delay(2000).Wait(); // 2초 대기
        Console.WriteLine($"{taskName} 완료");
    }
}

이 코드는 두 개의 작업을 병렬로 실행하고, 모두 완료될 때까지 기다립니다. 👏


4. 비동기 프로그래밍을 통한 성능 최적화

비동기 프로그래밍은 다음과 같은 시나리오에서 성능 최적화에 필수적입니다:

  • 대규모 네트워크 호출: API 요청을 병렬로 처리.
  • 파일 처리: 대용량 파일을 비동기적으로 읽고 쓰기.
  • UI 애플리케이션: UI 스레드를 블로킹하지 않고 작업 수행.

실무 사례: 비동기 HTTP 요청

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        using HttpClient client = new HttpClient();

        var urls = new[] {
            "https://example.com/api/data1",
            "https://example.com/api/data2",
            "https://example.com/api/data3"
        };

        var tasks = urls.Select(url => FetchDataAsync(client, url));
        var results = await Task.WhenAll(tasks);

        foreach (var result in results)
        {
            Console.WriteLine(result);
        }
    }

    static async Task FetchDataAsync(HttpClient client, string url)
    {
        var response = await client.GetAsync(url);
        return await response.Content.ReadAsStringAsync();
    }
}

이 코드는 여러 API 요청을 병렬로 처리하여 응답 시간을 단축합니다. ⚡


마무리

이번 글에서는 C#에서 비동기 프로그래밍의 핵심 개념과 실무 활용법을 다뤘습니다. async와 await를 통해 효율적으로 작업을 처리하고, Task와 TPL을 사용해 병렬 처리의 이점을 활용할 수 있습니다. 비동기 프로그래밍은 사용자 경험과 애플리케이션 성능을 동시에 향상시키는 강력한 도구입니다. 💪

꾸준히 연습하며 비동기의 매력을 느껴보세요! 🚀

728x90
반응형