ยท Develop  ยท 14 min read

Java NIO์™€ Netty

NIO, ๊ทธ๋ฆฌ๊ณ  Netty

Spring Webflux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์ด ์™€์„œ ๊ณต๋ถ€ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

Spring Boot๋„ 2.x ๋ฒ„์ „๋ถ€ํ„ฐ Webflux ์„ ํƒ์‹œ ๋‚ด์žฅ ํ†ฐ์บฃ์ด ์•„๋‹Œ Netty๋ฅผ ๊ธฐ๋ณธ์„ค์ •์œผ๋กœ ์žก๋Š”๋‹ค.
Netty๋Š” NIO ๊ธฐ๋ฐ˜ ๋„คํŠธ์›Œํฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์ด๊ธฐ ๋•Œ๋ฌธ์— NIO๋„ ๊ฐ™์ด ์ •๋ฆฌํ•˜์˜€๋‹ค.

NIO๋ž€?

Java New Input/Output์˜ ์•ฝ์ž๋กœ ์ž๋ฐ” 4๋ถ€ํ„ฐ๋ถ€ํ„ฐ ์ง€์›๋œ ์ƒ๊ฐ๋ณด๋‹ค ์˜ค๋ž˜๋œ ๊ธฐ๋Šฅ์ด๋ฉฐ,
์ž๋ฐ” 7๋ถ€ํ„ฐ๋Š” NIO2๊ฐ€ ์ง€์›๋˜์—ˆ๋‹ค.

๋‹ค์Œ์€ NIO์™€ ์ด์ „ IO ๋ฐฉ์‹์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋น„๊ต์ด๋‹ค.
์ด์ „ IO๋Š” BIO๋ผ๊ณ  ์นญํ•œ๋‹ค.

BIO

๊ธฐ์กด ์ž๋ฐ” I/O๋Š” ๊ฐ€์ƒ๋จธ์‹ ์˜ ํ•œ๊ณ„๋กœ OS์˜ ์ปค๋„ ๋ฒ„ํผ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ํ•ธ๋“ค๋ง ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ์†Œ์ผ“์ด๋‚˜ ํŒŒ์ผ์—์„œ Stream์ด ๋“ค์–ด์˜ค๋ฉด ์ปค๋„ ๋ฒ„ํผ์— ๋ฐ์ดํ„ฐ๋ฅผ ์จ์•ผํ•˜๋Š”๋ฐ
๋‹น์‹œ์—๋Š” ์ด๋ฅผ ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ ๋Œ€์•ˆ์œผ๋กœ BIO์˜ ๊ฒฝ์šฐ, JVM์ด ์ปค๋„์—๊ฒŒ ์‹œ์Šคํ…œ ์ฝœ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ด ๊ณผ์ •์—์„œ JVM์€

JVM -> ์ปค๋„-> ์‹œ์Šคํ…œ ์ฝœ -> ๋””์Šคํฌ ์ปจํŠธ๋กค๋Ÿฌ -> DMA๊ฐ€ ์ปค๋„๋ฒ„ํผ๋กœ ๋ณต์‚ฌ -> JVM ๋ฒ„ํผ์— ๋ณต์‚ฌ

์˜ ๊ธด ๊ณผ์ •์„ ๊ฑฐ์น˜๊ฒŒ ๋œ๋‹ค.

์ด๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋กœ๋Š”

  1. JVM์œผ๋กœ ๋‚ด๋ถ€ ๋ฒ„ํผ ๋ณต์‚ฌ์‹œ CPU๊ฐ€ ๊ด€์—ฌ -> CPU ์˜ค๋ฒ„ํ—ค๋“œ

  2. ๋ณต์‚ฌ๋œ Buffer๋Š” ํ™œ์šฉ ํ›„ GC ๋Œ€์ƒ์ด๋จ. -> Stop-the-World๋กœ ์ธํ•œ ์„ฑ๋Šฅ ์ €ํ•˜

  3. ๋ณต์‚ฌ์ค‘์ธ I/O ์š”์ฒญ ์Šค๋ ˆ๋“œ๋Š” ๋ธ”๋กœํ‚น ์ƒํƒœ -> ์ฒ˜๋ฆฌ์†๋„ ์ €ํ•˜

