[Onboarding] : 비동기 프로그래밍

문승현·2022년 7월 5일
0

BeDev_1

목록 보기
5/7
post-thumbnail

비동기 프로그래밍(Asynchronous Programming)이란 일련의 명령문이
기본 프로그래밍 흐름과 독립적으로 실행되는 병렬 프로그래밍의 한 형태이다.
동기적으로 작업을 수행한다면 블로킹 작업이 있을 때 해당 작업의 결과를 기다려야 한다.
하지만 비동기적으로 수행한다면 프로그램 실행을 멈추지 않기에 병목을 피할 수 있다.

병렬 프로그래밍이라고 했지만 비동기 프로그래밍과 멀티쓰레딩은 같은 것이 아니다.
요리에 비유하자면 비동기 프로그래밍은 한명의 요리사가 동시에 여러 작업을 수행하는 것이고
멀티쓰레딩은 요리사 여러 명이 각각 작업을 수행하는 것을 의미한다.

또한, 비동기 프로그래밍이 언제나 곧 더 나은 성능과 속도를 의미하지는 않는다.
상황에 따라서 비동기 프로그래밍 사용 시 성능과 속도가 나빠질 수 있다.
또한 코드 작성, 디버그 및 유지 관리가 어렵다는 단점이 있다.

C#에서는 아래와 같이 async 및 await 키워드를 사용하여 비동기 프로그래밍을 수행할 수 있다.
async 메서드의 리턴 타입은 리턴 값 유무에 따라 다른데
리턴 값이 있는 경우 Task<TResult>, 리턴 값이 없는 경우 Task를 사용한다.

비동기 프로그래밍에 있어 개인적으로 중요하다고 생각하는 것은 제어 흐름의 변화이다.
메소드에서 메소드로 어떻게 제어 흐름이 이동하는지 그 동작을 이해하는 것이 필요하다.
아래 이미지는 Microsoft Docs에서 가져온 것으로 이해에 도움이 되었다.

1. A calling method calls and awaits the GetUrlContentLengthAsync async method.

   calling methond가 GetUrlContentLengthAsync를 호출하고 기다린다.
  

2. GetUrlContentLengthAsync creates an HttpClient instance and calls the GetStringAsync 
   asynchronous method to download the contents of a website as a string.

   HttpClient 인스턴스를 생성하고 해당 인스턴스로 GetStringAsync를 호출한다.


3. Something happens in GetStringAsync that suspends its progress. 
   Perhaps it must wait for a website to download or some other blocking activity. 
   To avoid blocking, GetStringAsync yields control to GetUrlContentLengthAsync.
   
   GetStringAsync의 작업은 시간이 소요되기에 제어 흐름을 GetUrlContentLengthAsync로 넘긴다.
   
   
4. GetUrlContentLengthAsync can continue with other work.
   That work is represented by a call to the synchronous method DoIndependentWork.
   
   따라서 GetUrlContentLengthAsync는 다른 작업(DoIndependentWork 호출)을 계속할 수 있다.


5. DoIndependentWork(synchronous method) does its work and returns to its caller.
   
   DoindependentWork는 자신의 작업을 하고 호출자에게 제어를 반환한다. 


6. GetUrlContentLengthAsync has run out of work that it can do without a result 
   from getStringTask. Therefore, GetUrlContentLengthAsync uses an await operator 
   to suspend its progress and to yield control to its caller.
   The caller might do other work that doesn't depend on the result from 
   GetUrlContentLengthAsync before awaiting that result, or the caller might await. 
   The calling method is waiting for GetUrlContentLengthAsync, 
   and GetUrlContentLengthAsync is waiting for GetStringAsync.
   
   getStringTask의 결과 없이는 GetUrlContentLengthAsync가 할 수 있는일이 없다.
   따라서 await 연산자를 이용하여 진행을 중단하고 제어 흐름을 호출자에게 반환한다.
   호출자는 GetUrlContentLengthAsync의 결과가 필요하지 않은 작업을 계속해서 진행하거나 
   작업이 없다면 GetUrlContentLengthAsync의 결과를 기다린다.
   즉, caliing method는 GetUrlContentLegnthAsync의 작업 결과를 기다리고
   GetUrlContentLengthAsync는 GetStringAsync의 작업 결과를 기다린다.
	
    
7. GetStringAsync completes and produces a string result.
   The string result is stored in the task, getStringTask. 
   The await operator retrieves the result from getStringTask. 
   The assignment statement assigns the retrieved result to contents.
   
   GetStringAsync의 작업이 완료되어 string 결과물이 만들어졌다.
   해당 string은 getStringTask에 저장되고, await 연산자는 다시 이를 contents에 저장한다.

나 역시 과제를 수행하면서 비동기 프로그래밍을 사용하였다.
아래는 구현 중 async 및 await 키워드와 리턴 타입으로 Task<Tresut>를 사용한 예시이다.

[HttpPost]
public async Task<Response<PostDTO>> CreatePostAsync([Bind("Title", "Content", "Author")] PostDTO post)
{
	return await _postService.CreatePostAsync(post);
}

코드 작성 시 언제 비동기 프로그래밍을 사용해야 하는지 아직은 판단이 서툴다.
위에서 처럼 I/O 작업이 발생하면 async 및 await 키워드를 사용하고 있는데,
다른 사용 예를 추가적으로 공부할 필요가 있을 것 같다.

참고 자료 1) - Synchronous vs. Asynchronous Programming: What's the Difference?
참고 자료 2) - Asynchronous programming with async and await
참고 자료 3) - Asynchronous programming in C#

0개의 댓글