Virtual Thread

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” Java 21์—์„œ ์ •์‹ ๋„์ž…๋œ ๊ฒฝ๋Ÿ‰ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ๋กœ, ๊ธฐ์กด์˜ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ€์ง„ ๋ฆฌ์†Œ์Šค ์ข…์†์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ๋‹จ์ˆœํ•œ ๋™๊ธฐ์‹ ์ฝ”๋“œ๋กœ ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰์„ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์„ค๊ณ„๋˜์—ˆ๋‹ค.

  • OS ์Šค๋ ˆ๋“œ์— 1:1๋กœ ๋งคํ•‘๋˜์ง€ ์•Š๊ณ  JVM ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌ๋˜๋Š” ๋…ผ๋ฆฌ์  ์‹คํ–‰ ๋‹จ์œ„

  • ์ˆ˜๋ฐฑ๋งŒ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๋™์‹œ์— ์ƒ์„ฑํ•˜๋”๋ผ๋„ ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๊ทนํžˆ ์ ์Œ

  • ๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋ณต์žก์„ฑ ์—†์ด ๊ธฐ์กด ์„œ๋ธ”๋ฆฟ ๊ธฐ๋ฐ˜์˜ Thread-per-request ๋ชจ๋ธ ์œ ์ง€ ๊ฐ€๋Šฅ

  • ๋ธ”๋กœํ‚น I/O ์ž‘์—…์ด ๋ฐœ์ƒํ•ด๋„ OS ์Šค๋ ˆ๋“œ ์ ์œ  ์—†์ด ํšจ์œจ์ ์œผ๋กœ ๋Œ€๊ธฐํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„

๋„์ž… ๋ฐฐ๊ฒฝ ๋ฐ ํ•œ๊ณ„ ๊ทน๋ณต

์ „ํ†ต์ ์ธ ์ž๋ฐ” ๋™๊ธฐํ™” ๋ชจ๋ธ์€ ์šด์˜์ฒด์ œ์˜ ์ปค๋„ ์Šค๋ ˆ๋“œ๋ฅผ ๋ž˜ํ•‘ํ•œ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ์ด ๋ฐฉ์‹์€ ํ™•์žฅ์„ฑ ์ธก๋ฉด์—์„œ ๋ช…ํ™•ํ•œ ํ•œ๊ณ„๋ฅผ ์ง€๋‹Œ๋‹ค.

  • ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ์˜ ๋น„์šฉ ๋ฌธ์ œ

    • ๋ฉ”๋ชจ๋ฆฌ ์ ์œ : ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋Š” ์ƒ์„ฑ ์‹œ ์•ฝ 1MB์˜ ๊ณ ์ •๋œ ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น

    • ์ƒ์„ฑ ๋น„์šฉ: OS ์ปค๋„์ด ์ง์ ‘ ๊ฐœ์ž…ํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ์‹œ๊ฐ„ ์†Œ๋ชจ๊ฐ€ ํผ

    • ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ: ์Šค๋ ˆ๋“œ ๊ฐ„ ์ „ํ™˜ ์‹œ ์ปค๋„ ๋ชจ๋“œ ๊ถŒํ•œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜์—ฌ CPU ์‚ฌ์ดํด ๋‚ญ๋น„ ๋ฐœ์ƒ

  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ชจ๋ธ์˜ ๋ณ€ํ™”

    • ํ˜„๋Œ€์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ CPU ์—ฐ์‚ฐ๋ณด๋‹ค I/O(DB ํ˜ธ์ถœ, API ์—ฐ๋™) ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋” ํผ

    • ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋Š” I/O ๋ธ”๋กœํ‚น ๋ฐœ์ƒ ์‹œ ํ•ด๋‹น ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋ฌด ์ผ๋„ ํ•˜์ง€ ๋ชปํ•˜๊ณ  ์ž์›์„ ์ ์œ ํ•˜๋Š” ๋‚ญ๋น„ ๋ฐœ์ƒ

    • ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” ์ด๋Ÿฌํ•œ ๋Œ€๊ธฐ ์‹œ๊ฐ„์— ์ž์›์„ ๋ฐ˜๋‚ฉํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด ์ž์› ํšจ์œจ์„ฑ ๊ทน๋Œ€ํ™”

๋‚ด๋ถ€ ๋™์ž‘ ์›๋ฆฌ์™€ ์Šค์ผ€์ค„๋ง

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” JDK ๋‚ด๋ถ€์˜ ForkJoinPool์„ ์Šค์ผ€์ค„๋Ÿฌ๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ์‹ค์ œ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ์ธ ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ(Carrier Thread) ์œ„์—์„œ ์‹คํ–‰๋œ๋‹ค.

