병렬처리
기존 멀티스레드와 병렬 처리의 한계
멀티스레드와 병렬 처리는 CPU 코어를 최대한 활용하여 여러 작업을 동시에 수행하는 기법입니다. 예를 들어, Java나 Kotlin에서 스레드를 사용해 작업을 분산시키면 다음과 같은 코드로 구현할 수 있습니다.
위와 같은 코드에서는 각 스레드가 별도의 OS 스레드로 실행되므로, 스레드 생성과 관리, 컨텍스트 스위칭 등의 오버헤드가 발생합니다. 특히 작업이 I/O 중심이거나 대기 시간이 긴 경우, 스레드들이 블로킹되어 리소스 낭비가 발생할 수 있습니다.
텍스트 다이어그램으로 표현하면 다음과 같습니다.
문제점은 스레드의 생성과 종료, 컨텍스트 스위칭에 따른 비용, 그리고 수백 개 이상의 스레드를 생성할 경우 메모리 및 CPU 오버헤드가 증가하는 점입니다.
코루틴의 개념과 원리
코루틴은 경량 스레드로 볼 수 있으며, 스레드보다 훨씬 적은 오버헤드로 비동기 작업을 처리할 수 있습니다. 코루틴은 기본적으로 하나의 스레드 내에서 여러 작업을 순차적이면서도 동시에 수행하는 느낌을 주도록 설계되었습니다.
Kotlin의 코루틴은 suspend
키워드와 함께 사용되어 비동기 작업을 단순하고 가독성 높은 코드로 구현할 수 있습니다. 예를 들어, 다음과 같은 코드를 보겠습니다.
delay
함수는 스레드를 블로킹하지 않고 다른 코루틴에게 실행 기회를 넘겨주므로, 하나의 스레드 내에서 효율적으로 여러 작업을 동시에 수행할 수 있습니다.
텍스트 다이어그램으로 코루틴의 실행 흐름을 표현하면 다음과 같습니다.
이처럼 코루틴은 단일 스레드 내에서 협력적으로 작업을 전환하며 실행되기 때문에 스레드 전환에 필요한 비용을 크게 줄일 수 있습니다.
코루틴의 장점과 개선 효과
코루틴은 멀티스레드 방식에 비해 다음과 같은 장점들을 제공합니다.
경량성 및 자원 효율성
수천 개 이상의 코루틴을 생성해도 OS 스레드보다 훨씬 적은 메모리와 CPU 오버헤드를 발생시킵니다.
코루틴은 실제 실행 시점에 스택 메모리를 필요에 따라 할당하므로, 미리 많은 스레드를 생성할 필요가 없습니다.
비동기 코드의 간결함
콜백 지옥(callback hell) 문제를 해소할 수 있으며, 동기 코드와 유사한 구조로 비동기 작업을 작성할 수 있습니다.
suspend
함수와async
/await
패턴을 통해 비동기 처리를 직관적으로 구현할 수 있습니다.
컨텍스트 전환 최소화
코루틴은 OS 레벨의 스레드 스위칭이 아닌, 코루틴 스케줄러에 의한 경량 전환을 사용하므로 성능이 크게 개선됩니다.
I/O나 네트워크 요청 등 대기 상태의 작업에서 불필요한 스레드 차단을 줄입니다.
실제 서버 애플리케이션에서는 많은 클라이언트 요청을 동시에 처리해야 하므로, 스레드 수를 최소화하면서 높은 동시성을 지원하는 것이 중요합니다. 코루틴은 이러한 요구사항에 부합하여, 높은 확장성과 효율성을 보장합니다.
명령어와 코드 예제를 통한 비교
멀티스레드 방식 (Java/Kotlin)
위 예제는 두 개의 스레드를 생성하여 각각의 작업을 블로킹 방식으로 처리합니다. 스레드 간의 전환과 스레드 생성 자체에 소모되는 리소스가 큰 단점입니다.
코루틴 방식 (Kotlin)
코루틴 방식에서는 delay
함수를 사용해 블로킹 없이 작업을 대기시킵니다. 이 경우, 하나의 스레드 내에서 코루틴들이 협력적으로 실행되기 때문에 스레드 생성 비용이 없고, 코드 구조도 간결해집니다.
텍스트 다이어그램을 통해 비교하면 다음과 같습니다.
이와 같이 코루틴은 스레드보다 훨씬 가볍게 실행되며, 여러 작업이 동시에 대기 및 실행되는 상황에서 큰 효율성을 발휘합니다.
Last updated