๊ฐ€ ์žˆ๋‹ค.

ํŠนํžˆ 3๋ฒˆ์งธ์˜ ๋ธ”๋กœํ‚น ์ด์Šˆ๊ฐ€ ์ฃผ์š” ๋ฌธ์ œ์˜€๋‹ค.
Stream์€ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ์ฝ๊ธฐ ๋•Œ๋ฌธ์— ์ฝ์„ ๋•Œ์™€ ์“ธ ๋•Œ InputStream๊ณผ OutputStream์œผ๋กœ
๊ตฌ๋ถ„ํ•˜์—ฌ ์‚ฌ์šฉํ•˜์˜€๊ณ , ์ฝ๊ณ  ์“ฐ๋Š” ์ž‘์—…์ด ๋‹ค ๋๋‚ ๋•Œ ๊นŒ์ง€๋Š” ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

๋˜ํ•œ ์ž๋ฐ”๋Š” C์™€ C++ ์Šค๋ ˆ๋“œ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ ํ•œ๋‹จ๊ณ„์˜ ์ถ”์ƒํ™” ๋ ˆ์ด์–ด๊ฐ€ ๋” ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—
์ด ๋‘˜๋ณด๋‹ค ์Šค๋ ˆ๋“œ ์ƒ์„ฑ์— ์‹œ๊ฐ„์ด ์˜ค๋ž˜๊ฑธ๋ ธ์œผ๋ฉฐ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„์— ์ ‘์† ํ•  ๊ฒฝ์šฐ์—๋Š” ์•ž์„œ ์ ‘์†ํ•œ
ํด๋ผ์ด์–ธํŠธ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค ๋งŒ๋“ค์–ด์งˆ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜๋ฆฌ์†๋„๊ฐ€ ์ฒ˜ํ•˜๋˜์—ˆ๋‹ค.
(๊ทธ๋ž˜์„œ ์Šค๋ ˆ๋“œ๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด pool ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ ๊ฐ™๋‹ค.)

NIO

์ž๋ฐ” 1.3 ์ดํ›„ ๋ถ€ํ„ฐ JVM์— ํ†ต์ผ๋œ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋„์ž…๋˜์–ด, ๊ฐ OS๋ณ„ ์ปค๋„ ๋ฒ„ํผ์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

IO์™€ NIO ๋ชจ๋‘ Blocking ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•˜์ง€๋งŒ, ๋ธ”๋กœํ‚น์„ ๋น ์ ธ๋‚˜์˜ค๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์—๋Š” ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.
IO๋Š” ์˜ค์ง Stream์„ ๋‹ซ๋Š” ๊ฒƒ์œผ๋กœ๋ฏผ ๋ธ”๋กœํ‚น์„ ๋น ์ ธ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, NIO๋Š” Selector๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฅผ ํ•ด๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์…€๋ ‰ํ„ฐ

java.nio.channels.Selector๋Š” ์ž๋ฐ”์ƒ์—์„œ์˜ ๋…ผ๋ธ”๋กœํ‚น I/O ๊ตฌํ˜„์˜ ํ•ต์‹ฌ์œผ๋กœ์จ, **Multiplex/IO **Select****์™€ ๊ฐ™๋‹ค.
Select๋Š” ์‹œ์Šคํ…œ ์ด๋ฒคํŠธ ํ†ต์ง€ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋กœ ๋™์‹œ์— ๋งŽ์€ IO๋ฅผ ๋‹ด๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค.

์‹œ์Šคํ…œ ์ด๋ฒคํŠธ ํ†ต์ง€ API๋ž€ Linux์˜ Select()์™€ Epoll()๊ณผ ๊ฐ™์ด ๋‹ค์ค‘ I/O๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ€ํ‹ฐํ”Œ๋ ‰์‹ฑ ๋ฐฉ์‹์˜ API๋ฅผ ๋งํ•œ๋‹ค

