๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒฑ Sprout Framework

Spring์ด ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ตฌ์ถ•ํ•œ ๊ฒฝ๋Ÿ‰ Java ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค.

Sprout์€ ํ˜„๋Œ€ Java ์›น ๊ฐœ๋ฐœ์˜ ํ•ต์‹ฌ ๊ฐœ๋…์„ ๋ฐ”๋‹ฅ๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•œ ํฌ๊ด„์ ์ธ ์›น ํ”„๋ ˆ์ž„์›Œํฌ์ž…๋‹ˆ๋‹ค. ์™„์ „ํžˆ ์ž‘๋™ํ•˜๋Š” NIO & ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์„œ๋ฒ„์™€ ๋น„๋™๊ธฐ WebSocket ์Šคํƒ์„ ํ†ตํ•ด ๋ช…ํ™•์„ฑ, ํ•ดํ‚น ๊ฐ€๋Šฅ์„ฑ, ํ™•์žฅ์„ฑ์— ์ค‘์ ์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ Sprout์ธ๊ฐ€?โ€‹

๊ต์œก์  ๋ชฉ์ : Spring๊ณผ ๊ฐ™์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋น„์Šทํ•œ ๊ธฐ๋Šฅ์„ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ตฌ์ถ•ํ•˜์—ฌ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

์ง‘์ค‘๋œ ๋ฒ”์œ„: ์ปจํ…Œ์ด๋„ˆ/AOP/์›น/์„œ๋ฒ„ ๋‚ด๋ถ€์— ์˜๋„์ ์œผ๋กœ ์ง‘์ค‘. v1.0์—์„œ๋Š” ์™„์ „ํ•œ ORM์ด ๋ฒ”์œ„์—์„œ ์ œ์™ธ๋˜์–ด ํ‘œ๋ฉด์ ์„ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์œ ์ง€ํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅโ€‹

๐Ÿ—๏ธ IoC / DI ์ปจํ…Œ์ด๋„ˆโ€‹

  • @Component, @Service, @Controller, @Repository, @Configuration, @Aspect ์Šค์บ”
  • ์ž๋™ List<T> ์ฑ„์šฐ๊ธฐ์™€ ํ•จ๊ป˜ ์ƒ์„ฑ์ž ๊ธฐ๋ฐ˜ ์ฃผ์ž…
  • ์œ„์ƒ ์ •๋ ฌ์„ ์‚ฌ์šฉํ•œ ์ˆœํ™˜ ์˜์กด์„ฑ ๊ฐ์ง€
  • ํ•ฉ๋ฆฌ์ ์ธ ๊ธฐ๋ณธ๊ฐ’์„ ์œ„ํ•œ BeanDefinitionRegistrar๋ฅผ ํ†ตํ•œ ์ž๋™ ๊ตฌ์„ฑ

๐ŸŽฏ AOP (๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)โ€‹

  • ์–ด๋…ธํ…Œ์ด์…˜ ์ฃผ๋„ (@Before, @After, @Around)
  • ์™€์ผ๋“œ์นด๋“œ(*, .., ?)๋ฅผ ํฌํ•จํ•œ AspectJ ์Šคํƒ€์ผ ํฌ์ธํŠธ์ปท
  • CGLIB ์„œ๋ธŒํด๋ž˜์‹ฑ + Objenesis ํด๋ฐฑ (์ธ์ž๊ฐ€ ์—†๋Š” ์ƒ์„ฑ์ž ๋ถˆํ•„์š”)
  • ํƒ€๊ฒŸ๋ณ„ ํ”„๋ก์‹œ๊ฐ€ ์žˆ๋Š” ์ •๋ ฌ๋œ ์–ด๋“œ๋ฐ”์ด์ € ์ฒด์ธ

๐ŸŒ ์›น ๋ ˆ์ด์–ดโ€‹

  • ์„ ์–ธ์  ๋ผ์šฐํŒ… (@GetMapping, @PostMapping ๋“ฑ)
  • ๊ฒฝ๋กœ ๋ณ€์ˆ˜({id})์™€ ์š”์ฒญ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ฐ”์ธ๋”ฉ
  • ํฌ๊ด„์ ์ธ ์ธ์ˆ˜ ๋ฆฌ์กธ๋ฒ„ ๋ฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
  • @ControllerAdvice๋ฅผ ํ†ตํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

