Virtual Thread ์๋ฆฌ์ฆ ๋ชฉ์ฐจ
- Java Virtual Thread: ์๊ฐ์ ๋์ ์๋ฆฌ
- Java Virtual Thread: Pinning ๋ฐ์ ์์ธ๊ณผ ๋์
- Java Virtual Thread: ์ฑ๋ฅ ์ธก์ ๊ณผ ์ ์ฉ ๊ธฐ์ค
- Java Virtual Thread: Spring Boot ์ ์ฉ๊ณผ ์ฃผ์์ฌํญ
- Java Virtual Thread: Coroutine, WebFlux์ ๋น๊ต
๊ฐ์ ๋ชฉํ, ๋ค๋ฅธ ๋ฐฉ๋ฒ
Java 21์์ Virtual Thread๊ฐ ์ ์์ผ๋ก ๋ค์ด์จ ๋ค โ๊ทธ๋ฌ๋ฉด Kotlin Coroutine์ ํ์ ์์ด์ง๋ ๊ฑด ์๋๊ฐโ๋ผ๋ ์ด์ผ๊ธฐ๊ฐ ๋์๋ค. ์ฌ๊ธฐ์ Spring WebFlux(Project Reactor)๊น์ง ๋ํ๋ฉด ๊ฐ์ ๋ฌธ์ ๋ฅผ ์ธ ๊ฐ์ง ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ํธ๋ ๊ตฌ์กฐ๊ฐ ๋๋ค.
- Virtual Thread: JVM ๋ฐํ์์ด ์ ๊ณตํ๋ ๊ธฐ๋ฅ. ๋ธ๋กํน ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์ฐ๋ฉด์ ์ฒ๋ฆฌ๋์ ๋์ธ๋ค.
- Kotlin Coroutine: ์ธ์ด ์์ค์ ๊ธฐ๋ฅ.
suspendํจ์์ ์ฝ๋ฃจํด ๋น๋๋ก ๋น๋๊ธฐ ํ๋ฆ์ ํํํ๋ค. - WebFlux (Reactor): ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ.
Mono/Flux๋ก ๋น๋ธ๋กํน ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๋ค.
์ด ํธ์์๋ ๋ด์ค๋ ํฐ ๋ฐ์ก ์์๋ฅผ ์ธ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ฉด์ ๊ตฌ์กฐ์ ์ฐจ์ด๋ฅผ ์ดํด๋ณธ๋ค.
์ฝ๋ ์คํ์ผ ๋น๊ต
Virtual Thread (Java)
public class NewsletterDispatcher {
private final MailClient mailClient;
public NewsletterDispatcher(MailClient mailClient) {
this.mailClient = mailClient;
}
public void dispatch(List<Subscriber> subscribers, Newsletter newsletter) {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (Subscriber subscriber : subscribers) {
executor.submit(() -> mailClient.send(subscriber.email(), newsletter));
}
}
}
}
mailClient.send()๋ ์ผ๋ฐ ๋ธ๋กํน ๋ฉ์๋๋ค. ๊ธฐ์กด ๋ธ๋กํน ์ฝ๋์ ์ฐจ์ด๊ฐ ์๋ค. Executor๋ง ๋ฐ๊ฟจ๋ค.
Kotlin Coroutine
class NewsletterDispatcher(private val mailClient: MailClient) {
suspend fun dispatch(subscribers: List<Subscriber>, newsletter: Newsletter) {
coroutineScope {
subscribers.forEach { subscriber ->
launch(Dispatchers.IO) {
mailClient.send(subscriber.email, newsletter)
}
}
}
}
}
suspend ํค์๋์ coroutineScope, launch ๊ฐ์ ์ฝ๋ฃจํด ๋น๋๊ฐ ๋ฑ์ฅํ๋ค.
mailClient.send()๊ฐ ๋ธ๋กํน ํธ์ถ์ด๋ผ๋ฉด Dispatchers.IO์์ ์คํํด์ผ ์ค๋ ๋๋ฅผ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ค.
mailClient.send()๊ฐ suspend ํจ์๋ผ๋ฉด Dispatchers.IO ์์ด ๊ธฐ๋ณธ ๋์คํจ์ฒ์์ ์คํํ ์ ์๊ณ , ์ง์ ํ ๋น๋ธ๋กํน ์ฒ๋ฆฌ๊ฐ ๋๋ค.
WebFlux (Reactor)
public class NewsletterDispatcher {
private final ReactiveMailClient mailClient;
public NewsletterDispatcher(ReactiveMailClient mailClient) {
this.mailClient = mailClient;
}
public Mono<Void> dispatch(List<Subscriber> subscribers, Newsletter newsletter) {
return Flux.fromIterable(subscribers)
.flatMap(subscriber -> mailClient.send(subscriber.email(), newsletter))
.then();
}
}
ReactiveMailClient.send()๋ Mono<Void>๋ฅผ ๋ฐํํ๋ ๋ฆฌ์กํฐ๋ธ API๋ค.
flatMap์ผ๋ก ๊ฐ ๊ตฌ๋
์์๊ฒ ๋น๋๊ธฐ ๋ฐ์ก์ ์ฐ๊ฒฐํ๊ณ , ์ ์ฒด๊ฐ ์๋ฃ๋๋ฉด then()์ผ๋ก ๋ง๋ฌด๋ฆฌํ๋ค.
๋ธ๋กํน ์ฝ๋๊ฐ ์ ํ ์๋ค. ๋์ API ์ ์ฒด๊ฐ ๋ฆฌ์กํฐ๋ธ ํ์
์ผ๋ก ๋ฐ๋๋ค.
flatMap์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ต๋ 256๊ฐ ์์
์ ๋์์ ์ฒ๋ฆฌํ๋ค(Queues.SMALL_BUFFER_SIZE).
Virtual Thread์ฒ๋ผ ํ์คํฌ๋ง๋ค ์ฆ์ ์์ํ๋ ค๋ฉด flatMap(f, Integer.MAX_VALUE)๋ก ๋์์ฑ ์ ํ์ ํ์ด์ผ ํ๋ค.
๋ค๋ง ๊ธฐ๋ณธ๊ฐ์ ์์ฐ์ค๋ฌ์ด ๋ฐฑํ๋ ์
์ญํ ๋ ํ๋ฏ๋ก ๋ฌด์์ ์ ๊ฑฐํ ํ์๋ ์๋ค.
๊ตฌ์กฐ์ ์ฐจ์ด
์ธ ๋ฐฉ์์ด ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋จผ์ ํ๋ก ์ ๋ฆฌํ๊ณ , ๊ฐ ํญ๋ชฉ์ ์์ธํ ์ดํด๋ณธ๋ค.
| ํญ๋ชฉ | Virtual Thread | Kotlin Coroutine | WebFlux |
|---|---|---|---|
| ์ค๋จ ๋ฐฉ์ | JVM์ด I/O ์ง์ ์์ ์๋ ์ฒ๋ฆฌ | suspend ํธ์ถ ์ง์ ์์ ๋ช
์์ ์ค๋จ |
์คํผ๋ ์ดํฐ ์ฒด์ธ, ์ค๋จ ๊ฐ๋ ์์ |
| ์ทจ์/ํ์์์ | StructuredTaskScope (Preview) |
withTimeout ์๋ ์ ํ |
.timeout() ์คํผ๋ ์ดํฐ |
| ์ปจํ ์คํธ ์ ํ | ScopedValue (Preview) / ThreadLocal |
CoroutineContext ์๋ ์ ํ |
Reactor Context, ๋ณ๋ ๋ธ๋ฆฌ์ง ํ์ |
| ์ฝ๋ ์คํ์ผ | ๊ธฐ์กด ๋ธ๋กํน ์ฝ๋ ๊ทธ๋๋ก | suspend ํจ์ ๋์
|
์ ์ธํ ๋ฆฌ์กํฐ๋ธ ํ์ดํ๋ผ์ธ |
| ํ์ต ๋น์ฉ | ๋ฎ์ | ์ค๊ฐ | ๋์ |
์ด๋์ ์ค๋จ๋๋๊ฐ
Virtual Thread๋ ๋ธ๋กํน I/O ์ง์ ์์ JVM์ด ์๋์ผ๋ก carrier๋ฅผ ์๋ณดํ๋ค. ๊ฐ๋ฐ์๊ฐ ์ค๋จ ์ง์ ์ ๋ช ์ํ์ง ์์๋ ๋๋ค.
Coroutine์ suspend ํจ์ ํธ์ถ ์ง์ ์์๋ง ์ค๋จ๋ ์ ์๋ค.
์ค๋จ ๊ฐ๋ฅํ ์ง์ ์ด ์ฝ๋์ ๋ช
์์ ์ผ๋ก ๋๋ฌ๋๋ค.
WebFlux๋ ์ค๋จ์ด๋ผ๋ ๊ฐ๋
์ด ์๋ค. flatMap, map ๊ฐ์ ์คํผ๋ ์ดํฐ๊ฐ ๋น๋ธ๋กํน ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๊ณ , Reactor ์ค์ผ์ค๋ฌ๊ฐ ํ๋ฆ์ ์ฒ๋ฆฌํ๋ค.
์ฝ๋ ์ ์ฒด๊ฐ ์ ์ธํ์ผ๋ก ํํ๋๋ค.
์ทจ์์ ํ์์์
Coroutine์ ๊ตฌ์กฐ์ ๋์์ฑ(Structured Concurrency)์ ์ง์ํ๋ค.
coroutineScope๊ฐ ์ทจ์๋๋ฉด ๊ทธ ์์ ๋ชจ๋ launch ๋ธ๋ก์ด ํจ๊ป ์ทจ์๋๋ค.
withTimeout(5.seconds) {
coroutineScope {
subscribers.forEach { subscriber ->
launch {
mailClient.send(subscriber.email, newsletter)
}
}
}
}
withTimeout์ kotlin.time.Duration์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ๋๋ค.
5์ด ์์ ์๋ฃ๋์ง ์์ผ๋ฉด coroutineScope ์ ์ฒด๊ฐ ์ทจ์๋๊ณ , ์งํ ์ค์ธ ๋ชจ๋ ์์ ์ฝ๋ฃจํด์ ์ทจ์ ์ ํธ๊ฐ ์ ํ๋๋ค.
WebFlux๋ ์คํผ๋ ์ดํฐ ํ ์ค๋ก ๋์ผํ ํจ๊ณผ๋ฅผ ๋ผ ์ ์๋ค.
dispatch(subscribers, newsletter)
.timeout(Duration.ofSeconds(5))
.subscribe();
Java์ Virtual Thread๋ StructuredTaskScope(JEP 480, Java 23 Preview)๋ฅผ ํตํด ๊ตฌ์กฐ์ ๋์์ฑ์ ์ง์ํ๋ค.
StructuredTaskScope๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ Virtual Thread๋ฅผ ํ๋์ ๋
ผ๋ฆฌ์ ๋จ์๋ก ๋ฌถ์ด ๊ด๋ฆฌํ ์ ์๋ค.
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
subscribers.forEach(subscriber ->
scope.fork(() -> {
mailClient.send(subscriber.email(), newsletter);
return null;
})
);
scope.join();
scope.throwIfFailed();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
ShutdownOnFailure ์ ์ฑ
์ ์ฌ์ฉํ๋ฉด ์์ ์ค๋ ๋ ์ค ํ๋๊ฐ ์คํจํ ๊ฒฝ์ฐ ๋๋จธ์ง๋ฅผ ์ฆ์ ์ทจ์ํ๋ค.
join()์ InterruptedException์, throwIfFailed()๋ ExecutionException์ ๋์ง๋ฏ๋ก ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
์ปจํ ์คํธ ์ ํ
Virtual Thread๋ ThreadLocal ๊ธฐ๋ฐ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๋ค. ์์ ์ค๋ ๋๋ก ์ ํํ๋ ค๋ฉด ๊ฐ์ ๋ช ์์ ์ผ๋ก ๋ณต์ฌํด์ผ ํ๋ค.
Java 21๋ถํฐ Preview๋ก ๋์
๋ ScopedValue(JEP 481, Java 23 Preview)๋ ์ด ๋ฌธ์ ๋ฅผ ๊ฐ์ ํ๋ค.
๋ถ๋ณ ๊ฐ์ ํน์ ๋ฒ์ ์์์๋ง ์ ํจํ๊ฒ ์ ๋ฌํ๋ฉฐ, StructuredTaskScope์ ํจ๊ป ์ฐ๋ฉด ์์ ์ค๋ ๋๋ก ์๋ ์์๋๋ค.
private static final ScopedValue<String> REQUEST_ID = ScopedValue.newInstance();
ScopedValue.where(REQUEST_ID, "req-123").run(() -> {
mailClient.send(subscriber.email(), newsletter);
});
๋ค๋ง ThreadLocal ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(MDC, Spring Security ๋ฑ)์์ ํธํ์ ์ํด์๋ ์ฌ์ ํ ๋ณ๋ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
Coroutine์ CoroutineContext๋ฅผ ํตํด MDC ๊ฐ, ํธ๋์ญ์
์ปจํ
์คํธ ๊ฐ์ ์ ๋ณด๋ฅผ ์์ ์ฝ๋ฃจํด์ ์๋์ผ๋ก ์ ํํ ์ ์๋ค.
kotlinx-coroutines-slf4j๊ฐ ์ ๊ณตํ๋ MDCContext๋ฅผ ์ฌ์ฉํ๋ฉด MDC ๊ฐ์ด ์ฝ๋ฃจํด ์ฌ๊ฐ ์ ์๋์ผ๋ก ๋ณต์๋๋ค.
launch(Dispatchers.IO + MDCContext()) {
mailClient.send(subscriber.email, newsletter)
}
WebFlux๋ Reactor Context๋ก ์ปจํ
์คํธ๋ฅผ ์ ํํ๋ค.
ํ์ดํ๋ผ์ธ ์์์ contextWrite()๋ก ๊ฐ์ ์ฃผ์
ํ๊ณ Mono.deferContextual()๋ก ์ฝ๋๋ค.
Mono.just(subscriber)
.flatMap(s -> mailClient.send(s.email(), newsletter))
.contextWrite(Context.of("requestId", requestId));
ThreadLocal ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ Reactor Context์ ์ง์ ์ฐ๊ฒฐ๋์ง ์์ ๋ณ๋ ๋ธ๋ฆฌ์ง ์ค์ ์ด ํ์ํ๋ค.
์ฑ๋ฅ ๋น๊ต
| ํญ๋ชฉ | Virtual Thread | Kotlin Coroutine | WebFlux |
|---|---|---|---|
| ์ค๋ ๋ ์ | carrier ์ โ ์ฝ์ด ์ | ๋์คํจ์ฒ ์ค์ ์ ๋ฐ๋ผ ๋ค๋ฆ | ์ด๋ฒคํธ ๋ฃจํ (๋งค์ฐ ์ ์) |
| I/O ๋๊ธฐ ์ฒ๋ฆฌ | carrier ์๋ณด | suspend + ๋น๋ธ๋กํน ์ ํ ๊ฐ๋ฅ | ์์ ๋น๋ธ๋กํน |
| ๊ทนํ ๋์ ์ฐ๊ฒฐ | ๋ณดํต | ๋์ | ๋งค์ฐ ๋์ |
| ๋ฉ๋ชจ๋ฆฌ (ํ) | ํ ์คํ, ํ์ํ ๋งํผ๋ง | continuation ๊ฐ์ฒด | ์คํผ๋ ์ดํฐ ์ฒด์ธ |
Virtual Thread๋ carrier ์๊ฐ CPU ์ฝ์ด ์์ ๋น๋กํ๋ค. ๋๊ธฐ ์ค์๋ carrier๋ฅผ ๋ฐํํ๋ฏ๋ก ๋๋ถ๋ถ์ ์๋ฒ ์ํฌ๋ก๋์์ ์ถฉ๋ถํ ์ฑ๋ฅ์ ๋ธ๋ค.
Coroutine์ suspend + ๋น๋ธ๋กํน I/O ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์กฐํฉํ๋ฉด OS ์ค๋ ๋๋ฅผ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ์ง์ ํ ๋น๋ธ๋กํน ๊ฒฝ๋ก๋ฅผ ์ ํํ ์ ์๋ค.
WebFlux๋ Netty์ ์ด๋ฒคํธ ๋ฃจํ ์์์ ๋์ํ๋ค. ๊ทน์์์ ์ค๋ ๋๋ก ๋งค์ฐ ๋์ ๋์์ฑ์ ์ฒ๋ฆฌํ ์ ์์ด, ์ฐ๊ฒฐ ์๊ฐ ๊ทน๋จ์ ์ผ๋ก ๋ง์ ํ๊ฒฝ์์ ์ด์ ์ด ์๋ค.
์์ญ๋ง ๊ฐ ๋์์ฑ ์ํฉ์ด ์๋๋ผ๋ฉด ์ธ ๋ฐฉ์ ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ฐจ์ด๋ ํฌ์ง ์๋ค.
์ ํ ๊ธฐ์ค
| ์ํฉ | ๊ถ์ฅ |
|---|---|
| ๊ธฐ์กด Java ๋ธ๋กํน ์ฝ๋๋ฒ ์ด์ค์ ๋น ๋ฅด๊ฒ ์ ์ฉ | Virtual Thread |
| ์ฝ๋ ๋ณ๊ฒฝ ์ต์ํ | Virtual Thread |
| Kotlin ํ๋ก์ ํธ | Coroutine |
| ๊ตฌ์กฐ์ ๋์์ฑ, ์ทจ์ ์ ํ๊ฐ ์ค์ํ ๊ฒฝ์ฐ | Coroutine |
| ๋น๋ธ๋กํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Ktor, R2DBC)์ ํจ๊ป ์ฌ์ฉ | Coroutine |
| ๊ทนํ์ ๋์ ์ฐ๊ฒฐ ์, ๋ฆฌ์กํฐ๋ธ ์ํ๊ณ ์ ์ฒด ํ์ฉ | WebFlux |
| Java + Kotlin ํผํฉ ํ๋ก์ ํธ | ์ํฉ์ ๋ฐ๋ผ ํผํฉ ๊ฐ๋ฅ |
Virtual Thread๋ ๊ธฐ์กด Java ์ฝ๋๋ฒ ์ด์ค์ ๊ฐ์ฅ ์์ฐ์ค๋ฝ๊ฒ ๋ น์๋ ๋ค. ๋ธ๋กํน ์ฝ๋๋ฅผ ๊ทธ๋๋ก ๋๊ณ Executor๋ง ๋ฐ๊พธ๋ฉด ๋๋ฏ๋ก, ๋ ๊ฑฐ์ ํ๋ก์ ํธ๋ ํ ๋ด ๋น๋๊ธฐ ๊ฒฝํ์ด ๋ง์ง ์์ ๊ฒฝ์ฐ์ ์ค์ฉ์ ์ธ ์ ํ์ด๋ค.
Coroutine์ Kotlin ํ๋ก์ ํธ์์ ์ ์ญ๋์ ๋ฐํํ๋ค.
withTimeout, coroutineScope ๊ฐ์ ๊ตฌ์กฐ์ ๋์์ฑ ๋๊ตฌ๊ฐ ์ทจ์ ์ ํ์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ๋ช
ํํ๊ฒ ํํํด ์ค๋ค.
๋น๋ธ๋กํน ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Ktor ํด๋ผ์ด์ธํธ, R2DBC)์ ์กฐํฉํ๋ฉด OS ์ค๋ ๋๋ฅผ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ์ง์ ํ ๋น๋ธ๋กํน ๊ฒฝ๋ก๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค.
WebFlux๋ ๊ทน๋จ์ ์ธ ๋์ ์ฐ๊ฒฐ์ด ์๊ตฌ๋๋ ํ๊ฒฝ, ๋๋ ์ด๋ฏธ ๋ฆฌ์กํฐ๋ธ ์ํ๊ณ๋ฅผ ์ ๋ฉด ์ฑํํ ํ๋ก์ ํธ์ ์ ํฉํ๋ค. ํ์ต ๋น์ฉ๊ณผ ์ฝ๋ ๋ณต์ก๋๊ฐ ๋์ ๋งํผ, ์ด ์ด์ ์ด ์ค์ ๋ก ํ์ํ ์ํฉ์ธ์ง ๋จผ์ ๋ฐ์ ธ๋ณด๋ ๊ฒ์ด ์ข๋ค.
Virtual Thread + Coroutine
Kotlin ํ๋ก์ ํธ์์ Virtual Thread์ Coroutine์ ํจ๊ป ์ฌ์ฉํ ์๋ ์๋ค.
Dispatchers.IO๋ฅผ Virtual Thread ๊ธฐ๋ฐ Executor๋ก ๊ต์ฒดํ๋ฉด ๋ ๋ฐฉ์์ ์กฐํฉํ ์ ์๋ค.
val virtualThreadDispatcher = Executors.newVirtualThreadPerTaskExecutor()
.asCoroutineDispatcher()
launch(virtualThreadDispatcher) {
mailClient.send(subscriber.email, newsletter)
}
๋จ, ์ด ์กฐํฉ์ด ํญ์ ๋ ๋์ ์ฑ๋ฅ์ ๋ณด์ฅํ์ง๋ ์๋๋ค.
๋ธ๋กํน ์ฝ๋๋ฅผ Dispatchers.IO์์ ์คํํ๋ ๊ธฐ์กด ํจํด์ด ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ถฉ๋ถํ๋ค.
๋ ๋ฐฉ์์ ํผ์ฉํ๊ธฐ ์ ์ ์ค์ ๋ก ๋ณ๋ชฉ์ด ์ด๋์ ์๋์ง ๋จผ์ ์ธก์ ํ๋ ๊ฒ์ด ์์๋ค.
WebFlux์ ํผ์ฉํ์ง ์๋ ์ด์
WebFlux์ Virtual Thread๋ ํจ๊ป ์ฐ์ง ์๋ ๊ฒ์ด ์ข๋ค. WebFlux๋ ์์์ ์ด๋ฒคํธ ๋ฃจํ ์ค๋ ๋๊ฐ ๋น๋ธ๋กํน์ผ๋ก ๋ชจ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๊ตฌ์กฐ๋ค. ์ฌ๊ธฐ์ Virtual Thread๋ฅผ ์ถ๊ฐํ๋ฉด ๋ ์ค๋ ๋ ๋ชจ๋ธ์ด ์ถฉ๋ํด ์ด๋ ์ชฝ์ ์ด์ ๋ ์ ๋๋ก ์ป์ง ๋ชปํ๋ค.
Virtual Thread๋ spring-boot-starter-web ๊ธฐ๋ฐ Servlet ์คํ์์ ํ์ฑํํ๋ ๊ฒ์ด ์ ํฉํ๋ค.
WebFlux(spring-boot-starter-webflux) ๊ธฐ๋ฐ ํ๋ก์ ํธ์์๋ ํ์ฑํํ์ง ์๋๋ค.
๋ง๋ฌด๋ฆฌ
Virtual Thread, Kotlin Coroutine, WebFlux๋ ๊ฐ์ ๋ฌธ์ ๋ฅผ ์๋ก ๋ค๋ฅธ ์์ค์์ ํด๊ฒฐํ๋ค.
- Virtual Thread: ๋ธ๋กํน ์ฝ๋์ ๋น์ฉ์ ๋ฎ์ถ๋ JVM ๋ฐํ์ ์ต์ ํ. ์ฝ๋ ๋ณ๊ฒฝ ์์ด ์ฒ๋ฆฌ๋์ ๋์ธ๋ค.
- Coroutine: ๋น๋๊ธฐ ํ๋ฆ์ ๊ตฌ์กฐ์ ์ผ๋ก ํํํ๋ ์ธ์ด ์ถ์ํ. ์ทจ์ ์ ํ์ ์ปจํ ์คํธ ๊ด๋ฆฌ๊ฐ ๊ฐ์ ์ด๋ค.
- WebFlux: ๋ฆฌ์กํฐ๋ธ ํ์ดํ๋ผ์ธ ์ ์ฒด๋ฅผ ๋น๋ธ๋กํน์ผ๋ก ๊ตฌ์ฑํ๋ ํ๋ก๊ทธ๋๋ฐ ๋ชจ๋ธ. ๊ทนํ์ ๋์์ฑ์ด ํ์ํ ๋ ๊ฐ์ ์ด ์๋ค.
Virtual Thread๊ฐ ๋์๋ค๊ณ Coroutine์ด๋ WebFlux๊ฐ ํ์ ์์ด์ง๋ ๊ฑด ์๋๋ค. Java๋ง ์ด๋ค๋ฉด Virtual Thread๊ฐ ๊ฐ์ฅ ์ค์ฉ์ ์ธ ์ถ๋ฐ์ ์ด๋ค. Kotlin์ ์ด๋ค๋ฉด Coroutine์ด ์ ๊ณตํ๋ ๊ตฌ์กฐ์ ๋์์ฑ์ Virtual Thread๋ง์ผ๋ก๋ ์ป๊ธฐ ์ด๋ ต๋ค. ์ฐ๊ฒฐ ์๊ฐ ๊ทน๋จ์ ์ผ๋ก ๋ง๊ณ ๋ฆฌ์กํฐ๋ธ ์ํ๊ณ๋ฅผ ์ด๋ฏธ ์ฐ๊ณ ์๋ค๋ฉด WebFlux๊ฐ ์ฌ์ ํ ์ ํจํ๋ค.
์ง๊ธ๊น์ง Virtual Thread์ ๋์ ์๋ฆฌ๋ถํฐ Pinning ์ง๋จ, ์ฑ๋ฅ ์ธก์ , Spring Boot ์ ์ฉ, ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ๋ฐฉ์๊ณผ์ ๋น๊ต๊น์ง ๋ค๋ค๋ดค๋ค. ๊ฒฐ๊ตญ ์ด๋ ์ชฝ์ด ๋ ๋ซ๋ค๋ ๋ฌธ์ ๊ฐ ์๋๋ผ, ํ๋ก์ ํธ ํ๊ฒฝ๊ณผ ํ ์ํฉ์ ๋ง๋ ๊ฒ์ ๊ณ ๋ฅด๋ ๊ฒ์ด ์ค์ํ๋ค.