๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring

Spring Webflux

Spring Webflux

  • Spring5์—์„œ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๋ชจ๋“ˆ
  • ๋น„๋™๊ธฐ์ ์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์ง€์›
  • Reactor ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง€์›
  • ์ ์€ ์Šค๋ ˆ๋“œ๋กœ ๋งŽ์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ
  • HTTP ํด๋ผ์ด์–ธํŠธ๋„ ์ œ๊ณต
  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง€์›
  • Java์™€ Kotlin ๋ชจ๋‘์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  • Spring Boot์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ• ๊ฐ€๋Šฅ

webmvc

  • Spring MVC๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ blocking์ด๊ณ  ๋™๊ธฐ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค Thread๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ๋ณดํ†ต์€ ์š”์ฒญ ์‹œ๋งˆ๋‹ค ์Šค๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑ, ์‚ญ์ œํ•ด ์ฃผ๋ฉด ์ผ์ •ํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ง€์†์ ์œผ๋กœ ์†Œ๋ชจ๋˜๋ฏ€๋กœ Thread๋ฅผ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด ์ €์žฅํ•ด ๋‘๋Š” Thread Pool ์„  ์ƒ์„ฑํ•ด ์‚ฌ์šฉํ•œ๋‹ค.
  • spring mvc ๊ฐ™์€ ๊ฒฝ์šฐ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด  Queue์— ์Œ“๊ณ  ์ˆœ์„œ์— ๋”ฐ๋ผ์„œ Thread๋ฅผ ํ•˜๋‚˜ ์ ์œ ํ•ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ์š”์ฒญ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๊ณ„์†ํ•ด์„œ ์š”์ฒญ์ด ํ์— ๋Œ€๊ธฐํ•˜๊ฒŒ ๋˜๋Š” Thread Pool Hell ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

webflux

  • webflux๋Š” ์ด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด Event-Driven ๋ฐฉ์‹์ด๊ณ  ๋น„๋™๊ธฐ non-blocking ๋ฐฉ์‹์ด๋‹ค.
  • webflux๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๊ฐ€ ๋Œ์•„์„œ ์š”์ฒญ์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๊ทธ๊ฒƒ์— ๋งž๋Š” ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•˜๊ณ  ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด callback ๋ฉ”์„œ๋“œ ๋“ฑ์„ ํ†ตํ•ด ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ์ด ๋ฐฉ์‹์˜ ๊ฒฝ์šฐ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Spring MVC์— ๋น„ํ•ด ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ๋Œ€๋Ÿ‰์œผ๋กœ ๋ฐ›์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

WebFlux๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 

  • ๋น„๋™๊ธฐ non-blocking ๋ฐฉ์‹์˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ๊ฐœ๋ฐœ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ด ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•ด์„œ, cpu, thread, memory์— ์ž์›์„ ๋‚ญ๋น„ํ•˜์ง€์•Š๊ณ  ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฑธ ๋ชฉ์ ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
  • ์„œ๋น„์Šค๊ฐ„ ํ˜ธ์ถœ์ด ๋งŽ์€ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์— ์ ํ•ฉํ•˜๋‹ค
"์ ์€ ์–‘์˜ ์Šค๋ ˆ๋“œ" ์™€ "์ตœ์†Œํ•œ์˜ ํ•˜๋“œ์›จ์–ด ์ž์›" ์œผ๋กœ ๋™์‹œ์„ฑ์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์œ„ํ•ด Webflux๊ฐ€ ํƒ„์ƒํ•˜์˜€๋‹ค. 
ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด webflux์˜ ๊ธฐ๋ฐ˜์ด ๋˜์—ˆ๋‹ค

 