spinner

๋งˆ์šดํŠธ(Mount)์™€ ์–ธ๋งˆ์šดํŠธ(Unmount)

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ์— ํ• ๋‹น๋˜๋Š” ๊ณผ์ •์„ ๋งˆ์šดํŠธ๋ผ๊ณ  ํ•˜๋ฉฐ, ๊ทธ ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. Mount: ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋ฅผ ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ์— ํ• ๋‹นํ•˜์—ฌ ์‹คํ–‰ ์ƒํƒœ๋กœ ์ „ํ™˜

  2. Execution: ์ฝ”๋“œ ์‹คํ–‰

  3. Unmount (Yield): I/O ์ž‘์—…์ด๋‚˜ Sleep ๋“ฑ ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•˜๋ฉด, ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ์—์„œ ๋‚ด๋ ค์™€ ์–ธ๋งˆ์šดํŠธ ์ƒํƒœ๋กœ ์ „ํ™˜

    • ํ˜„์žฌ๊นŒ์ง€์˜ ์Šคํƒ ์ƒํƒœ๋ฅผ Heap ์˜์—ญ์— ์ €์žฅ

  4. Wait: ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ์‰ฌ๋Š” ๋™์•ˆ ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ๋Š” ๋‹ค๋ฅธ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋ฅผ ์ฒ˜๋ฆฌ

  5. Remount: I/O๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋‹ค์‹œ ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ์— ๋งˆ์šดํŠธ๋˜์–ด Heap์— ์ €์žฅํ–ˆ๋˜ ์ƒํƒœ๋ฅผ ๋ณต๊ตฌํ•˜๊ณ  ์‹คํ–‰ ์žฌ๊ฐœ

์ปจํ‹ฐ๋‰ด์—์ด์…˜(Continuation)

  • ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ์˜ ํ•ต์‹ฌ ๋งค์ปค๋‹ˆ์ฆ˜์œผ๋กœ, ์‹คํ–‰ ์ค‘์ธ ์ง€์ ์˜ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•˜๊ณ  ๋‚˜์ค‘์— ํ•ด๋‹น ์ง€์ ๋ถ€ํ„ฐ ์žฌ๊ฐœํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ

  • JVM์€ ์–ธ๋งˆ์šดํŠธ ์‹œ์ ์— CPU ๋ ˆ์ง€์Šคํ„ฐ์™€ ์Šคํƒ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํž™์œผ๋กœ ๋ณต์‚ฌํ•˜๊ณ , ์žฌ๊ฐœ ์‹œ์ ์— ๋‹ค์‹œ ๋ณต๊ตฌ

ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ์™€ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ๋น„๊ต

๊ตฌ๋ถ„
ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ (Platform Thread)
๊ฐ€์ƒ ์Šค๋ ˆ๋“œ (Virtual Thread)

๊ด€๋ฆฌ ์ฃผ์ฒด

OS ์ปค๋„

JVM

๊ธฐ๋ณธ ์Šคํƒ ํฌ๊ธฐ

์•ฝ 1MB (๊ณ ์ •์ )

์ˆ˜๋ฐฑ ๋ฐ”์ดํŠธ ~ ์ˆ˜ KB (๊ฐ€๋ณ€์ )

์ƒ์„ฑ ๋น„์šฉ

๋งค์šฐ ๋†’์Œ (ํ’€๋ง ํ•„์ˆ˜)

๋งค์šฐ ๋‚ฎ์Œ (ํ•„์š” ์‹œ ์ƒ์„ฑ)

์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ

OS ์ปค๋„ ์Šค์œ„์นญ (๋ฌด๊ฑฐ์›€)

JVM ๋‚ด ์Šค์œ„์นญ (๊ฐ€๋ฒผ์›€)

ํ™•์žฅ์„ฑ

์ˆ˜์ฒœ ๊ฐœ ์ˆ˜์ค€

์ˆ˜๋ฐฑ๋งŒ ๊ฐœ ์ˆ˜์ค€

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ vs ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(WebFlux) ์ƒ์„ธ ๋น„๊ต

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ์™€ ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋ชจ๋ธ์€ ๋ชจ๋‘ ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰์„ ๋ชฉ์ ์œผ๋กœ ํ•˜์ง€๋งŒ, ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅธ ์ฒ ํ•™๊ณผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

๊ตฌ๋ถ„
๊ฐ€์ƒ ์Šค๋ ˆ๋“œ (Virtual Thread)
๋ฆฌ์•กํ‹ฐ๋ธŒ (Spring WebFlux)

๋™์ž‘ ๋ฉ”์ปค๋‹ˆ์ฆ˜

