1. JVM 프로세스와 스레드
코틀린 애플리케이션이 실행되면 JVM이 프로세스를 시작하고 메인 스레드를 생성하여 메인 함수의 코드를 수행한다. 메인 스레드는 프로세스의 생명주기와 밀접하게 연관되어 있어, 프로세스의 시작부터 종료까지 함께 실행된다. JVM 프로세스는 기본적으로 이 단일 메인 스레드로 동작하며, 메인 함수의 코드가 모두 실행되거나 메인 스레드가 비정상적으로 종료되면 프로세스도 함께 종료된다.
🤔 메인 스레드가 항상 프로세스의 끝을 함께할까?
그렇지 않다. JVM의 프로세스는 모든 사용자 스레드가 종료될 때 종료되며, 메인 스레드는 여러 사용자 스레드 중 하나일 뿐이다. 따라서 멀티 스레드 환경에서는 메인 스레드에서 예외가 발생하더라도, 다른 사용자 스레드가 실행 중이라면 프로세스는 계속 실행된다.
2. 단일 스레드의 한계와 멀티 스레드 프로그래밍
메인 스레드만을 사용하는 단일 스레드 애플리케이션은 한 번에 하나의 작업만 처리할 수 있다는 한계를 가진다. 이로 인해 시간이 오래 걸리는 작업을 수행할 때 다른 작업이 블로킹되어 전반적인 응답성이 저하될 수 있다.
이러한 한계는 멀티 스레드 프로그래밍을 통해 극복할 수 있다. 큰 작업을 여러 개의 독립적인 작은 작업으로 분할하고, 이를 여러 스레드에 분산하여 동시에 처리함으로써 전체적인 응답 속도를 향상시킬 수 있다. 이렇게 여러 스레드가 작업을 동시에 처리하는 방식을 병렬 처리라고 한다.
3. 스레드, 스레드풀을 사용한 멀티 스레드 프로그래밍
JVM에서는 Thread 클래스를 상속하여 사용자 스레드를 생성하고, 이를 통해 작업을 병렬로 실행할 수 있다. 하지만 이 방식에는 두 가지 문제점이 있다:
- Thread 클래스를 상속한 클래스의 인스턴스를 생성할 때마다 새로운 스레드가 만들어지는데, 이 생성 비용이 비싸다.
- 스레드의 생성과 관리를 개발자가 직접 담당해야 하므로, 프로그램의 복잡도가 증가하고 실수로 인한 오류나 메모리 누수가 발생할 위험이 높아진다.
이러한 문제들을 해결하기 위해 Executor 프레임워크가 도입되었다.
Executor 프레임워크는 작업 처리를 위한 스레드 집합인 스레드풀을 사전에 생성하여 관리한다. 새로운 작업이 요청되면 스레드풀 내의 쉬고 있는 스레드에 작업을 할당하고, 작업이 완료된 스레드는 종료하지 않고 다음 작업을 위해 재사용한다. 스레드의 생성, 관리, 작업 분배 등 모든 책임은 Executor 프레임워크가 담당하므로, 개발자는 단순히 스레드풀의 크기를 설정하고 작업을 제출하기만 하면 된다.
하지만 Executor 프레임워크에도 여러 문제가 있는데, 그중 가장 큰 문제는 스레드 블로킹이다. 스레드 블로킹은 스레드가 작업을 수행하지 못하고 대기 상태에 머무는 현상을 말한다. 스레드는 생성과 유지에 많은 비용이 드는 자원이므로, 블로킹 상태가 자주 발생하면 애플리케이션의 전반적인 성능이 저하될 수 있다.
4. 기존 멀티 스레드 프로그래밍의 한계와 코루틴
멀티 스레드 프로그래밍은 지속적으로 발전하며 단점을 보완해왔지만, 여전히 스레드 기반 작업이라는 근본적인 한계를 가지고 있다. 스레드는 생성과 작업 전환에 많은 비용이 들며, 특히 스레드 블로킹은 스레드 기반 작업을 하는 멀티 스레드 프로그래밍에서 피할 수 없는 문제이기도 하다.
하지만 코루틴은 이러한 한계를 해결한다. 작업이 일시 중단될 때 스레드 사용 권한을 다른 작업에 양보하고, 중단된 작업은 나중에 적절한 시점에 재개된다. 이처럼 코루틴은 스레드에 자유롭게 붙었다 떼었다 할 수 있어 '경량 스레드'라고도 불린다.
코루틴의 핵심 장점은 스레드 사용을 최적화하고 블로킹을 방지한다는 점이다. 스레드에 비해 생성과 전환 비용이 매우 적어, 작업 처리에 필요한 리소스와 시간을 크게 절약할 수 있다.
더불어 코루틴은 구조화된 동시성을 제공하여 비동기 작업을 안전하게 처리하고, 효과적인 예외 처리가 가능하며, 실행 스레드를 손쉽게 전환하는 등 기존의 멀티 스레드 프로그래밍에 비해 많은 장점이 있다.
'Study' 카테고리의 다른 글
[오픈소스] Spring Boot 프로젝트 컨트리뷰터 되기 (0) | 2024.04.29 |
---|---|
[Java] Method Area는 Heap 영역이 아니다! (1) | 2024.02.19 |
[Java] 자바 런타임 데이터 영역(Runtime Data Area) (0) | 2024.02.19 |
[Java] 변수와 객체 데이터 저장 (0) | 2024.02.17 |
[DB] 트랜잭션의 격리 수준(Isolation Level)이란? (0) | 2024.02.16 |