WebFlux ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ์˜ ํŠน์ง•

  1. ๋ชจ๋“  ์›น ์š”์ฒญ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ๋ช…์‹œ์ ์ธ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜์–ด์žˆ๋‹ค.
    • ๊ธฐ์กด์˜ Spring MVC๋Š” ์–ด๋…ธํ…Œ์ด์…˜์— ์˜ํ•œ ํ๋ฆ„ ๊ด€๋ก€๋ฅผ ์‚ฌ์‹ค์ƒ ์™ธ์›Œ์•ผ ์ฝ”๋“œ์˜ ํ•ด์„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • (์–ด๋…ธํ…Œ์ด์…˜์˜ ๋ช…์‹œ์ ์ธ ๋ถ„์„์ด ํž˜๋“ค๋‹ค.)
    • ํ•จ์ˆ˜ํ˜• ํƒ€์ž…์˜ WebFlux๋Š” ๋ช…์‹œ์ ์ธ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”์†Œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๊ด€๋ก€์™€ ํƒ€์ž…์ฒดํฌ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•œ ์–ด๋…ธํ…Œ์ด์…˜์— ์˜์กดํ•˜๋Š” MVC ์Šคํƒ€์ผ๋ณด๋‹ค๋Š” ๋ช…ํ™•ํ•˜๋‹ค.
    • ์ •ํ™•ํ•œ ํƒ€์ž… ์ฒดํฌ ๊ฐ€๋Šฅ
  2. ํ•จ์ˆ˜ ์กฐํ•ฉ์„ ํ†ตํ•œ ํŽธ๋ฆฌํ•œ ๊ตฌ์„ฑ, ์ถ”์ƒํ™”์— ์œ ๋ฆฌํ•˜๋‹ค.
    • ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ƒํ™”์™€ ๋ชจ๋“ˆํ™”์— ์œ ๋ฆฌํ•˜๋‹ค.
    • MVC ๋ณด๋‹ค ํ™•์žฅ์— ์œ ๋ฆฌํ•˜๋‹ค.
  3. ํ…Œ์ŠคํŠธ ์ž‘์„ฑ์ด ํŽธ๋ฆฌํ•˜๋‹ค.
    • Spring MVC ๋Š” Controller ๋‚˜ Service ๋‹จ์œ„๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” ์‚ฌ์‹ค์ƒ WebTest ๋ฅผ ์ง„ํ–‰ํ•ด์•ผํ•˜์ง€๋งŒ
    • WebFlux๋Š” ํ•ธ๋“ค๋Ÿฌ ๋กœ์ง๊ณผ ์š”์ฒญ ๋งคํ•‘, ๋ฆฌํ„ด ๊ฐ’ ์ฒ˜๋ฆฌ๊นŒ์ง€ ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋กœ ์ž‘์„ฑ ๊ฐ€๋Šฅ

 

Reactor Library

  • Java 8+์—์„œ ์ž‘๋™ํ•˜๋Š” Reactor ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„๋˜๋Š” Reactive Programming ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • Reactor๋Š” Spring Framework 5์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ฐ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.
  • Spring WebFlux์™€ ๊ฐ™์€ Spring ํ”„๋กœ์ ํŠธ์—์„œ Reactive Programming์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
  • Reactor๋Š” Reactor Core, Reactor Addons ๋ฐ Reactor Netty๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

 

Reactor Core

  • Reactor์˜ ํ•ต์‹ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • Flux์™€ Mono์™€ ๊ฐ™์€ Reactive Stream ๊ธฐ๋ฐ˜ ํƒ€์ž…
  • Flux์™€ Mono์— ๋Œ€ํ•œ ๋ณ€ํ™˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ฐ์‚ฐ์ž
  • Hot Sequence๋ฅผ ์ƒ์„ฑํ•˜๋Š” Hot Stream์— ๋Œ€ํ•œ ๋„๊ตฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค.

Reactor Addons

  • Reactor Core์— ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • Retry ๋ฐ Circuit Breaker์™€ ๊ฐ™์€ ๋” ๋‚˜์€ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ, ๋กœ๊น… ๋ฐ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

Reactor Netty

  • Reactor Netty๋Š” Netty์˜ ์ผ๋ถ€๋ถ„์œผ๋กœ Reactor์—์„œ ์‚ฌ์šฉํ•˜๋Š” Reactor Netty HTTP ๋ฐ TCP ์„œ๋ฒ„๋ฅผ ์ง€์›ํ•œ๋‹ค.

 