์ปจํ‹ฐ๋‰ด์—์ด์…˜ ๋ฐ ๋งˆ์šดํŠธ ์ „๋žต ํ™œ์šฉ

์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ฐ ์ฝœ๋ฐฑ ๊ธฐ๋ฐ˜ ์ฒ˜๋ฆฌ

I/O ์ฒ˜๋ฆฌ ๋ฐฉ์‹

๊ธฐ์กด ๋ธ”๋กœํ‚น ์ฝ”๋“œ ๋ฐฉ์‹

๋…ผ๋ธ”๋กœํ‚น ๋งค์ปค๋‹ˆ์ฆ˜ ํ•„์š”

๋ฐฐ์•• (Backpressure)

๋ณ„๋„์˜ ์ œ์–ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์กด์žฌํ•˜์ง€ ์•Š์Œ

๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์ฆˆ ํ‘œ์ค€์„ ํ†ตํ•œ ๊ฐ•๋ ฅํ•œ ํ๋ฆ„ ์ œ์–ด

๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐ ์œ„ํ—˜

์ˆ˜๋ฐฑ๋งŒ ๊ฐœ ์ƒ์„ฑ ์‹œ ํž™ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ๊ธ‰์ฆํ•˜๊ฑฐ๋‚˜ ThreadLocal ๋‚จ์šฉ ์‹œ OOM ์œ„ํ—˜ ์กด์žฌ

๊ณ ์ •๋œ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ผ์ •ํ•˜๊ณ  ์˜ˆ์ธก ๊ฐ€๋Šฅ

์ž์› ํšจ์œจ์„ฑ

์ˆ˜๋ฐฑ๋งŒ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋‚˜ ๊ฐœ๋ณ„ ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ ์ €์žฅ ๋น„์šฉ ๋ฐœ์ƒ

์ ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋กœ ๋Œ€๊ทœ๋ชจ ๋™์‹œ ์—ฐ๊ฒฐ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณ ๋ฐ€๋„ ํšจ์œจ์„ฑ

์—๋Ÿฌ ํ•ธ๋“ค๋ง

ํ‘œ์ค€์ ์ธ try-catch ๋ฐ ๋ช…๋ นํ˜• ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ™œ์šฉ

์—ฐ์‚ฐ์ž ์ฒด์ธ ๋‚ด ์ „์šฉ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•œ ๋น„๋™๊ธฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€

์ผ๋ฐ˜์ ์ธ CRUD API, JDBC ๊ธฐ๋ฐ˜ ๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ ์ „ํ™˜, ๋‹จ์ˆœ ๋ณ‘๋ ฌ ์ž‘์—…

์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ, ๊ฒŒ์ดํŠธ์›จ์ด, ์ •๊ตํ•œ ํ๋ฆ„ ์ œ์–ด / ๋ฐฐ์•• ํ•„์š”ํ•œ ์‹œ์Šคํ…œ

์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” ๊ธฐ์กด Thread API๋ฅผ ๊ณ„์Šนํ•˜์ง€๋งŒ, ๋‚ด๋ถ€ ๋™์ž‘ ๋ฐฉ์‹์˜ ์ฐจ์ด๋กœ ์ธํ•ด ๊ธฐ์กด์˜ ์Šค๋ ˆ๋“œ ์‚ฌ์šฉ ํŒจํ„ด์ด ๊ทธ๋Œ€๋กœ ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

  • ์Šค๋ ˆ๋“œ ํ’€ ๋ฏธ์‚ฌ์šฉ

    • ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” ์žฌ์‚ฌ์šฉ์„ ๋ชฉ์ ์œผ๋กœ ์„ค๊ณ„๋˜์ง€ ์•Š์Œ

    • ์ƒ์„ฑ ๋น„์šฉ์ด ๋งค์šฐ ์ €๋ ดํ•˜๋ฏ€๋กœ ExecutorService๋ฅผ ํ†ตํ•ด ํ’€๋งํ•˜๊ธฐ๋ณด๋‹ค ์ž‘์—…๋งˆ๋‹ค ์ƒˆ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹ ๊ถŒ์žฅ

  • ํ”ผ๋‹(Pinning) ํ˜„์ƒ

    • synchronized ๋ธ”๋ก ๋‚ด์—์„œ I/O ์ž‘์—…์ด ๋ฐœ์ƒํ•˜๋ฉด ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ์บ๋ฆฌ์–ด ์Šค๋ ˆ๋“œ์— ๊ณ ์ •๋˜์–ด ์–ธ๋งˆ์šดํŠธ๋˜์ง€ ์•Š์Œ

    • ์ด๋กœ ์ธํ•ด ๋‹ค๋ฅธ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋“ค์ด ์‹คํ–‰ ๊ธฐํšŒ๋ฅผ ์žƒ๋Š” ์„ฑ๋Šฅ ์ €ํ•˜ ๋ฐœ์ƒ

    • ํ•ด๊ฒฐ์ฑ…: synchronized ๋Œ€์‹  ReentrantLock ์‚ฌ์šฉํ•˜์—ฌ ํ”ผ๋‹ ๋ฐฉ์ง€

  • ThreadLocal ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

    • ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ThreadLocal์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋Š” ํž™์œผ๋กœ ์ด๋™ํ•˜์—ฌ ๊ด€๋ฆฌ

    • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ThreadLocal์— ์ €์žฅํ•  ๊ฒฝ์šฐ, ์ˆ˜๋ฐฑ๋งŒ ๊ฐœ์˜ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์กด์žฌํ•˜๋ฉด ํž™ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ํ˜„์ƒ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

    • ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ThreadLocal ์‚ฌ์šฉ์„ ์ตœ์†Œํ™”ํ•˜๊ฑฐ๋‚˜, ๊ฐ€๋ฒผ์šด ๋ฐ์ดํ„ฐ ์œ„์ฃผ๋กœ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

