C# 비동기 프로그래밍이란?
C#의 비동기(Asynchronous) 프로그래밍은 작업이 차단되거나 접근이 지연되는 상황을 효율적으로 처리할 수 있는 방식입니다. 동기(Synchronous) 방식에서는 특정 작업이 차단되면 애플리케이션 전체가 해당 작업이 끝날 때까지 대기해야 하므로 실행 시간이 길어지고, 최악의 경우 프로그램이 응답하지 않는 상태에 빠질 수 있습니다. 반면 비동기 방식을 사용하면 대기 중인 작업과 무관하게 애플리케이션이 다른 작업을 계속 수행할 수 있습니다.
동기 처리 시 발생하는 문제
GUI를 갖춘 애플리케이션에서 큐(queue)의 내용을 확인하고, 처리되지 않은 작업이 있으면 이를 꺼내어 먼저 처리한다고 가정해 보겠습니다. 코드가 동기적으로 실행되기 때문에 해당 작업이 완료될 때까지 프로그램 전체가 대기해야 합니다. 만약 처리 시간이 예상보다 오래 걸린다면 애플리케이션은 "응답 없음" 메시지를 표시하게 되어 사용자 경험이 크게 저하됩니다.
앞서 설명한 상황을 코드로 살펴보겠습니다.
private void OnRequestDownload(object sender, RoutedEventArgs e) {
var req = HttpWebRequest.Create(_requestedUri);
var res = req.GetResponse();
}위 코드에서 GetResponse() 메서드는 네트워크 응답이 도착할 때까지 호출 스레드를 차단합니다. 결과적으로 UI 스레드까지 멈추게 되어 화면이 정지된 것처럼 보이는 문제가 발생합니다.
async와 await 키워드로 문제 해결
이러한 문제를 해결하려면 C#에서 제공하는 async와 await 키워드를 활용하면 됩니다.
private async void OnRequestDownload(object sender, RoutedEventArgs e) {
var req = HttpWebRequest.Create(_requestedUri);
var res = await req.GetResponseAsync();
}메서드 선언부에 async 키워드를 추가하고, 차단 가능한 작업 앞에 await 키워드를 붙여 GetResponseAsync()를 호출하도록 변경했습니다. 이렇게 하면 네트워크 요청이 완료되기를 기다리는 동안에도 UI 스레드는 차단되지 않고 계속해서 다른 작업을 처리할 수 있습니다.
핵심 포인트 정리
비동기 프로그래밍은 특히 네트워크 통신, 파일 입출력처럼 완료까지 시간이 오래 걸릴 수 있는 작업에서 그 진가를 발휘합니다. async와 await를 적절히 사용하면 애플리케이션의 응답성을 유지하면서도 코드의 가독성과 유지보수성을 높일 수 있으므로, GUI 기반 애플리케이션 개발 시 반드시 고려해야 할 필수 패턴이라 할 수 있습니다.