Mono,  Flux

๋ฆฌ์•กํ„ฐ๋Š” ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ Mono ์™€ Flux 2๊ฐ€์ง€ ๋ฐ์ดํ„ฐ ํƒ€์ž…์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ์ •์˜ํ•œ๋‹ค.
spring WebFlux๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์ ์ธ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์˜ ์ฒ˜๋ฆฌ๋ฅผ ๋ฆฌ์•กํ„ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฐ์ดํ„ฐ ํƒ€์ž…์ธ Mono ์™€ Flux๋กœ ๋‹ค๋ค„์•ผ ํ•œ๋‹ค
"๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— WebFlux์—์„œ๋Š” ๋ชจ๋“  ์‘๋‹ต์„ Mono ํ˜น์€ Flux์— ๋‹ด์•„์„œ ๋ฐ˜ํ™˜ํ•ด ์ฃผ์–ด์•ผ ํ•œ๋‹ค."

 

Mono ์™€ Flux ์˜ ์ฐจ์ด์ 

  • Mono๋Š” 0-1๊ฐœ์˜ ๊ฒฐ๊ณผ๋งŒ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
  • Flux๋Š” 0-N๊ฐœ์ธ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด

Reactor๋ฅผ ์‚ฌ์šฉํ•ด ์ผ๋ จ์˜ ์ŠคํŠธ๋ฆผ์„ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•˜๋‹ค ๋ณด๋ฉด ๋ณดํ†ต ์—ฌ๋Ÿฌ ์ŠคํŠธ๋ฆผ์„ ํ•˜๋‚˜์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์•„์ค„ ๋•Œ Mono๋ฅผ ์“ฐ๊ณ , ๊ฐ๊ฐ์˜ Mono๋ฅผ ํ•ฉ์ณ์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜๋Š” Flux๋กœ ํ‘œํ˜„ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

Mono <>

  • Mono ๋Š” 0 ๋˜๋Š” ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ๊ณผ ์—๋Ÿฌ๋ฅผ ๊ฐ€์ง„๋‹ค.

Flux <>

  • Flux ๋Š” 0 ๋˜๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ ๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ๊ณผ ์—๋Ÿฌ๋ฅผ ๊ฐ€์ง„๋‹ค.

 

Netty

  • ํ”„๋กœํ† ์ฝœ ์„œ๋ฒ„ ๋ฐ ํด๋ผ์ด์–ธํŠธ์™€ ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋น ๋ฅด๊ณ  ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š”
  • NIO (Non-Blocking Input / output) ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„ ํ”„๋ ˆ์ž„ ์›Œํฌ
  • TCP ๋ฐ UDP ์†Œ์ผ“ ์„œ๋ฒ„์™€ ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํฌ๊ฒŒ ๋‹จ์ˆœํ™”ํ•˜๊ณ  ๊ฐ„์†Œํ™”ํ•œ๋‹ค.

Netty ์˜ ์žฅ์ 

  • NIO ๋„คํŠธ์›Œํฌ ๊ธฐ๋ฐ˜ Netty ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๋น„๋™๊ธฐ์‹ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋„คํŠธ์›Œํ‚น (Event Driven) ์„ ์ง€์›ํ•œ๋‹ค.
  • Tomcat์„œ๋ฒ„๊ฐ€ 10,000๊ฑด์˜ ์ปค๋„ฅ์…˜์„ ์ฒ˜๋ฆฌํ•œ๋‹ค๋ฉด, netty๋Š” NIO ๋ฐฉ์‹์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž์›์ด ์Šค๋ ˆ๋“œ๋ฅผ ๊ณ„์† ์ ์œ ํ•˜๋ฉฐ Block ์ƒํƒœ๋ฅผ ์œ ์ง€ ํ•˜์ง€ ์•Š๋Š”๋‹ค. => 10๋ฐฐ~100๋ฐฐ์˜ ์ปค๋„ฅ์…˜์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋„คํ‹ฐ์˜ ๊ฒฝ์šฐ์—๋Š” ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋Š” ๋จธ์‹  Core ๊ฐœ์ˆ˜์˜ 2๋ฐฐ์ด๋‹ค.

 

