Spring MVC vs WebFlux

๋™๊ธฐ, ๋น„๋™๊ธฐ, ๋ธ”๋กœํ‚น, ๋…ผ๋ธ”๋กœํ‚น

๋จผ์ € Spring MVC์™€ WebFlux์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด์„œ ๋ณด๊ธฐ์ „์— ๋™๊ธฐ/๋น„๋™๊ธฐ, ๋ธ”๋กœํ‚น/๋…ผ๋ธ”๋กœํ‚น์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

๋™๊ธฐ(Synchronous)

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

๋™๊ธฐ๋ž€ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ๊ณณ์—์„œ ์‘๋‹ต์„ ๋ฐ›๋Š” ๊ฒƒ

์ด ๋ง์€ ํ˜ธ์ถœ๊ณผ ์‘๋‹ต์ด ๋™์‹œ์— ์ด๋ฃจ์–ด ์ง€๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ํ˜ธ์ถœ๊ณผ ์‘๋‹ต์ด ๋™์‹œ์— ์ด๋ฃจ์–ด ์ง„๋‹ค๋Š” ๊ฒƒ ์ž์ฒด๊ฐ€ ์›ƒ๊ธด์–˜๊ธฐ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ๋ƒฅ ํ•œ๋งˆ๋””๋กœ ๋น„๋™๊ธฐ์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ ์ฒ˜๋ฆฌ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๋Š” ์‹œ์ ์— ๋Œ€ํ•œ ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

๋น„๋™๊ธฐ(Asynchronous)

๋น„๋™๊ธฐ๋Š” ๋™๊ธฐ์™€ ๋‹ค๋ฅด๊ฒŒ ํŠน์ • ํ˜ธ์ถœ์‹œ์ ๊ณผ ์ฒ˜๋ฆฌ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์‘๋‹ต์‹œ์ ์ด ๊ฐ™์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋ฐ›๊ณ  ์ฒ˜๋ฆฌ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ๊ฒƒ์€ ์ถ”ํ›„์— ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋ถˆํŠน์ • ์‹œ์ ์— ์ „๋‹ฌ ๋ฐ›๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋‹ค์‹œํ•œ๋ฒˆ ๋งํ•˜๋ฉด ๋™๊ธฐ(Synchronous)์™€ ์ฐจ์ด์ ์€ ๊ฒฐ๊ณผ์— ๋Œ€ํ•œ ์ˆœ์„œ? ์‹œ์ ? ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

Blocking

Blocking์€ ํ•จ์ˆ˜๋ฅผ call ํ–ˆ์„ ๋•Œ ์‘๋‹ต์„ ๋ฐ›๊ธฐ ์œ„ํ•ด ๋ฉˆ์ถฐ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

์˜ˆ๋ฅผ๋“ค์–ด ์šฐ๋ฆฌ๊ฐ€ fn hello()๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ hello()๋ผ๊ณ  ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•จ์ˆ˜์˜ return์ด ์žˆ๊ณ ๋‚˜์„œ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ๋‹ค์Œ์ค„์— i++; ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

Non-blocking

Non-blocking์€ ํ•จ์ˆ˜๋ฅผ call ํ–ˆ์„ ๋•Œ blocking๊ณผ ๋‹ค๋ฅด๊ฒŒ ํ•จ์ˆ˜์— ๊ฒฐ๊ณผ๊ฐ€ ์˜ค๊ธฐ ์ „์— ๋‹ค์Œ์ค„์„ ์‹คํ–‰ํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋งํ•œ๋‹ค.

์ด๊ฒƒ ๋˜ํ•œ ์˜ˆ๋ฅผ๋“ค๋ฉด hello()๋ฅผ ํ˜ธ์ถœํ–ˆ์–ด๋„ return์ด ๋˜๊ธฐ ์ „์— ๋‹ค์Œ์ค„์˜ i++; ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ๋‚˜๋งˆ ๋™๊ธฐ, ๋น„๋™๊ธฐ, ๋ธ”๋กœํ‚น, ๋…ผ๋ธ”๋กœํ‚น์— ๋Œ€ํ•ด ์„ค๋ช…ํ–ˆ๋Š”๋ฐ ์‚ฌ์‹ค ํ•„์ž๋˜ํ•œ ์ ์œผ๋ฉด์„œ ์ฝ”๋“œ๋ ˆ๋ฒจ์—์„œ ์ƒ๊ฐํ•ด๋ดค์„๋•Œ Synchronous & Blocking ์กฐํ•ฉ ๋“ฑ์ด ๊ฐ™์ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€ ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค.

์ด๋Ÿฐ ๊ฐœ๋…์„ ๋ฏธ๋ฆฌ ์„ค๋ช…ํ•œ ์ด์œ ๋Š” Spring MVC๊ฐ€ ๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  WebFlux๊ฐ€ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด์ œ ์ด ๋‘˜์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

Spring MVC