์„ฑ๋Šฅ์  ์ธก๋ฉด์—์„œ์˜ ๊ณ ๋ ค์‚ฌํ•ญ

  • ์ฒ˜๋ฆฌ๋Ÿ‰(Throughput) vs ์‘๋‹ต ์†๋„(Latency): ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋Š” ๊ฐœ๋ณ„ ์ž‘์—…์˜ ์†๋„๋ฅผ ๋น ๋ฅด๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋‹จ์œ„ ์‹œ๊ฐ„๋‹น ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์˜ ์–‘์„ ๋Š˜๋ ค์ฃผ๋Š” ๋„๊ตฌ

  • CPU Bound ์ž‘์—…: ๋ณต์žกํ•œ ์—ฐ์‚ฐ์ด ์ฃผ๋ฅผ ์ด๋ฃจ๋Š” ์ž‘์—…์—์„œ๋Š” ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ์˜ ์ด์ ์ด ์—†์œผ๋ฉฐ, ์˜คํžˆ๋ ค ์Šค์ผ€์ค„๋ง ์˜ค๋ฒ„ํ—ค๋“œ๋กœ ์ธํ•ด ์„ฑ๋Šฅ์ด ํ•˜๋ฝ ๊ฐ€๋Šฅ์„ฑ ์กด์žฌ

  • I/O Bound ์ž‘์—…: ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ์„ ์ฒ˜๋ฆฌํ•˜๋Š” API ์„œ๋ฒ„๋‚˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ํ™˜๊ฒฝ์—์„œ ๋ฆฌ์†Œ์Šค ํšจ์œจ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๋ฐ ์ตœ์ 

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ์‹คํ–‰ ์˜ˆ์ œ

Java 21๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ Executors.newVirtualThreadPerTaskExecutor()๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ œ์ถœ๋˜๋Š” ๋ชจ๋“  ํƒœ์Šคํฌ์— ๋Œ€ํ•ด ์ƒˆ๋กœ์šด ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‹คํ–‰ํ•œ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ ์ง€์›(Spring Boot 3.2+)

Spring Boot 3.2 ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” ๋ณต์žกํ•œ ์„ค์ • ์—†์ด ํ”„๋กœํผํ‹ฐ ํ•˜๋‚˜๋กœ ๋ชจ๋“  ์„œ๋ธ”๋ฆฟ ์ฒ˜๋ฆฌ ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • Tomcat์ด๋‚˜ Jetty ๊ฐ™์€ ๋‚ด์žฅ ์›น ์„œ๋ฒ„๊ฐ€ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ ์ฒ˜๋ฆฌ

  • ๊ธฐ์กด์˜ @Async ์ฒ˜๋ฆฌ๋‚˜ ์Šค์ผ€์ค„๋Ÿฌ ๋“ฑ๋„ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜ Executor ์‚ฌ์šฉ

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ๋ฐฉ์‹ ์‚ฌ์šฉ ์‹œ, ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ(OOM)์ด๋‚˜ ์„ฑ๋Šฅ ์ €ํ•˜ ์—†์ด ์ž‘์—… ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ€์ƒ ์Šค๋ ˆ๋“œ ์ง์ ‘ ์ƒ์„ฑ (Thread Builder)

ํŠน์ • ์ž‘์—… ํ•˜๋‚˜๋ฅผ ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋กœ ์ฆ‰์‹œ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” Thread.ofVirtual() ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํžˆ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

Last updated