Netty ์˜ ๊ตฌ์กฐ : ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ

Channel

  • ํ•˜๋‚˜ ์ด์ƒ์˜ ์ž…์ถœ๋ ฅ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋“œ์›จ์–ด ์žฅ์น˜, ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ ์†Œ์ผ“์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ ์ปดํฌ๋„ŒํŠธ์™€ ๊ฐ™์€ Open๋œ Connection

CallBack

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

Future

  • ์ž‘์—…์ด ์™„๋ฃŒ๊ฐ€ ๋  ๊ฒฝ์šฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์•Œ๋ฆฐ๋‹ค.
  • Future ๊ฐ์ฒด๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ๋‹ด๋Š” Plachloder์˜ ์—ญํ• ์„ ํ•œ๋‹ค.
  • ์ด๋•Œ ChannelFuture ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด ๊ฒฐ๊ณผ๊ฐ’์„ ํ™œ์šฉํ•œ๋‹ค.

Event์™€ Handler

  • Netty๋Š” ์ž‘์—… ์ƒํƒœ์˜ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•˜๊ณ , ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ Handler๋ฅผ ํ†ตํ•ด ํŠธ๋ฆฌ๊ฑฐํ•œ๋‹ค.

Event Loop

  • ์œ ์ €๊ฐ€ ์ž…์ถœ๋ ฅ์„ ์š”๊ตฌํ•  ๊ฒฝ์šฐ์˜ ํ๋ฆ„

PipeLine

  • ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„ ํ•ธ๋“ค๋Ÿฌ์— ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

Reactor๋Š” Reactor Core์˜ Flux์™€ Mono์™€ ๊ฐ™์€ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ ๋ฐ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์—์„œ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•œ๋‹ค. Reactive Programming์€ ๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„์ด๋ฉฐ
๋น„๋™๊ธฐ์„ฑ, ์ผ๊ด€์„ฑ, ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์ฒ˜๋ฆฌ, ๋น„๋™๊ธฐ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋ฐ ๋†’์€ ๊ฐ€์šฉ์„ฑ๊ณผ ๊ฐ™์€ ์ด์ ์„ ์ œ๊ณตํ•œ๋‹ค.

 

Spring R2DBC

(Reactive Relational DataBase Connectivity)

Reactive Programming์„ ํ•˜๋Š” ๊ณผ์ •์—์„œ Database ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•œ๋‹ค.

๋งŽ์€ ์˜ˆ์ œ๋กœ Project Reactor ๊ธฐ๋ฐ˜์˜ Spring Webflux๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ Database๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•  ๋•Œ R2DBC๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

 

"Spring์—์„œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†๋‚˜?"

 "์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์ง„ ์•Š๋‹ค."

 

JPA๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„๋™๊ธฐ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ฆ‰, Webflux ๊ธฐ๋ฐ˜์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Database ๋ถ€๋ถ„์—์„œ block๋˜๊ณ , ๊ทธ๋™์•ˆ thread๊ฐ€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋œ๋‹ค.

Webflux ๊ฐ™์€ ์ ์€ ์–‘์˜ thread๋ฅผ ๊ณ„์†ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” framework์—์„œ ์ด๋Ÿฌํ•œ ์ž‘์—…์€ ๋น„ํšจ์œจ์ ์ด๋ฉฐ ์ „์ฒด ์‹œ์Šคํ…œ์— ์˜ํ–ฅ์ด ๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ๊ฒƒ์ด R2DBC์ด๋‹ค.

 

R2DBC๋Š” Reactive programming ๊ธฐ๋ฐ˜์ด๋‹ค๋ณด๋‹ˆ Reactive programming์ด ๊ฐ€์ง€๋Š” ์žฅ์ ์„ ๊ทธ๋Œ€๋กœ ๊ฐ–๋Š”๋‹ค.

์ฆ‰, Blocking programming์ผ ๋•Œ๋ณด๋‹ค ๋†’์€ ๋™์‹œ์„ฑ(High Concurrency)์ด ์š”๊ตฌ๋˜๋Š” ์ƒํ™ฉ์—์„œ ๋” ์ข‹์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 