netty์˜ ๊ฒฝ์šฐ, ๋ฆฌ๋ˆ…์Šค ์œ„์—์„œ ์ž‘๋™ํ•  ๊ฒฝ์šฐ, ์ž๋™์ ์œผ๋กœ Select๊ฐ€ ์•„๋‹Œ Epoll์„ ์‚ฌ์šฉํ•œ๋‹ค.

Select์™€ Epoll ๋ชจ๋‘ ์‹œ์Šคํ…œ ์ฝœ์ด๋‹ค.

๊ฐ„๋‹จํ•œ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•˜์ž๋ฉด, ์†Œ์ผ“์„ ์—ด๋ฉด ํŒŒ์ผ ๋””์Šคํฌ๋Ÿฝํ„ฐ๋ผ๋Š” unsigned int ํ˜•์‹์˜ ์†Œ์ผ“ ID๋ฅผ ๋ถ€์—ฌ ํ•œ๋‹ค.

Select์˜ ๊ฒฝ์šฐ ๋ฃจํ”„๋ฅผ ๋Œ๋ฉด์„œ ํŒŒ์ผ ๋””์Šคํฌ๋Ÿฝํ„ฐ๋“ค์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์‹œํ•˜๋Š” ๋ฐ˜๋ฉด,

epoll์€ ์ฝœ๋ฐฑํ˜•์‹์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค. ์ฆ‰, epoll์ด ๋” ๋น ๋ฅด๋‹ค.

๋„คํ‹ฐ ์†Œ๊ฐœ

ํ•˜์ง€๋งŒ ์œ„์™€ ๊ฐ™์ด NIO๋ฅผ ํ†ตํ•ด Low Level API๋ฅผ ์ง์ ‘ ์ด์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์ด ์‹ฌํ™”๋œ๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.
๋˜ํ•œ ๊ทธ๊ฑธ ๋‹ค๋ฃฐ ๊ณ ๊ธ‰ ๊ฐœ๋ฐœ์ž๋“ค์—๊ฒŒ๋งŒ ์˜์กดํ•˜๊ฒŒ ๋  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ๊ทธ๋ž˜์„œ Netty๊ฐ€ ๋“ฑ์žฅํ•˜์˜€๋‹ค.

๋„คํ‹ฐ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ

