프로세스와 쓰레드의 차이, Coroutine이 쓰레드인지에 대한 생각
프로세스와 쓰레드는 멀티태스킹 환경에서 프로그램이 실행되는 방식에 대한 기본 개념입니다. 이 글에서는 프로세스와 쓰레드의 차이, Coroutine의 동작 방식, 그리고 Coroutine이 쓰레드라고 할 수 있는지에 대하여 서술하겠습니다.
글의 내용이 길지는 않지만 서론에 결론을 먼저 한번 나타 서술하고 마지막에 한번 더 결론을 서술합니다.
Coroutine은 쓰레드인가?
Coroutine은 쓰레드와 비슷한 동시성을 제공하지만, 쓰레드와는 구조와 동작 방식이 다릅니다. Coroutine은 이벤트 루프를 사용해 동시성을 처리하고, 공유 데이터에 대한 접근을 제어하여 경쟁 조건을 최소화합니다. 또한, 코루틴은 쓰레드보다 메모리 소비가 적고, 컨텍스트 스위칭 오버헤드가 적습니다. 따라서, Coroutine은 쓰레드와 비슷한 동시성을 제공하지만, 쓰레드와는 별개의 개념으로 이해해야 합니다.
- 경쟁조건이 궁금하다면 https://korshika.tistory.com/150
코루틴을 사용하는 주요 이유
- 비동기 프로그래밍: 코루틴을 사용하면, 동시성을 지원하는 코드를 작성할 때 비동기 프로그래밍을 손쉽게 구현할 수 있습니다. 비동기 프로그래밍은 여러 작업을 동시에 실행하여 전체 처리 속도를 개선하거나 높은 처리량을 제공합니다.
- 리소스 효율: 코루틴은 쓰레드와 같은 동시성을 제공하지만, 쓰레드에 비해 훨씬 적은 메모리와 시스템 리소스를 사용합니다. 따라서 많은 수의 동시 작업을 수행할 때 코루틴이 더 효율적입니다.
- 동기화 문제 해결: 코루틴은 일반적으로 동시성 제어가 더 간단하고, 쓰레드와 같은 복잡한 동기화 문제가 없습니다. 코루틴은 한 번에 하나의 작업만 실행되기 때문에 공유 자원에 대한 경쟁 상황이 발생할 가능성이 줄어듭니다.
- 코드 간결성: 코루틴을 사용하면 콜백이나 이벤트 기반 프로그래밍보다 코드가 간결하고 읽기 쉬워집니다.
async
와await
문법을 사용하여 비동기 작업을 동기적인 스타일로 작성할 수 있어 코드 가독성이 향상됩니다. - I/O 바운드 작업 최적화: 코루틴은 I/O 바운드 작업에 특히 효율적입니다. 네트워크 통신, 파일 I/O 등의 작업이 많은 경우에 코루틴을 사용하면 작업이 동시에 처리되어 대기 시간을 최소화하고 처리량을 높일 수 있습니다.
프로세스와 쓰레드의 차이
프로세스 (Process)
프로세스는 운영 체제가 실행하는 프로그램의 인스턴스입니다. 각 프로세스는 독립적인 메모리 공간, 코드, 데이터, 열린 파일 등을 갖습니다. 프로세스는 다른 프로세스와 통신하기 위해 IPC(Inter-process Communication)를 사용합니다.
- IPC에 대한 자세한 내용이 궁금하다면 https://y-oni.tistory.com/77
쓰레드 (Thread)
쓰레드는 프로세스 내에서 실행되는 경량의 실행 단위입니다. 쓰레드는 프로세스와 같은 메모리 공간, 코드, 데이터 등을 공유하면서 실행되지만, 각 쓰레드는 자체 스택을 가지고 있어서 독립적으로 작동합니다. 쓰레드는 멀티프로세싱과 비교하여 오버헤드가 적고, 데이터 공유가 쉽지만, 동시성 제어에 주의해야 합니다.
Coroutine 동작 방식
Coroutine(코루틴)은 일반적인 함수와 유사하지만, 실행을 일시 중지할 수 있고, 나중에 이어서 실행할 수 있는 함수입니다. 이러한 동작은 비동기 작업의 동시성을 관리하는 데 유용합니다.
Python의 경우, 코루틴은 async def
를 사용하여 정의하며, await
키워드를 사용해 일시 중지할 수 있습니다. 코루틴은 이벤트 루프를 사용하여 비동기 작업을 스케줄링하고 관리합니다.
코루틴을 다루는 방식에는 크게 두 가지가 있습니다:
- Python 3.5 이후에 도입된
async
/await
문법을 사용하는 코루틴 - Python의 제너레이터를 활용하는 레거시 코루틴 (이 방식에서는
next()
와send()
메서드를 사용합니다)
async/await 문법을 사용하는 코루틴
Python 3.5에서 도입된 async
/await
문법은 비동기 작업을 직관적으로 작성하고 이해하기 쉽게 도와줍니다. async def
로 정의된 함수는 코루틴 함수로 간주되며, 이 함수의 호출 결과는 코루틴 객체를 반환합니다. await
키워드는 비동기 작업을 기다리도록 코루틴을 일시 중지할 수 있습니다.
예시:
import asyncio
async def my_coroutine():
print("Before await")
await asyncio.sleep(1)
print("After await")
async def main():
await my_coroutine()
asyncio.run(main())
제너레이터를 활용하는 레거시 코루틴
이 방식에서는 제너레이터 함수를 이용하여 코루틴을 구현합니다. 제너레이터 함수는 yield
키워드를 사용해 값을 반환하며, 이 때 함수의 실행이 일시 중지됩니다. 이후 next()
나 send()
메서드를 호출하여 제너레이터를 다시 실행할 수 있습니다. 이 방식은 Python 3.5 이전 버전에서도 사용할 수 있으며, async
/await
를 지원하지 않는 환경에서 코루틴을 구현하는 방법입니다.
예시:
def my_coroutine():
print("Before yield")
value = yield
print("After yield with value:", value)
coroutine = my_coroutine()
next(coroutine) # 코루틴 실행 시작
coroutine.send(42) # 코루틴 재개, 값을 전달
두 방식의 차이점은 구현 방식, 문법, 그리고 가독성에 있습니다. async
/await
문법을 사용하는 코루틴이 더 직관적이고 이해하기 쉬운 방식입니다. Python의 최신 버전에서는 async
/await
를 사용한 비동기 프로그래밍을 권장하며, 레거시 방식은 이제 사용하지 않는 것이 좋다고 합니다.
결론
프로세스와 쓰레드는 독립적인 실행 환경을 제공하는 반면, Coroutine은 프로그램의 실행 흐름을 일시 중지하고, 나중에 이어서 실행할 수 있는 특성을 제공합니다. 이 특성 덕분에 Coroutine은 동시성을 효율적으로 관리할 수 있으며, 쓰레드와는 구조와 동작 방식이 다릅니다. 이러한 차이로 인해 Coroutine은 쓰레드와 비슷한 동시성을 제공하지만, 쓰레드와 별개의 개념으로 이해해야 합니다.
이 글은 아래 링크를 참조하여 작성하였습니다:
'ComputerScience' 카테고리의 다른 글
[1분 지식] 매개변수와 인자 ( parameter 와 argument ) (0) | 2023.04.23 |
---|---|
[1분 지식] 함수와 메서드 (0) | 2023.04.23 |
[3분지식] Shell (0) | 2023.04.19 |
[3분 지식] WAS 란? - WEB server와 WAS (0) | 2022.08.11 |
[3분 CS지식] Nginx 요약정리 (0) | 2022.07.17 |