Spring: Blocking vs non-blocking: R2DBC vs JDBC and WebFlux vs Web MVC

Spring WebFlux and R2DBC perform better at higher concurrency than Spring Web MVC and JDBC

medium.com

๋™์‹œ์„ฑ(Concurrency)์ด ๋†’์•„์ง์— ๋”ฐ๋ผ MVC-JDBC๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค Latency๋Š” ๋” ์ค„์—ˆ๊ณ , Throughput์€ ๋” ์ฆ๊ฐ€ํ•œ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ ์•„์ง!

  • ๊ธฐ์ˆ ์ธก๋ฉด์—์„œ ์ˆ™๋ จ๋„๊ฐ€ ๋†’์ง€ ์•Š๋‹ค. Blocking ๋ฐฉ์‹์— ๋น„ํ•ด ์‚ฌ์šฉ์ž๋„ ๋งŽ์ง€ ์•Š๊ณ , ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋ถ€์žฌ, ๋…ธํ•˜์šฐ ๋ฐ ์ž๋ฃŒ์˜ ์ ์Œ, ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ธฐ ์–ด๋ ค์›€ ๋“ฑ ์ด์Šˆ๊ฐ€ ์žˆ๋‹ค.
  • ๊ตฌํ˜„์ฒด ์ธก๋ฉด์—์„œ๋„ ์•„์ง ์ œ๊ณต๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฒค๋”๊ฐ€ ์žˆ๋‹ค. ๋˜ํ•œ, ๊ณต์‹์ ์œผ๋กœ ๋ฒค๋”์‚ฌ์—์„œ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ์— ์ถ”ํ›„ ๊ด€๋ฆฌ ์ธก๋ฉด์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋„์ž…ํ•˜๋Š”๋ฐ ๊ณ ๋ คํ•ด๋ด์•ผํ•  ์ ์ด ๋งŽ๋‹ค.
  • Spring ์ง„์˜์—์„œ๋Š” R2DBC๋ฅผ ์œ„ํ•œ Spring Data R2DBC ๋ฅผ ์ง€์›ํ•˜์ง€๋งŒ ์•„์ง ๋ถ€์กฑํ•œ ์ ์ด ๋งŽ๋‹ค.

 

API ์˜ˆ์ œ

Controller

@Controller
public class UserController {

    private final UserService userService;

    @GetMapping("/users")
    public Flux<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @PostMapping("/users")
    public Mono<User> createUser(@RequestBody User user) {
        return userService.createUser(user);
    }

    @PutMapping("/users/{id}")
    public Mono<ResponseEntity<User>> updateUser(@PathVariable("id") String id, @RequestBody User user) {
        return userService.updateUser(id, user)
                .map(updatedUser -> ResponseEntity.ok().body(updatedUser))
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    @DeleteMapping("/users/{id}")
    public Mono<ResponseEntity<Void>> deleteUser(@PathVariable("id") String id) {
        return userService.deleteUser(id)
                .map(user -> ResponseEntity.ok().<Void>build())
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }
}

 

Service

public interface UserService {
    Mono<User> getUserById(String id);
    Flux<User> getAllUsers();
    Mono<User> createUser(User user);
    Mono<User> updateUser(String id, User user);
    Mono<Void> deleteUser(String id);
}

 

@Service
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    @Override
    public Flux<User> getAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public Mono<User> createUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public Mono<User> updateUser(String id, User user) {
        return userRepository.findById(id)
                .flatMap(existingUser -> {
                    existingUser.setName(user.getName());
                    existingUser.setEmail(user.getEmail());
                    return userRepository.save(existingUser);
                });
    }

    @Override
    public Mono<Void> deleteUser(String id) {
        return userRepository.deleteById(id);
    }
}

 

'Spring' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Spring WebClient  (0) 2023.04.30
Spring ๋ฉด์ ‘ ๋Œ€๋น„ ์ •๋ฆฌ  (0) 2023.02.01