Backend/Java, Kotlin

Virtual Thread vs. Coroutine

mopil 2023. 12. 12. 00:37
반응형

DevFest 2023에서 Spring Weflux vs. Virtual Thread 세션을 듣고 정리한 내용과 내생각을 정리 및 공유하고자 한다.

 

# Virtual Thread

Project Loom이라는 프로젝트로, JDK 21버전 부터 공식으로 추가된 자바 전용 코루틴 느낌이다.

 

일반적으로 JVM의 스레드는 OS 스레드와 1:1로 매핑되어서 사용된다.

 

OS 스레드 (커널 스레드)는 그 생성/유지 비용이 비싸 보통 풀링 (스레드 풀)을 통해 미리 만들어놓고 사용한다.

 

당연히 OS 자원이기 때문에 그 수는 제한이 있다.

 

그래서 JVM 레벨에서 이 OS 스레드를 좀 더 나뉘어서 사용하게끔 만든 스레드가 Virtual Thread이고 이는 생성 제한이 없다.

 

가상 스레드의 최고 장점은 기존 자바 스레드 코드와 호환성이 엄청 높고, 전환하더라도 코드를 수정할 부분이 극히 적다는 점이다!

 

 

# thread per request 모델과 이벤트 루프

어찌보면 스레드는 굉장히 비싼 자원이고, thread per request 모델을 사용하는 톰캣은 한 요청이 오래걸려서 해당 스레드가 블록되면 유휴상태가 되는, 비효율적인 구조를 가지고 있다고도 볼 수 있다.

 

따라서 높은 Throughoutput을 요구하는 서버 어플리케이션은 thread per request 모델은 scale up의 한계가 있다.

 

그래서 사람들은 보다 효율적으로 작업을 처리하고 싶었고, 리액티브 프로그래밍이 발전한다. JVM 생태계에서 이를 구현한것은 RxJava와 Reactor(웹플럭스의 Mono, Flux)가 대표적이다.

 

최근 프레임워크들을 보면 거의 이벤트루프 기반의 고효율 고성능 서버 프레임워크들이 많다. 톰캣만 전통적으로 thread per request모델을 고수하고 있다.

 

 

고성능의 서버 어플리케이션을 만들고 싶다면, 스프링 웹플럭스를 활용할 수 있다.

 

 

# 그럼 웹플럭스는 만능인가?

그렇다면 무조건 이벤트루프, 웹플럭스, 리액티브 프로그래밍이 가장 좋은것인가? 는 당연히 아니다.

은탄환은 없다!

 

필자 회사에서도 웹플럭스와 MVC를 모두 사용하고 있지만, 모든 k8s 마이크로 서비스들이 웹플럭스로 만들어지진 않는다. 웹플럭스로 만들어진 서버는 극히 드물다.

 

이유는 러닝커브가 높기 때문이다. 웬만한 TPS는 MVC로도 커버 가능하다. 

JDBC가 블로킹 I/O 인 것도 한 몫한다. R2DBC는 공식 지원 드라이버가 없고 엔터프라이즈 급에서 사용하기에는 애매한 것 같다.

 

 

# 그래서 Virtual Thread가 갖는 의미가 뭔데?

스프링 개발자가 익숙한 MVC 모델에서, 가상 스레드를 enabled하면 톰캣의 thread per request 모델로도 가상 스레드를 활용하여 굉장히 높은 throughoutput을 낼 수 있다는게 쟁점이다.

 

사실, 가상 스레드는 코틀린의 코루틴과 동일하다.

 

 

JVM 특성 상 비동기 프로그래밍을 지원하는 컨셉이 아니여서 (자바스크립트 처럼 언어차원에서 async await을 제공)

코틀린의 코루틴, 자바의 가상 스레드 모두 컴파일러 시점에서 이를 강제로 해결하려는 모습으로 변화해 왔다.

 

결국 두 개념은 동일하고, 내부적으로 Continuation을 구현한것이며, 블로킹을 마주했을 때 기다리지 않고 잠시 중단하여 다른 일을 할 수 있도록 좀 더 효율적으로 스레드를 쓰는 방법을 찾았다고 볼 수 있다.

 

즉, Virtual Thread == Coroutine

 

다만 가상 스레드가 더 좋은점은 기존 자바로 작성된 코드에서 호환이 매우 잘 된다는 점이다. 

 

 

# 결론...?

Virtual Thread가 JDK 21에 정식 출시되었고, 스프링 부트 3.0 이상부터는 아주 쉽게 사용가능하도록 지원하고있다.

 

세션에서는 웹플럭스랑 가상 스레드를 이용한 성능 테스트도 공유해주셨는데, 별반 차이가 없었다.

 

다만 JDBC 경합과 관련된 이슈등을 각 드라이버들이 대응하는 중이라 당장 상용 단계에서 사용하기에는 레퍼런스도 적고 무리가 있지 않나 싶다.

 

확실히 가상 스레드의 등장으로 코루틴의 이점이 많이 퇴색된 것은 맞는 것 같고, 발표자분도 공감하였다. (그래서 미래에 어떻게 될 지 더욱 궁금하다.)

 

자바에서 스레드가 블록되면 os 스레드가 블록 안 되게끔 공식 지원한다는게 핵심인 것 같다.

반응형