프로그래밍 일기 — C#을 알아보자 — Bonus
아차, 비동기식 프로그래밍(Asynchronous Programming)을 안 다뤘다!
어제까지 C#의 기본기를 마무리했다고 판단했지만, 아직 미쳐 커버하지 못한 부분이 있었다. 직전 블로그글에서 이야기했던 비동기식프로그래밍(Asynchronous Programming)에 대해서다. 왜 이 중요한 부분을 다룬다고 해놓고 나는 놓쳤을까? 아쉬운 마음에 또 내가 목표로 한 것을 끝까지 해보지 못했다는 찝찝한 마음에 이 주제에 대해서 반드시 짚고 넘어가야겠다는 생각을 했다. C#의 코어에 들어오고나서, 그 안에 숨겨진 마지막 보물을 보지 못하고 넘어간다면 얼마나 아쉬울까?
물론 이번에 비동기식 프로그래밍을 배운다고해서 프로그래밍 여정이, 특히 C#에 대한 탐험이 끝난다고 생각하지 않는다. 오히려 지금까지 배운 내용들을 활용하여 실생활에 어떻게 적용해 나아갈지에 대해 고민해보아야할 것이라 생각한다. 즉, 이제 시작일 뿐이다. 끝을 보려면 한참 남았다. 아마 보지 못할 수도 있다. 중요한 것은 내가 새로운 것을 배우고 성장한다는 것이라 믿는다. 어쨌든 이번 글에서는 저번에 미쳐 다루지 못했던 비동기식 프로그래밍에 대해 설명해 보려한다. 그래야 비로소 C# 프로그래밍의 시작점에 섰다는 안심이 들 것 같다.
C# 심화학습
동기식 프로그래밍(Asynchronous Programming)
- 코드 실행이 한번이 순차적으로 일어나는 프로그래밍 방식을 말한다.
- 동기식 메서드(Synchronous Method)가 호출되면 프로그램은 코드의 다음 라인을 실행하기전 메서드가 완료할 때까지 대기한다.
- 프로그램은 메서드가 호출되는 동안 다른 작업을 중단하거나 차단한다는 의미다.
- Blocking Architecture라고 부르기도한다.
장점:
- 특정 작업을 수행할 때, 다른 모든 것들을 막거나 지연시켜야할 때 효과적이다.
단점:
- 전체 어플리케이션의 처리 시간이 더 길어질 수 있고, 특정 작업을 수행하는 동안에는 응답하지 못한다.
- 예: 전화는 한 사람이 말하는 동안 다른 사람이 듣는 상태에서 동시에 말을 할 수 없고, 바로 응답을 해야하는 상황이 펼쳐지기에 동기식 어플리케이션이라 볼 수 있다.
비동기식 프로그래밍(Asynchronous Programming)
- 동기식 프로그래밍의 단점을 개선한 방식으로, 어플리케이션이 평행으로 여러 다른 작업을 수행할 수 있다.
- 여러 개발자가 로컬에서 어플리케이션을 개발하면서, 동시에 Remote에 Push할 수 있다.
- 예: 문자(Texting)는 한 사람이 문자를 보내는 와중에도 상대가 보낼 수 있고, 문자를 보내는 동안 상대가 다른 작업을 할 수 있다. 또한 상대방이 원할 때 답장할 수 있으므로 비동기식 어플리케이션이라 볼 수 있다.
동기식 vs 비동기식 프로그래밍 비교
- 동기식은 특정 작업을 제외한 다른 모든 것을 차단하는 Blocking Architecture 방식, 비동기식은 여러 작업을 허용하는 Non-blocking Architecture 방식을 사용한다.
- 동기식은 Single-Thread이기에 특정 I/O 연산이 끝날 때까지 새로운 Thread를 기다려야하지만, 비동기식은 Multi-Thread이다.
- 동기식은 이해하기 쉽지만, 비동기식은 복잡할 수 있다.
- 동기식에서는 어플리케이션이 응답을 중단할 수 있지만, 비동기식에서는 어플리케이션이 작업 처리와 동시에 반응할 수 있다.
- 동기식은 하나의 CPU의 처리능력에 의존하지만, 비동기식은 여러 CPU코어를 활용한다.
- 동기식에서는 예외가 바로 나타나지만, 비동기식에서는 예외가 작업 진행시 감춰지거나 작업 후에 띄워질 수 있다.
- 동기식은 Task를 사용하지 않지만, 비동기식은
async
단위 작업을 표현하기 위해 Task를 사용한다.
.NET상의 비동기식 프로그래밍 패턴
- Asynchronous Programming Model(APM)
- Input/Output 연산이 다른 형태의 연산보다 상대적으로 느리다.
- 특정 연산이 완료될때까지 새로운 Thread를 기다릴 필요가 없이, 여러 Thread들이 계속 실행될 수 있기에 비동기식 I/O(Asynchronous I/O)처리가 가능하다.
- 즉, 코드의 부분들이 각각 별도의 Thread로 실행될 수 있다.
IAsyncResult
인터페이스를 디자인 패턴으로 활용한다.
// APM 메서드 시그니쳐 예제
public class EmployeeImport
{
// IAsyncResult 인터페이스 사용(리턴타입)
public IAsyncResult BeginImportEmployeeData(Employee employee,
AsyncCallback callback, object state);
// IAsyncResult를 인자로 활용
public int EndImportEmployeeData(IAsyncResult asyncResult);
}
Asynchronous 연산 타입:
- Delegate of async callback
- Dependency를 갖는 Operational state property
2. Event-Based Asynchronous Pattern(EAP)
- EAP를 지원하는 클래스로써 메서드의 비동기식 버전을 가진다.
- 클래스는
<em>MethodName</em>Async
라는 식의 형태를 가진 하나 이상의 메서드를 갖는다. 또한 이에 대한 cancel 메서드인<em>MethodName</em>
이라는 형식의 메서드를 사용해 작업처리 중간에 취소할 수 있다. - 또한 비동기식 메서드가 완료되었을 때 나타나는
MethodNameCompleted
이벤트를 가질 수 있다. - 그 어떤 메서드에 대해 비동기식 실행의 복잡성을 은닉할 수 있는 표준 패턴으로 활용되고 있다.
- 다운로드 및 데이터베이스 작업 등 시간이 많이 필요한 작업들을 어플리케이션을 중지하지 않고도 진행할 수 있다.
- 여러 작업을 동시에 진행하여 각각이 완료되었을 때 알림을 받을 수 있다.
- 어플리케이션을 중지하지않고도 가용가능한 리소스가 있을 때까지 대기할 수 있다.
- events-and-delegates모델을 통해 대기상태의 비동기 작업과 커뮤니케이션한다.
// EAP 예제
// 메서드의 EAP버전 시그니쳐
public class EmployeeImport
{
// ImportEmployeeData 메서드의 비동기식 버전
public void ImportEmployeeDataAsync(Employee employee);
// ImportEmployeeData 메서드의 이벤트 Handler(작업 완료시 알림 받기 위함)
public event ImportEmployeeDataCompletedEventHandler ImportCompleted;
}
3. Task-Based Asynchronous Pattern(TAP) [.NET 어플리케이션에서 가장 널리 쓰임]
- .NET 4.5이후 비동기식 프로그래밍 적용시 활용되는 권장모델이다.
- C# 5.0 부터 도입된
async
및await
키워드를 활용한다. - non-blocking 프레임워크를 제공한다. 이를 활용하면 현재 진행 중인 Thread를 차단(block)하지 않는다. time async 요청이 완료될때까지 다음 작업들을 계속 진행할 수 있다.
- 비동기 메서드는
Async
접미사를 활용한다.(예:<MethodName>Async
) - .NET 프레임워크 4.5부터는 많은 기존 클래스의
Async
버전을 도입했다.(예:System.IO.Stream
클래스내CopyToAsync
,ReadAsync
,WriteAsync
메서드 추가)
// TAP 예제
public class EmployeeImport
{
// ImportEmployeeData 메서드의 Async 버전
public Task<int> ImportEmployeeDataAsync(Employee employee);
}
참조:
(1) https://pixabay.com/photos/road-nevada-clouds-bird-landscape-3856796/