Spring MVC๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์šฐ๋ฆฌ๊ฐ€ Spring Framework์™€ Boot๋ฅผ ์“ฐ๋ฉด์„œ ๊ฐ€์žฅ ๋ณดํŽธ์ ์œผ๋กœ ์“ฐ๋Š” ๋ฐฉ์‹์ผ ๊ฒƒ์ด๋‹ค. ํ•„์ž ๋˜ํ•œ ์ด ๋ฐฉ๋ฒ•์„ ๋งŽ์ด ์จ์™”๋‹ค. Spring MVC์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ ๊ทธ ๋•Œ๋งˆ๋‹ค Thread๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์ˆ˜์˜ ์‚ฌ์šฉ์ž ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ Thread๋ฅผ ๊ณ„์† ์ƒ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ Thread๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋“ฑ์˜ ๋ฆฌ์†Œ์Šค๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์ด ๋“ค์–ด๊ฐ„๋‹ค. ๊ทธ๋ž˜์„œ Spring MVC์˜ ๊ฒฝ์šฐ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๋ฉด์„œ Thread๋ฅผ ์ƒ์„ฑํ•˜๋ฉด Pool์„ ๋งŒ๋“ค์–ด ๋†“๋Š”๋‹ค(Thread). ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ๊ทธ ์š”์ฒญ์„ Queue์— ์Œ“๊ณ  ์ด๊ฒƒ์„ Thread Pool์˜ Thread๋“ค์ด ์š”์ฒญ์„ ๊ฐ€์ ธ๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด ๋ฐฉ์‹์˜ ๋‹จ์ ์ด ์žˆ๋Š”๋ฐ ์—„์ฒญ๋‚˜๊ฒŒ ๋งŽ์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์š”์ฒญ์„ ๋ณด๋‚ผ ๊ฒฝ์šฐ Pool Size๋ฅผ ์ดˆ๊ณผํ•˜์—ฌ Queue์— ๊ณ„์† ์š”์ฒญ์ด ์Œ“์ด๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์š”์ฒญ์„ ๊ณ„์† ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋Š” Thread Pool Hell์ด๋ผ๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋”ฐ๋ผ์„œ Spring MVC์˜ ๊ฒฝ์šฐ ๊ฐœ๋ฐœํ•˜๋Š” ํ•ด๋‹น ์‹œ์Šคํ…œ์˜ ํŠธ๋ž˜ํ”ฝ์„ ์ธก์ •ํ•˜์—ฌ Pool Size๋ฅผ ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

WebFlux

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

ํ•˜์ง€๋งŒ ๋ฌด์กฐ๊ฑด WebFlux๋ฅผ ์“ด๋‹ค๊ณ  ์ข‹์„๊นŒ? ๋‚ด ์ƒ๊ฐ์€ ์•„๋‹ˆ๋ผ๊ณ  ๋งํ•˜๊ณ  ์‹ถ๋‹ค. ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํŒŒ์ดํ”„๋ผ์ธ์˜ ์š”์†Œ๋“ค์ด ๋ชจ๋‘ ๋…ผ๋ธ”๋กœํ‚นํ•˜๊ฒŒ ๋™์ž‘ํ•ด์•ผ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์–ด๋–ค ํŠน์ •ํ•œ ๊ตฌ๊ฐ„์—์„œ ๋ธ”๋กœํ‚น์ด ๋ฐœ์ƒํ•˜๋Š” ๊ตฌ๊ฐ„์ด ์žˆ๋‹ค๋ฉด ๊ฑฐ๊ธฐ์„œ๋ถ€ํ„ฐ Thread Pool Hell๊ฐ™์€ ๋ฌธ์ œ๋“ค์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๊ฐ€ ๊ฐœ๋ฐœํ•˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ง€ํ‘œ๋ฅผ ์ธก์ •ํ•ด์„œ WebFlux๋กœ ํšจ์œจ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ตฌ๊ฐ„์— ๋„๋‹ฌํ–ˆ์„ ๋•Œ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ ๋‹ค.

Boot1์ด Spring MVC๋กœ ๊ฐœ๋ฐœ๋œ ๊ฒƒ์ด๊ณ  Boot2๊ฐ€ WebFlux์ด๋‹ค. ์ด์ฒ˜๋Ÿผ ๋‘ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์ด ์ฐจ์ด๊ฐ€ ๋‚˜๋Š” ๊ตฌ๊ฐ„์ด ์žˆ๋‹ค. ์ด๋•Œ WebFlux๋ฅผ ์ ์šฉํ•ด์•ผ ํšจ์œจ์„ ๋ณผ ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ ์ƒ๊ฐํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋งŒ์•ฝ Spring MVC์—์„œ WebFlux๋กœ ์ „ํ™˜์„ ์ƒ๊ฐํ•œ๋‹ค๋ฉด ์ด๋Ÿฐ ์ง€ํ‘œ๋ฅผ ๋ณด๊ณ  ์ „ํ™˜ํ•ด์„œ ํšจ์œจ์„ ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฉด ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ๋งž์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•œ๋‹ค.

Last updated