โšก ๊ณ ์„ฑ๋Šฅ ์„œ๋ฒ„โ€‹

  • java.nio.channels๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ NIO ์„œ๋ฒ„
  • ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๋ชจ๋“œ: ๊ฐ€์ƒ ์Šค๋ ˆ๋“œ๋ฅผ ํ†ตํ•œ HTTP, NIO๋ฅผ ํ†ตํ•œ WebSocket
  • ํ•™์Šต ๋ฐ ๋””๋ฒ„๊น…์„ ์œ„ํ•œ ๋ธ”๋กœํ‚น ํด๋ฐฑ
  • ๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•œ ์‹คํ–‰ ๋ชจ๋“œ ๋ฐ ์Šค๋ ˆ๋“œ ์œ ํ˜•

๐Ÿ”’ ๋ณด์•ˆ ์‹œ์Šคํ…œโ€‹

  • ๋ชจ๋“ˆ์‹ ์ธ์ฆ (AuthenticationManager, UserDetailsService)
  • @PreAuthorize๋ฅผ ํ†ตํ•œ ๋ฉ”์„œ๋“œ ๋ณด์•ˆ (AOP ๊ธฐ๋ฐ˜)
  • URL ์ธ๊ฐ€ ๋ฐ ์—ญํ•  ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ์ œ์–ด
  • ์š”์ฒญ๋ณ„ ThreadLocal์„ ๊ฐ€์ง„ SecurityContextHolder

๐Ÿ”Œ WebSocket ์ง€์›โ€‹

  • RFC6455 ํ˜ธํ™˜ ํ•ธ๋“œ์…ฐ์ดํฌ ๋ฐ ํ”„๋ ˆ์ž„ ์ฒ˜๋ฆฌ
  • ์šฐ์•„ํ•œ ์—ฐ๊ฒฐ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ€์ง„ ๋…ผ๋ธ”๋กœํ‚น ์“ฐ๊ธฐ ํ
  • ํฐ ๋ฉ”์‹œ์ง€๋ฅผ ์œ„ํ•œ ๋ถ„ํ•  ์ง€์›
  • ์ƒ๋ช…์ฃผ๊ธฐ ํ›… (@OnOpen, @OnMessage, @OnClose, @OnError)

ํ’ˆ์งˆ & ํ…Œ์ŠคํŠธโ€‹

575๊ฐœ ํ…Œ์ŠคํŠธ
85% ๋ผ์ธ ์ปค๋ฒ„๋ฆฌ์ง€
75% ๋ธŒ๋žœ์น˜ ์ปค๋ฒ„๋ฆฌ์ง€
0๊ฐœ ์‹คํŒจ

ํฌ๊ด„์ ์ธ ํ…Œ์ŠคํŠธ ์ŠˆํŠธ๋Š” ๋‹ค์Œ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค:

  • ํ•ต์‹ฌ ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋Šฅ (์Šค์บ”, ์ฃผ์ž…, ์ƒ๋ช…์ฃผ๊ธฐ)
  • AOP ์–ด๋“œ๋ฐ”์ด์Šค ๋นŒ๋”์™€ ์ธํ„ฐ์…‰ํ„ฐ
  • MVC ์š”์ฒญ/์‘๋‹ต ์ฒ˜๋ฆฌ
  • ๋ณด์•ˆ ์ธ์ฆ ๋ฐ ์ธ๊ฐ€
  • ์„œ๋ฒ„ ๊ตฌํ˜„ (๋ธ”๋กœํ‚น/NIO/ํ•˜์ด๋ธŒ๋ฆฌ๋“œ)
  • WebSocket ํ”„๋กœํ† ์ฝœ ์ค€์ˆ˜

์‹œ์ž‘ํ•˜๊ธฐโ€‹

Sprout์œผ๋กœ ๊ตฌ์ถ•ํ•  ์ค€๋น„๊ฐ€ ๋˜์…จ๋‚˜์š”? ๋น ๋ฅธ ์‹œ์ž‘ ๊ฐ€์ด๋“œ๋ฅผ ํ™•์ธํ•˜์—ฌ ๋ช‡ ๋ถ„ ์•ˆ์— ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”.

์•„ํ‚คํ…์ฒ˜๋ฅผ ์ดํ•ดํ•˜๊ณ  ์‹ถ์œผ์‹ ๊ฐ€์š”? ์•„ํ‚คํ…์ฒ˜ ๊ฐ€์ด๋“œ๋ฅผ ํƒ์ƒ‰ํ•˜์—ฌ Sprout์ด IoC, AOP, ์›น ์„œ๋น™์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์„ธ์š”.

์ปค๋ฎค๋‹ˆํ‹ฐ & ์ง€์›โ€‹