๋„คํ‹ฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด 4๊ฐœ์˜ ์ฃผ์š” ์š”์†Œ๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋‹ค.

  • Channel

    • ์ฑ„๋„์€ ์ž๋ฐ” NIO์— ๊ธฐ๋ณธ ๊ตฌ์กฐ์ธ ๊ทธ Channel์ด๋‹ค. ๋„คํ‹ฐ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ์šด์†ก ์ˆ˜๋‹จ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ณ , ๋„คํ‹ฐ๊ฐ€ ์ž๋™์œผ๋กœ Channel์„ ์—ด๊ฑฐ๋‚˜ ๋‹ซ์•„์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๊ตฌํ˜„ํ•  ํ•„์š”๋Š” ์—†๋‹ค.
  • CallBack

    • ์ฝœ๋ฐฑ ๋˜ํ•œ ๊ธฐ์กด์— ์šฐ๋ฆฌ๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜์™€ ๋˜‘๊ฐ™๋‹ค. ๋„คํ‹ฐ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฝœ๋ฐฑ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š”๋ฐ, ์ฝœ๋ฐฑ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋‚ด๋ถ€์—์„œ๋Š” ChannelHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•จ์œผ๋กœ์จ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Future

    • Future๋Š” ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด Application์— ์•Œ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์ด ๊ฐ์ฒด๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, ์ด๋ฅผ placeholder๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
    • JDK ์ž์ฒด์—์„œ ์ด์™€๊ฐ™์€ ์—ญํ• ์„ํ•˜๋Š” java.util.concurrent.Future ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, ์ˆ˜๋™์œผ๋กœ ์ž‘์—… ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ์™„๋ฃŒ ์ „๊นŒ์ง€ ๋ธ”๋กœํ‚นํ•˜๋Š” ๊ธฐ๋Šฅ๋งŒ ์žˆ์—ˆ๋‹ค.
    • ๊ทธ๋ž˜์„œ ๋„คํ‹ฐ๋Š” ์ž์ฒด์ ์œผ๋กœ ChannelFuture๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ž๋™์œผ๋กœ ์™„๋ฃŒ๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

    ChannelFuture์—๋Š” ChannelFutureListener์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜ ์ด์ƒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์ด Listener๋“ค์ด ํ˜ธ์ถœ๋˜๋ฉฐ ์ฒ˜๋ฆฌ ์„ฑ๊ณต ์œ ๋ฌด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ์ž‘์—… ์™„๋ฃŒ๋ฅผ ์ˆ˜๋™์œผ๋กœ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ๋ธ”๋กœํ‚น ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

  • ์ด ๋•๋ถ„์— Netty์˜ ๋ชจ๋“  OutBound ์ž‘์—…์€ ChannelFuture๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ง„ํ–‰์„ ๋ธ”๋กœํ‚นํ•˜์ง€ ์•Š๋Š”๋‹ค.

  • Event ์™€ Handler

    • ๋„คํ‹ฐ๋Š” ์ž‘์—…์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ๊ณ ์œ ํ•œ ์ด๋ฒคํŠธ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ ์ ˆํ•œ ๋™์ž‘์„ ํŠธ๋ฆฌ๊ฑฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„ค๊ณ„์—์„œ ํ•œ Channel์˜ ์ž…์ถœ๋ ฅ์ด ๋™์ผํ•œ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋™๊ธฐํ™”๊ฐ€ ํ•„์š” ์—†๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋น„๋™๊ธฐ ๋…ผ๋ธ”๋กœํ‚น ์‹œ์—๋Š” ํ•˜๋‚˜์˜ ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ์˜ Channel๊ณผ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ๋‹ค.

๋„คํ‹ฐ์˜ Thread ๊ด€๋ฆฌ

  • 1. ๋น„๋™๊ธฐ ๋น„๋™๊ธฐ ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ์—๋Š” 1 Event Loop๊ฐ€ ์—ฌ๋Ÿฌ Channel์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • 2. ๋™๊ธฐ ๋™๊ธฐ ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ์—๋Š” 1 Event Loop๊ฐ€ 1 Channel์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๊ธฐํƒ€ ํŠน์ง•

  • ์ œ๋กœ ์นดํ”ผ

  • ํ˜„์žฌ NIO์™€ Epoll ์ „์†ก์—์„œ๋งŒ ์ด์šฉ๊ฐ€๋Šฅํ•œ ๊ธฐ๋Šฅ์œผ๋กœ์จ, ํŒŒ์ผ ์‹œ์Šค์…ˆ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ปค๋„ ๊ณต๊ฐ„์—์„œ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์œผ๋กœ ๋ณต์‚ฌํ•˜๋Š” ๊ณผ์ •์„ ์ƒ๋žตํ•œ๋‹ค.

    ์ด ๊ธฐ๋Šฅ ๋•๋ถ„์— ์œ„์˜ BIO์—์„œ ์„ค๋ช…ํ• ๋•Œ ์ฒ˜๋Ÿผ ๋ฒ„ํผ๋ฅผ ๋ณต์‚ฌํ•ด์„œ GC ๋Œ€์ƒ์ด ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค. ๋•๋ถ„์— ๋ฆฌ๋ˆ…์Šค ์ƒ์—์„œ ๊ณผ๋ถ€ํ•˜ ์กฐ๊ฑด์‹œ์— ์„ฑ๋Šฅ์ƒ์˜ ์ด์ ์„ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜๋„ ์žˆ๋‹ค,

