๐Ÿ“— Spring WebFlux, Reactive Stream, R2DBC, Mono, Flux ์ •๋ณตํ•˜๊ธฐ

1,689 ๋‹จ์–ดยท4 ๋ถ„ยท์›๋ฌธ(.md)

๊ฐœ์š” #

Non-Blocking ๋ฐฉ์‹์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ api๊ฐ€ ๋Œ€๊ทœ๋ชจ ์†Œํ”„ํŠธ์›จ์–ด ํ”„๋กœ๊ทธ๋žจ์—์„œ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๊ฑฐ์˜ ํ•„์ˆ˜๋‹ค ์‹ถ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ์ˆ ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ์˜ค๋Š˜ Webflux์™€ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ, ๋…ผ๋ธ”๋ผํ‚น์— ๋Œ€ํ•ด์„œ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ ํ•œ๋‹ค.

Non-Blocking #

Non-Blocking์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ์ „์— ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์ด๋‹ค.

Non-Blocking ํŠน์ง•

  • ์ž…์ถœ๋ ฅ ์ž‘์—…์ด๋‚˜ ๊ธด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ CPU๊ฐ€ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ• ๋‹นํ•ด ์ž์›์„ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ์™€ ๋‹ฌ๋ฆฌ ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์•„ CPU ๋ถ€ํ•˜์™€ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Spring WebFlux #

Spring WebFlux๋Š” Spring5์—์„œ ์ถ”๊ฐ€๋œ Reactive-Stack์˜ ์›น ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ„์— ๋ฆฌ์•กํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ Non-Blocking Reactive-Stream์„ ์ง€์›ํ•œ๋‹ค.

WebFlux๊ฐ€ ์ƒ๊ธด ์ด์œ ๋กœ๋Š”

  1. ์ ์€ ์–‘์˜ ์Šค๋ ˆ๋“œ์™€ ์ตœ์†Œํ•œ์˜ ํ•˜๋“œ์›จ์–ด ์ž์›์œผ๋กœ ๋™์‹œ์„ฑ์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์œ„ํ•จ

  2. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์ด ์žˆ๋‹ค.

Spirng WebFlux ๋“ฑ์žฅ ๋ฐฐ๊ฒฝ #

Spring WebFlux๋Š” ๊ธฐ์กด ์Šคํ”„๋ง MVC์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ณ ์ž Reactive Programming์„ ์ ์šฉํ•œ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„ ์›Œํฌ ๋ชจ๋“ˆ ์ค‘ ํ•˜๋‚˜๋‹ค.

๊ธฐ์กด ์Šคํ”„๋ง MVC๋Š” ์„œ๋ธ”๋ฆฟ ์ŠคํŒฉ์—์„œ ์ง€์›ํ•˜๋Š” Thread-Per-Request ๋ชจ๋ธ๋กœ ๋™์ž‘ํ•œ๋‹ค. ์ด๋Š” ์š”์ฒญ ํ•˜๋‚˜๋‹น ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ํ• ๋‹น๋˜๋Š” ๋ฐฉ์‹์œผ๋กœ, ํ•˜๋‚˜์˜ ์š”์ฒญ ์ฒ˜๋ฆฌ์— ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•˜๋ฉด ํ•ด๋‹น ์š”์ฒญ์— ํ• ๋‹น๋œ ์Šค๋ ˆ๋“œ๋Š” ๊ณ„์† ๋ธ”๋กœํ‚น ์ƒํƒœ๋กœ ๋‚จ์•„์žˆ๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ธ”๋กœํ‚น I/O๋Š” CPU ์ž์›์„ ๋‚ญ๋น„ํ•˜๋Š” ์›์ธ ์ค‘ ํ•˜๋‚˜๋‹ค. ๋˜ํ•œ, ๋งŽ์€ ์ˆ˜์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋งŽ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ ์„œ๋ฒ„์—์„œ ์Šค๋ ˆ๋“œ ๊ฐœ์ˆ˜๋ฅผ ๋ฏธ๋ฆฌ ๊ณ ์ •ํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ์Šค๋ ˆ๋“œ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์— ๋”ฐ๋ฅธ ๋ถ€ํ•˜ ์ฆ๊ฐ€๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ดํ•ด ๋น„ํ•ด Reactive Programming Model์€ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์˜ Non-Blocking I/O๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฉฐ, ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜์ง€ ์•Š๊ณ  ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ธ”๋กœํ‚น I/O ๋Œ€๊ธฐ ์‹œ๊ฐ„ ๋™์•ˆ์—๋„ ๋‹ค๋ฅธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ•œ์ •๋œ ๋ฆฌ์†Œ์Šค๋กœ๋„ ๋” ๋งŽ์€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค..

์ฆ‰ Spring WebFlux๋Š” ์ด๋Ÿฌํ•œ Reactive Programming Model์„ ์ง€์›ํ•˜๊ณ  ๋†’์€ ์„ฑ๋Šฅ๊ณผ ํ™•์žฅ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

