프로그래밍 언어/C#

동시성의 개요

뽀또치즈맛 2025. 6. 17. 09:15

동시성은 멋진 소프트웨어의 핵심적인 특징이다.
동시성은 이미 수십 년 전 부터 사용할 수 있었지만 제대로 구현하기 어려웠다.
동시성 소프트웨어는 코드 작성도, 디버깅도, 유지 보수도 어려워서 결국 많은 개발자가 동시성을 피하는 쉬운 길을 택했다.
요즘은 닷넷 프로그램에서 사용할 수 있는 라이브러리와 언어 기능 덕분에 동시성의 구현이 훨씬 수월해졌다.
마이크르소프트는 동시성의 진입 장벽을 크게 낮추는 데 앞장서 왔다.
예전에는 동시성 프로그래밍이 전문가의 영역이었지만,
요즘은 모든 개발자가 동시성을 받아들여야 하며, 또 받아들일 수 있다.
 
 
동시성이란,
한 번에 두 가지 이상의 작업을 수행하는 것이다.
 
이 정의를 통해 동시성의 유용함이 잘 들어났으면 좋겠다.
애플리케이션은 데이터 베이스에 쓰는 동안 사용자의 입력에 응답해야 하려고 동시성을 사용한다.
 
서버 애플리케이셔는 첫 번쨰 요청을 완료하는 동안 두 번쨰 요청에 응답하려고 동시성을 사용한다.
언제든 애플리케이션이 하나의 작업을 수행하는 동안 다른 작업을 수행해야 한다면 동시성을 사용한다.
 
언제든 애플리케이션의 하나의 작업을 수행하는 동안 다른 작업을 수행해야 한다면 동시성이 필요하다.
세상의 거의 모든 소프트웨어 애플리케이션은 동시성의 해택을 받을 수 있다.
 
대부분의 개발자는 '동시성'이라는 단어를 들으면 즉시 '멀티스레딩'을 떠올린다.
이 두가지는 구별해야 한다.
 
멀티스레딩
다수의 실행 스레드를 사용하는 동시성의 한 형태
 
멀티스레딩은 말 그대로 다수의 스레드를 사용한다는 뜻이다.
멀티스레딩은 동시성의 한 형태일 뿐 유일한 형태가 아니다.
사실 요즘 애플리케이션은 하위 레벨 스레드를 직접 사용할 이유가 거의 없다.
상위 레벨 추상화가 더 강력하고 효율적이다.
 
따라서 낡은 기술에 대한 소개는 해당 서적을 정리하며 최소화 하여 포스팅할 예정이다.
이 책의 기반 멀티스레딩 예제는 Thread나 BackgroundWorker 형식을 사용하지 않고 더 우수한 대안으로 대체되었다고 한다.
 
프로젝트에  new Thread()를 입력하는 순간, 이미 시대에 뒤처진 코드를 지닌 프로젝트로 바뀐다고 주장한다.
 
하지만 멀티스레딩이 죽었다는 생각은 하지 말라고 조언하기도 한다.
멀티스레딩은 스레드 풀안에 살아 숨쉬고 있으며, 스레드 풀은 필요에 따라 자동으로 작업을 할당하는 유용한 개념이다.
결과적으로 스레드 풀 덕분에 병렬 처리라는 다른 중요한 형태의 동시성을 사용할 수 있다.
 
병렬 처리
많은 작업을 여러 스레드에 나눠서 동시에 수행
 
병렬 처리 또는 병렬 프로그래밍은 멀티스레딩을 사용해서 멀티 코어 프로세서를 최대한 활용하는 방식이다.
요즘은 CPU 코어가 여러 개이다.
해야 할 작업이 많을 때 하나의 코어에 모든 일을 맡기고 다른 코어를 쉬게 두면 비효율적이다.
병렬 처리는 작업을 나눠서 각각 다른 코어에서 독립적으로 실행할 수 있는 여러 스레드에 맡긴다.
 
병렬 처리는 멀티스레등의 한 형태이고, 멀티스레딩은 동시성의 한 형태이다.
그 밖에 요즘 애플리케이션에 중요하지만, 많은 개발자에게 익숙하지 않은 동시성의 다른 형태로는 비동기 프로그래밍이 있다.
 
비동기 프로그래밍
불필요한 스레드의 사용을 피하려고 퓨처나 콜백을 사용하는 동시성의 한 형태이다.
 
퓨처 또는 프로미스는 나중에 완료될 연산을 나타내는 형식이다.
닷넷의 최신 퓨처 형식으로는 Task와 Task<TResult>가 있다.
구식 비동기 API는 퓨처가 아닌 콜백이나 이벤트를 사용한다.
비동기 프로그래밍은 나중에 완료되는 연산인 비동기 연산이라는 개념에 중점을 두고있다.
비동기 연산은 진행하는 동안 원래 스레드를 가로막지 않는다.
즉 해당 연산을 시작한 스레드는 자유롭게 다른 작업을 할 수 있다.
연산이 끝나면 퓨처에 알리거나 콜백 또는 이벤트를 실행해서 애플리케이션에 연산이 끝났음을 알린다.
 
비동기 프로그래밍은 동시성 중에서도 강력한 형태이지만, 최근까지도 엄청나게 복잡한 코드가 필요했다.
요즘 언어에서 지원하는 async, await는 비동기 프로그래밍을 거의 동기 방식의 프로그래밍처럼 쉽게 만들어준다.
 
그 밖에 동시성의 형태로는 리액티브 프로그래밍(reactive programming)이 있다.
비동기 프로그래밍은 결국 애플리케이션이 나주엥 완료될 연산을 시작한다는 뜻이다.
리액티브 프로그래밍은 비동기 프로그래밍과 밀접한 관련이 있지만, 비동기 연산이 아닌 비동기 이벤트를 바탕으로 한다.
비동기 이벤트는 실제로 '시작'이 없을 수 있으며, 언제든 발생할 수 있고, 여러번 발생할 수도 있다.
사용자 입력을 이에 대한 예로 들 수 있다.
 
리액티브 프로그래밍
애플리케이션이 이벤트에 대응하게 하는 선형형 프로그래밍 방식
 
애플리케이션을 커다란 상태 머신이라 생각한다면 애플리케이션의 동작이란 이벤트를 따라 상태를 업데이트하는 식으로 일련의 이벤트에 대응하는 것이라 설명할 수 있다.
추상적이거나 이론적인 이야기처럼 보여도 사실 그렇지 않다.
요즘 프레임워크는 이런 개념을 실제 애플리케이션에서 꽤 유용하게 사용한다.
리액티브 프로그래밍에 동시성이 꼭 필요하진 않지만,
동시성과 밀접한 관련이 있기 때문에 이 책에서는 기본적인 내용을 설명한다.
 
대게 동시성 프로그램을 작성할 땐 다양한 기법이 함께 쓰인다.
대부분의 애플리케이션은 최소한 스레드 풀을 통한 멀티스레딩과 비동기 프로그래밍을 사용한다.
적절한 도구를 통해 애플리케이션의 각 부분에 다양한 형태의 동시성을 자유롭게 섞어서 사용해 보기 바란다.

'프로그래밍 언어 > C#' 카테고리의 다른 글

동시성 프로그래밍 : 비동기 프로그래밍  (3) 2025.06.21
박싱 언박싱  (0) 2025.05.17
.NET 과 C#의 아키텍처  (4) 2025.05.17
IEnumerator<T> 인터페이스  (0) 2025.05.16
C# out 키워드  (1) 2024.07.27