๊ณผ๊ฑฐ์— ์šฐ์—ฐํžˆ ์จ๋†“์€ ๊ธ€์„ ๋ฐœ๊ฒฌํ•˜์—ฌ ์ด๊ณณ์œผ๋กœ ๋‹ค์‹œ ์˜ฎ๊ฒจ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

ํ‹€๋ฆฐ ๋ถ€๋ถ„์€ ์ง€์ ํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

Reference

wikibook.co.kr/netty-in-action/

[๋„คํ‹ฐ ์ธ ์•ก์…˜: Netty๋ฅผ ์ด์šฉํ•œ ์ž๋ฐ” ๊ธฐ๋ฐ˜์˜ ๊ณ ์„ฑ๋Šฅ ์„œ๋ฒ„ & ํด๋ผ์ด์–ธํŠธ ๊ฐœ๋ฐœ

๋„คํ‹ฐ๋Š” ๋ณต์žกํ•œ ๋„คํŠธ์›Œํ‚น, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ, ๋™์‹œ์„ฑ์„ ๊ด€๋ฆฌํ•˜๋Š” ์ž๋ฐ” ๊ธฐ๋ฐ˜ ๋„คํŠธ์›Œํ‚น ํ”„๋ ˆ์ž„์›Œํฌ๋กœ์„œ, ๋ฐ˜๋ณต์ ์ธ ์ €์ˆ˜์ค€ ์ฝ”๋“œ๋ฅผ ๋‚ด๋ถ€๋กœ ๊ฐ์ถค์œผ๋กœ์จ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ณ  ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด

wikibook.co.kr](https://wikibook.co.kr/netty-in-action/)


์˜๋ฌธ์ 

1. Spring Webflux๋Š” ๊ธฐ์กด ThreadLocal์— ์ €์žฅํ•˜๋˜ ๋ฐ์ดํ„ฐ๋Š”๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด๊ด€ํ• ๊นŒ?

๊ธฐ์กด์˜ ์ „ํ†ต์ ์ธ Thread Pool ๋ฐฉ์‹์€ 1 ์š”์ฒญ == 1 Thread ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์—
์ธ์ฆ๊ณผ ๊ฐ™์€ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋“ค์„ ThreadLocal์— ํƒœ์›Œ์„œ ๋ณด๋ƒˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฒคํŠธ ๋ฃจํ”„ ๊ธฐ๋ฐ˜์˜ Netty์™€ ๊ฐ™์€ ์•„ํ‚คํ…์ฒ˜์—์„œ๋Š” N๊ฐœ ์š”์ฒญ == 1 ์Šค๋ ˆ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์—

ThreadLocal์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์ฒ˜์Œ ์›นํ”Œ๋Ÿญ์Šค๋ฅผ ๋ฐฐ์šธ๋•Œ ์ด๋ถ€๋ถ„์ด ์ œ์ผ ๊ถ๊ธˆํ•˜์˜€์—ˆ๋‹ค.

๋Œ€ํ‘œ์ ์ธ ์˜ˆ์‹œ๋กœ SpringMVC - Spring Security์—์„œ๋Š” ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ SecurityContext๋กœ ์ €์žฅํ•˜๊ณ ,
์ด๋ฅผ SecurityContextHolder๋กœ ๊ฐ์‹ธ์„œ ThreadLocal์— ์ €์žฅํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

ํ•˜์ง€๋งŒ webflux๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ๊ฐ์ด ์žกํžˆ์ง€ ์•Š์•˜๋‹ค.
๊ทธ๋ž˜์„œ Spring ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์–ด์žˆ๋Š”์ง€ ๋น„๊ตํ•ด๋ณด์•˜๋‹ค.

์ฃผ์„์„ ๋ณด๋ฉด SpringMVC์—์„œ๋Š” SecurityContext๋ฅผ ์–ด๋–ป๊ฒŒ ์ €์žฅํ• ์ง€๋ฅผ

SecurityContextStrategy ๋ผ๋Š” ์ „๋žตํŒจํ„ด์œผ๋กœ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ

๋ณ„๋‹ค๋ฅธ ์„ค์ •์ด ์—†์œผ๋ฉด ThreadLocal์— ์ €์žฅํ•˜๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋™์ผํ•œ ์—ญํ• ์„ ํ•˜๋Š” ReactiveSecurityContextHolder๋ฅผ ๋ณด๋ฉด SecurityContext๊ฐ€ ์•„๋‹Œ
Reactor์— ์žˆ๋Š” Context๋ผ๋Š” ์˜์—ญ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ Reactor-Core์˜ Context [์ฝ”๋“œ]๋ฅผ ๋ณด์•˜๋”๋‹ˆ

Reatorํ™˜๊ฒฝ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”์ ์ด๋‚˜ ๋ณด์•ˆ ํ† ํฐ๋“ฑ์— ์‚ฌ์šฉํ•˜๊ธฐ ์ด์ƒ์ ์ธ Context๊ฐ€ ์กด์žฌํ•˜์˜€๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ์ฃผ์„์„ ๋ณด๋ฉด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์ ์€ ์ˆ˜์˜ key/value๋งŒ ์ €์žฅํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ๊ณ ,
ํ•œ Context๋‹น 5๊ฐœ์˜ Key/value๊ฐ€ ๋„˜์œผ๋ฉด Map์œผ๋กœ ๋ณต์‚ฌ๋˜์–ด ์žฌํ• ๋‹น ๋œ๋‹ค๊ณ  ์ ํ˜€ ์žˆ์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋” ์ฐพ์•„๋ณด์•˜๋”๋‹ˆโ€ฆ

์ด๋Ÿฐ์‹์œผ๋กœ ๋ณ€์ˆ˜ 5๊ฐœ ์ดํ•˜๋ฉด Context1, 2, 3.. ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ณ€์ˆ˜ ๊ฐœ์ˆ˜๋ฅผ

๋”ฐ๋กœ ๋งŒ๋“ค์–ด ์ €์žฅํ•˜๊ณ  5๊ฐœ๊ฐ€ ๋„˜์–ด์•ผ๋งŒ LinkedHashMap์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์™œ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์—ˆ๋Š”์ง€ ์ฐพ์•„๋ณด์•˜๋Š”๋ฐ [์™„๋ จ PR]

Copy-On-Write ์ „๋žต์„ ํ†ตํ•ด ์„ฑ๋Šฅ์ƒ์˜ ์ด๋“์„ ๋ณด๋ ค๊ณ  ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด์˜€๋‹ค.

Reactor ์—์„œ๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ฒ˜๋Ÿผ ๋ถˆ๋ณ€๊ฐ’์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ’์„ ์ถ”๊ฐ€ํ• ๋•Œ๋งˆ๋‹ค.

๊ธฐ์กด์˜ ๊ฐ’์„ ๋ณต์‚ฌํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, Context๋‚ด์— 5๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ ํ•  ๋•Œ๊นŒ์ง€๋Š”

Copy-On-Write ์ „๋žต์„ ํ†ตํ•ด ๋ณต์‚ฌํ•œ๊ฒƒ ์ฒ˜๋Ÿผ ์†์ด๊ณ , ์‹ค์ œ๋กœ ๊ฐ’์„ ๋ณต์‚ฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ฆ‰ Context ๋‚ด์—์„œ ํ•œ ์š”์ฒญ์—๋Œ€ํ•ด 5๊ฐœ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋ฉด, ์„ฑ๋Šฅ์ƒ์˜ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งˆ์ง€๋ง‰์— ์•Œ๊ฒŒ๋˜์—ˆ์ง€๋งŒ, Spring Webflux [๋„ํ๋จผํŠธ]์—๋„ ์„ค๋ช…๋˜์–ด์žˆ์—ˆ๋‹ค.

์•„๋ฌดํŠผ ๊ฒฐ๊ตญ SpringMVC : ThreadLocal == Spring Webflux : Context ์ด๋‹ค.

๋ธ”๋กœ๊ทธ๋กœ ๋Œ์•„๊ฐ€๊ธฐ