๋น„๋™๊ธฐ ๋…ผ๋ธ”๋กœํ‚น ํ™˜๊ฒฝ์˜ ์„œ๋ฒ„๋กœ Netty๊ฐ€ ๋ถ€์ƒํ•˜๊ณ  ์žˆ์—ˆ์œผ๋ฉฐ ์ด Netty์™€์˜ ์—ฐ๋™์„ ์œ„ํ•ด Spring์€ ์ƒˆ๋กœ์šด API๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค.

์Šคํ”„๋ง ์›นํ”Œ๋Ÿญ์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์ถ”์ฒœ๋œ๋‹ค.

  • ๋น„๋™๊ธฐ, non-blocking reactive ๊ฐœ๋ฐœ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ
  • ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ์‚ฌ์šฉ
  • ์„œ๋น„์Šค๊ฐ„ ํ˜ธ์ถœ์ด ๋งŽ์€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜์— ์ ํ•ฉ

Spring WebFlux :

-> many request : 1 thread, async + Non-Blocking

Spring MVC : 1 request :

-> 1 thread, sync + Blocking

Reactive Stream #

Reactive Stream์€ ๋น„๋™๊ธฐ์ , Non-Blocking, backpressure ๊ธฐ๋ฐ˜์˜ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ํ‘œ์ค€ ์ŠคํŽ™์ด๋‹ค. ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๋•Œ, ๋‹ค๋ฅธ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ์—†์–ด์ง€๊ณ , ์ž‘์—…์ด ์ฒ˜๋ฆฌ๋˜๋ฉด ์ฆ‰์‹œ ๋‹ค์Œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ๋” ํšจ์œจ์ ์œผ๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Reactive Stream์€ Publisher-Subscriber ํŒจํ„ด์„ ์‚ฌ์šฉํ•ด, Publisher๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  Subscriber๋Š” ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘๊ณผ ์†๋„๊ฐ€ Subscriber๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ๋Šฅ๋ ฅ์„ ์ดˆ๊ณผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, backpressure๋ฅผ ํ†ตํ•ด Publisher๊ฐ€ ๋ฐ์ดํ„ฐ ์ƒ์‚ฐ์„ ์ œํ•œํ•˜์—ฌ Subscriber๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์†๋„์— ๋งž์ถฐ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

R2DBC #

R2DBC (Reactive Relational Deatabase Connectivity)๋Š” ์ ์€ ์ˆ˜์˜ ์Šค๋ ˆ๋“œ๋กœ ๋™์‹œ์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋” ์ ์€ ํ•˜๋“œ์›จ์–ด ๋ฆฌ์†Œ์Šค๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” Non-Blocking ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์Šคํƒ์ด๋‹ค.

๊ถํ•ฉ์œผ๋กœ๋Š”

  • spirng mvc : jpa
  • spring webflux: r2dbc

์ด๋ ‡๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Reactive Model์ด๊ธฐ ๋•Œ๋ฌธ์— findAll()๊ณผ ๊ฐ™์€ ์—ฐ์‚ฐ์„ ํ–ˆ์„๋•Œ List๊ฐ€ ์•„๋‹Œ Flux๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ  ๋Œ€์‹ ์—๋Š” Mono๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

Mono & Flux #

Spring Webflux์—์„œ ์‚ฌ์šฉํ•˜๋Š” reactive library๋Š” Reactor์ด๊ณ  Reactor๊ฐ€ Reactive Streams์˜ ๊ตฌํ˜„์ฒด๋‹ค. ๊ทธ๋ž˜์„œ Webflux ๋ฌธ์„œ์— Reactive Streams๊ฐ€ ์–ธ๊ธ‰๋˜๋Š” ๊ฒƒ์ด๊ณ  ๊ทธ๊ฒƒ๊ณผ ๊ฐ™์ด Reactor๊ฐ€ ๋‚˜์˜จ๋‹ค.

์ฃผ์š” ๊ฐ์ฒด์ธ Mono / Flux๋Š” ๊ฒฐ๊ตญ ์›น ํ”Œ๋Ÿญ์Šค์— ๋™์ž‘ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š”๋ฐ ๊ผญ ์•Œ๊ณ  ๋„˜์–ด๊ฐ€์•ผํ•œ๋‹ค.

  • Mono : 0 ~ 1๊ฐœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ
  • Flux : 0 ~ N๊ฐœ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ

Mono์™€ Flux๋Š” Reactive Streams์˜ Publisher ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌํ˜„์ฒด์ด๋‹ค.

Mono #

Flux #

๋งˆ๋ฌด๋ฆฌ ์ด์ด #

์ด๋ ‡๊ฒŒ WebFlux์— ๋Œ€ํ•ด์„œ, ๊ด€๋ จ ์šฉ์–ด์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€๋ฅผ ํ•ด๋ณด์•˜๋‹ค ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์ง€ํ–ฅํ•˜๊ธฐ ์œ„ํ•œ ๋‚˜์˜ ๊ณต๋ถ€๋Š” ๋Š์ž„์—†์ด..!

Back-End/spring/webflux_reactive.md