๐Ÿ“š ์Šคํ”„๋ง(Spring) ์ •๋ฆฌ

CodeByHanยท2025๋…„ 8์›” 18์ผ

์Šคํ”„๋ง

๋ชฉ๋ก ๋ณด๊ธฐ
29/33

์ง€๊ธˆ๊นŒ์ง€ ๋‹ฌ๋ ค์˜ค๋ฉด์„œ ๊น€์˜ํ•œ๋‹˜์˜ ์Šคํ”„๋ง ๊ฐ•์˜์™€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์Šค ๋ฐ๋ธŒ์ฝ”์Šค์—์„œ ์Šคํ”„๋ง์„ ๋งŽ์ด ๋‹ค๋ค„๋ดค๊ณ  ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  "๊ธฐ๋ณธ์ด ์—†๋‹ค๋ฉด ๋ฏธ๋ž˜๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์—†๋‹ค"๋Š” ๋ง์ฒ˜๋Ÿผ, ๊ธฐ๋ณธ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ณต์Šตํ•˜๋ฉฐ ๋ฏธ๋ž˜๋ฅผ ์œ„ํ•œ ๊ธฐ์ดˆ๋ฅผ ํƒ„ํƒ„ํžˆ ๋‹ค์ ธ๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ์ž์„ธํ•˜๊ฒŒ๋Š” ์ •๋ฆฌ๋Š” ์•ˆํ• ๊ฑฐ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ์•„ ๋งž๋‹ค! ์ด๋Ÿฐ๊ฑฐ์˜€์ง€! ์ •๋„๋งŒ ์ ์„๋ ค๊ณ  ํ•œ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ vs ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

์Šคํ”„๋ง์— ๋Œ€ํ•ด ์•Œ๋ ค๋ฉด ์ผ๋‹จ ํ”„๋ ˆ์ž„์›Œํฌ ์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์˜ ์ฐจ์ด๋ฅผ ์ •๋ฆฌํ•ด์•ผํ•œ๋‹ค.

  • ํ”„๋ ˆ์ž„์›Œํฌ: ๊ธฐ๋ณธ์ ์œผ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๊ธฐ ์œ„ํ•œ ํ‹€์ด๋‚˜ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณต
  • ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: ๋‹จ์ˆœ ํ™œ์šฉ ๊ฐ€๋Šฅํ•œ ๋„๊ตฌ๋“ค์˜ ์ง‘ํ•ฉ

โ—๏ธ ์ฐจ์ด์ ์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋ฉด ํ๋ฆ„์„ ๋ˆ„๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋ƒ์— ๋‹ฌ๋ ค์žˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ ๋Š” ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ์ž์ฒด์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ๋ฐœ์ž๋Š” ๊ทธ ์•ˆ์—์„œ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
๋ฐ˜๋ฉด์—, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ „์ฒด์ ์ธ ํ๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์ž์‹ ์ด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•  ๋•Œ, ๊ฐ€์ ธ๋‹ค ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ฃผ๋„๊ถŒ์ด ํ”„๋ ˆ์ž„์›Œํฌ์—๊ฒŒ ์žˆ๊ณ  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ฃผ๋„๊ถŒ์ด ๊ฐœ๋ฐœ์žํ•œํ…Œ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ“Œ ์Šคํ”„๋ง(Spring)

  • ์ž๋ฐ” ๊ธฐ๋ฐ˜์˜ ์›น ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ

์Šคํ”„๋ง(Spring) ํŠน์ง•

  • ๊ฒฝ๋Ÿ‰ ์ปจํ…Œ์ด๋„ˆ๋กœ์„œ ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• 
    • ๋ชจ๋“  ๊ฐ์ฒด์˜ ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์Šคํ”„๋ง์—์„œ ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์†์‰ฝ๊ฒŒ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.
  • POJO(Plain Old Java Object)
    • ํŠน๋ณ„ํ•œ ๊ทœ์•ฝ์ด๋‚˜ ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ๊ฐ์ฒด๋กœ, ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‹ด๋Š” ๋ฐ ์‚ฌ์šฉ
  • IoC(Inversion Of Control) ์ง€์› (์ œ์–ด์˜ ์—ญ์ „)
    • ์Šคํ”„๋ง์ด ํ๋ฆ„์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์Šคํ”„๋ง์—์„œ ์‚ฌ์šฉ์ž์˜ ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœ
  • DI(Dependency Injection) ์ง€์›
    • ๊ฐ๊ฐ์˜ ๊ณ„์ธต์ด๋‚˜ ์„œ๋น„์Šค๋“ค ๊ฐ„, ์˜์กด์„ฑ์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์„œ๋กœ ์—ฐ๊ฒฐ ์‹œ์ผœ์คŒ
  • AOP(Aspect-Oriented Programming) ์ง€์›
    • ํŠธ๋žœ์žญ์…˜, ๋กœ๊น…์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ

๐Ÿค” DI(Dependency Injection)

์‚ฌ์‹ค ๊ฐœ์ธ์ ์œผ๋กœ ์‰ฌ์šฐ๋ฉด์„œ๋„ ์„ค๋ช…ํ•˜๊ธฐ์—๋Š” ์–ด๋ ค์šด ๊ฐœ๋…์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์˜์กด์„ฑ ์ฃผ์ž…์€ ์Šคํ”„๋ง์„ ๋‹ค๋ฃฌ๋‹ค๋ฉด ์–ด๋”œ ๊ฐ€๋“ ์ง€ ๋‚˜์˜ค๋Š” ๊ฐœ๋…์ด๋‹ค.

IoC (Inversion of Control)๋ฅผ ์ดํ•ดํ•˜๋ฉด DI๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋” ๋ช…ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

IoC๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์˜์กด์„ฑ์„ ์„ค์ •ํ•˜๋Š” ์ฑ…์ž„์„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹Œ, ์™ธ๋ถ€ ์ปจํ…Œ์ด๋„ˆ(์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ๋“ฑ)์— ๋งก๊ธฐ๋Š” ๋ฐฉ์‹์ด๋‹ค.

DI๋Š” ๋ฐ”๋กœ ์ด IoC๋ฅผ ์‹ค์ œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ธ๋ฐ, ์˜์กด์„ฑ์„ ์ฃผ์ž…๋ฐ›๋Š” ๋ฐฉ์‹์—๋Š” ์ƒ์„ฑ์ž ์ฃผ์ž…, ์„ธํ„ฐ(Setter) ์ฃผ์ž…, ํ•„๋“œ ์ฃผ์ž… ๋“ฑ์ด ์žˆ๋‹ค. ์ด ์ค‘์—์„œ ์Šคํ”„๋ง์—์„œ๋Š” ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํ˜ธํ•˜๋Š” ์ถ”์„ธ์ธ๋ฐ, ๊ทธ ์ด์œ ๋Š” ์ฃผ์ž…๋œ ์˜์กด์„ฑ์ด ๋ถˆ๋ณ€์„ฑ์„ ๋ณด์žฅํ•˜๊ณ , ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์˜์กด์„ฑ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ•„์š”๋กœ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€์—์„œ ๋ฐ›๋Š”๊ฒƒ

์ƒ์„ฑ์ž ์ฃผ์ž…

public class YuhanService {
    private final YuhanRepository yuhanRepository;

    // ์ƒ์„ฑ์ž ์ฃผ์ž…
    public YuhanService(YuhanRepository yuhanRepository) {
        this.yuhanRepository = yuhanRepository;
    }
}

์„ธํ„ฐ(Setter) ์ฃผ์ž…

public class YuhanService {
    private YuhanRepository yuhanRepository;

    // ์„ธํ„ฐ ์ฃผ์ž…
    public void setYuhanRepository(YuhanRepository yuhanRepository) {
        this.yuhanRepository = yuhanRepository;
    }
}
  • ๋ถˆ๋ณ€์„ฑ ๋ณด์žฅ ๋ถˆ๊ฐ€

ํ•„๋“œ ์ฃผ์ž…

public class YuhanService {
    @Autowired
    private YuhanRepository yuhanRepository; 
}

๋กฌ๋ณต(Lombok)์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์ข€ ๋” ์‰ฝ๊ณ  ๊ฐ€๋…์„ฑ์žˆ๊ฒŒ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•˜๋‹ค.

@RequiredArgsConstructor
public class YuhanService {
    private final YuhanRepository yuhanRepository;
}

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ(Spring Container)

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ(Spring Container) ๋Š” ์Šคํ”„๋ง์˜ ํ•ต์‹ฌ ์ปดํฌ๋„ŒํŠธ๋‹ค. ์ž๋ฐ” ๊ฐ์ฒด์˜ ์ƒ๋ช… ์ฃผ๊ธฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์ƒ์„ฑ๋œ ์ž๋ฐ” ๊ฐ์ฒด๋“ค์—๊ฒŒ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ๋งํ•˜์ž๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ๋นˆ์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌ

์—ฌ๊ธฐ์„œ ์Šคํ”„๋ง์—์„œ๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ ๋นˆ(Bean) ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” BeanFactory , ApplicationContext ๋‘ ๊ฐ€์ง€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.

BeanFactory๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค๊ณ  ๋นˆ์„ ๋“ฑ๋ก, ์ƒ์„ฑ, ์กฐํšŒ ๋“ฑ์˜ ๋นˆ์„ ๊ด€๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋ฉฐ, getBean() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋นˆ์„ ์ธ์Šคํ„ด์Šคํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ApplicationContext๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜์ง€ BeanFactory๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ณ„๋กœ ์—†๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ(ApplicationContext)๋Š” BeanFactory์˜ ๊ธฐ๋Šฅ์„ ์ƒ์†๋ฐ›์•„ ์ œ๊ณตํ•œ๋‹ค.
๋”ฐ๋ผ์„œ, ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ์„ BeanFactory๊ฐ€ ์ œ๊ณตํ•˜๊ณ , ๊ทธ ์™ธ์˜ ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

๐Ÿค” ๊ตณ์ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ํ•„์š”ํ• ๊นŒ? ๊ทธ๋ƒฅ new ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ๋Ÿฌ๋ฉด ์•ˆ๋˜๋‚˜?

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

์Šคํ”„๋ง ์‹ฑ๊ธ€ํ†ค(Spring Singleton)

์Šคํ”„๋ง์€ ๋นˆ ์ƒ์„ฑ์‹œ ๋””ํดํŠธ๋กœ ์‹ฑ๊ธ€ํ†ค
์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด ์ง์ ‘ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด ์ƒ์„ฑ ๊ด€๋ฆฌ
์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ๋งค๋ฒˆ ๊ฐ์ฒด ์ƒ์„ฑ X -> ์ด๋ฏธ ๋งŒ๋“  ๊ฐ์ฒด ์‚ฌ์šฉ ํšจ์œจ์„ฑ ์ฆ๊ฐ€

์Šคํ”„๋ง ๋นˆ (Spring Bean)

  • ์Šคํ”„๋ง Ioc ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ์ธ์Šคํ„ด์Šคํ™”๋˜๊ณ  ๊ด€๋ฆฌ๋˜๋Š” ๊ฐ์ฒด
  • Spring ์„ค์ • ํŒŒ์ผ(AppConfig)์— ์ •์˜๋˜๊ฑฐ๋‚˜ @Component, @Service, @Repository, @Controller ๋“ฑ์˜ ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ‘œ์‹œ
  • XML, AppConfig(@Configuration) , ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ์ •์˜ ๊ฐ€๋Šฅ

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑํ•œ ๊ฐ์ฒด

์Šคํ”„๋ง ๋นˆ ์ƒ๋ช… ์ฃผ๊ธฐ(Bean LifeCycle)

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ -> Bean ์ƒ์„ฑ -> ์˜์กด์„ฑ ์ฃผ์ž… -> ์ดˆ๊ธฐํ™” ์ฝœ๋ฐฑ -> Bean ์‚ฌ์šฉ -> ์†Œ๋ฉธ ์ „ ์ฝœ๋ฐฑ -> ์Šคํ”„๋ง ์ข…๋ฃŒ

์Šคํ”„๋ง VS ์Šคํ”„๋ง๋ถ€ํŠธ

์Šคํ”„๋ง๋ถ€ํŠธ๋Š” ์Šคํ”„๋ง์„ ๋ณด๋‹ค ๊ฐ„ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ํ™•์žฅํŒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

  • ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์›น ์„œ๋ฒ„(ํ†ฐ์บฃ)๋ฅผ ๋‚ด์žฅํ•˜์ง€ ์•Š์ง€๋งŒ ์Šคํ”„๋ง๋ถ€ํŠธ (Spring Boot) ๋‚ด์žฅ ํ†ฐ์บฃ์„ ๊ธฐ๋ณธ์œผ๋กœ ์ œ๊ณตํ•˜์—ฌ, ๋ณ„๋„์˜ ์™ธ๋ถ€ ์„œ๋ฒ„ ์„ค์ • ์—†์ด ๋ฐ”๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ต‰์žฅํžˆ ๋ณต์žกํ•˜๋‹ค. ๋ฐ‘์—๋ฅผ ๋ณด๋ฉด ํ™•์‹คํžˆ ์ฐจ์ด๊ฐ€ ๋А๊ปด์งˆ ๊ฒƒ์ด๋‹ค. ๋˜ํ•œ configuration ์„ค์ •๋„ ์Šคํ”„๋ง๋ถ€ํŠธ๋Š” AutoConfiguration ์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ ๋” ํŽธ๋ฆฌํ•˜๋‹ค.

์Šคํ”„๋ง

<dependencies>
    <!-- Spring Web -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.9</version>
    </dependency>

    <!-- Spring Data JPA -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.5.4</version>
    </dependency>
 </dependencies>

์Šคํ”„๋ง๋ถ€ํŠธ(Gradle)


dependencies {
    // Spring Boot Web
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // Spring Boot Data JPA
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}

๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ(DispatcherServlet)

HTTP ํ”„๋กœํ† ์ฝœ๋กœ ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์š”์ฒญ์„ ๊ฐ€์žฅ ๋จผ์ € ๋ฐ›์•„ ์ ํ•ฉํ•œ ์ปจํŠธ๋กค๋Ÿฌ์— ์œ„์ž„ํ•ด์ฃผ๋Š” ํ”„๋ก ํŠธ ์ปจํŠธ๋กค๋Ÿฌ(Front Controller)

  1. ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ ์ˆ˜์‹ 
    ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›น ์š”์ฒญ(HttpServletRequest)์„ ํ†ตํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ‘๊ทผํ•˜๋ฉด, ์ด ์š”์ฒญ์ด DispatcherServlet์œผ๋กœ ์ „๋‹ฌ

  2. HandlerMapping์„ ํ†ตํ•œ Controller ๋งคํ•‘
    DispatcherServlet์€ ์š”์ฒญ URL๊ณผ ๊ธฐํƒ€ ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ, ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ ์ ˆํ•œ Controller(Handler)๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด HandlerMapping์— ์š”์ฒญ์„ ์œ„์ž„

  3. HandlerAdapter ์„ ํƒ
    ์ฐพ์€ Controller๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก, DispatcherServlet์€ ํ•ด๋‹น Controller๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” HandlerAdapter๋ฅผ ๊ฒฐ์ •

  4. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์‹คํ–‰ ์š”์ฒญ
    DispatcherServlet์€ ์„ ํƒ๋œ HandlerAdapter์—๊ฒŒ Controller์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋„๋ก ์š”์ฒญ

  5. Controller ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    HandlerAdapter๋Š” Controller์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ˆ˜ํ–‰Controller๋Š” ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ Model ๊ฐ์ฒด์— ๋‹ด๊ณ , ์–ด๋–ค View๋ฅผ ์‚ฌ์šฉํ• ์ง€ ๋…ผ๋ฆฌ์ ์ธ ์ด๋ฆ„์„ ํ•จ๊ป˜ ๋ฐ˜ํ™˜

  • Model: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์‹คํ–‰ ๊ฒฐ๊ณผ๋กœ ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ
  • View : ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด์—ฌ์ค„ ํ™”๋ฉด(View) ํŒŒ์ผ์˜ ์ด๋ฆ„
  1. ViewResolver๋ฅผ ํ†ตํ•œ View ๊ฒฐ์ •
    DispatcherServlet์€ ๋ฐ˜ํ™˜๋ฐ›์€ View ์ด๋ฆ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ViewResolver์—๊ฒŒ ์‹ค์ œ View ๊ฐ์ฒด๋ฅผ ๊ฒฐ์ •ํ•˜๋„๋ก ์š”์ฒญ

  2. ์ตœ์ข… View ๊ฐ์ฒด์— Model ์ „๋‹ฌ
    ViewResolver๊ฐ€ ๋ฐ˜ํ™˜ํ•œ View ๊ฐ์ฒด์— Model ๋ฐ์ดํ„ฐ๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ•˜๋ฉด์„œ, DispatcherServlet์€ ์ตœ์ข… ํ™”๋ฉด ๋ Œ๋”๋ง์„ ์˜๋ขฐ

  3. ๋ Œ๋”๋ง ๋ฐ ์‘๋‹ต ๋ฐ˜ํ™˜
    ์ตœ์ข… View๋Š” ์ „๋‹ฌ๋ฐ›์€ Model ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ™”๋ฉด์„ ๋ Œ๋”๋งํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต์œผ๋กœ ๋ฐ˜ํ™˜

HandlerMapping

  • ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋“ค์–ด์˜จ HTTP ์š”์ฒญ์˜ URL, HTTP ๋ฉ”์„œ๋“œ(GET, POST ๋“ฑ), ํ—ค๋” ๋“ฑ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹นํ•˜๋Š” Hander(controller)๋ฅผ ์ฐพ๋Š” ์—ญํ• 
  • RequestMappingHandlerMapping : ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜(@RequestMapping) ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌ
  • BeanNameUrlHandlerMapping : ์Šคํ”„๋ง ๋นˆ ์ด๋ฆ„๊ณผ URL์„ ๋งคํ•‘
  • SimpleUrlHandlerMapping : XML ๋˜๋Š” Java ์„ค์ • ํŒŒ์ผ์— ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋œ URL ํŒจํ„ด๊ณผ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋งคํ•‘

HandlerAdapter

  • ์‹ค์ œ๋กœ Handler๋ฅผ ์‹คํ–‰ํ•  Adapter๋ฅผ ์ฐพ์•„์„œ Controller ๋กœ์ง์„ ํ˜ธ์ถœํ•˜๋Š” ์—ญํ• 
  • RequestMappingHandlerAdapter : ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜ ์ปจํŠธ๋กค๋Ÿฌ(@RequestMapping)๋ฅผ ์ฒ˜๋ฆฌ
  • HttpRequestHandlerAdapter : HttpRequestHandler ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌ
  • SimpleControllerHandlerAdapter : ๊ฑฐ ์Šคํƒ€์ผ์˜ ์ปจํŠธ๋กค๋Ÿฌ(Controller ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„)๋ฅผ ์ฒ˜๋ฆฌ
  • SimpleServletHandlerAdapter: ํ‘œ์ค€ ์„œ๋ธ”๋ฆฟ ์ธํ„ฐํŽ˜์ด์Šค(javax.servlet.Servlet)๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์‚ฌ์šฉํ•  ๋•Œ ์‚ฌ์šฉ

ViewResolver

  • ์‹คํ–‰ํ•  View๋ฅผ ์ฐพ๋Š” ์—ญํ• 
  • Controller์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ View์˜ ์ด๋ฆ„, ViewResolver๊ฐ€ ์„œ๋ฒ„๋‚ด์˜ ์ ์ ˆํ•œ ๋ทฐ ํŒŒ์ผ ์ฐพ์•„ ์ฒ˜๋ฆฌ
  • @RestController๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์„ HTTP ์‘๋‹ต ๋ณธ๋ฌธ(Response Body)์— ์ง์ ‘ ์ž‘์„ฑํ•˜๋ฉฐ, ๋ฐ˜ํ™˜ ๊ฐ’์€ ์ผ๋ฐ˜์ ์œผ๋กœ JSON ํ˜•์‹์œผ๋กœ ์ฒ˜๋ฆฌ. Spring MVC๋Š” ์ด๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด HttpMessageConverter๋ฅผ ์‚ฌ์šฉ

DAO, VO,BO, DTO

  • DAO(Data Access Object) : DB ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผ์„ ์œ„ํ•œ ๊ฐ์ฒด(Repository, Mapper)
  • VO(Value Object) : ์‹ค์ œ ๋ฐ์ดํ„ฐ๋งŒ์„ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด
  • BO(Business Object) : ์—ฌ๋Ÿฌ DAO๋ฅผ ํ™œ์šฉํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด(Service)
  • DTO(Data Transfer Object) : ๊ฐ ๊ณ„์ธต๊ฐ„์˜ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ์œ„ํ•œ ๊ฐ์ฒด

VO vs DTO
VO๋Š” ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด, ์˜ค์ง read๋งŒ ๊ฐ€๋Šฅ
DTO๋Š” ์ฝ๊ณ  ์“ฐ๋Š” ๊ฒƒ ๊ฐ€๋Šฅ(๊ฐ€๋ณ€์„ฑ)

์—”ํ‹ฐํ‹ฐ(Entity)
์—”ํ‹ฐํ‹ฐ(Entity)๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ 1:1๋กœ ๋งคํ•‘๋˜๋ฉฐ, ๊ณ ์œ  ์‹๋ณ„์ž๋ฅผ ๊ฐ€์ง„ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด๋กœ, ์ฃผ๋กœ CRUD ์ž‘์—…์— ์‚ฌ์šฉ

DTO ์‚ฌ์šฉ ์ด์œ 

  • ์ˆœํ™˜ ์ฐธ์กฐ ์˜ˆ๋ฐฉ
  • ์—”ํ‹ฐํ‹ฐ ๋‚ด๋ถ€ ๊ตฌํ˜„ ์บก์Аํ™”
  • ์—ญํ•  ๋ถ„๋ฆฌ

Spring MVC

๊ฐ ๋ ˆ์ด์–ด๊ฐ„ ๊ธฐ๋Šฅ์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•œ ๋””์ž์ธ ํŒจํ„ด

Model, View, Controller

  • Model : ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๋ฐ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ(DTO, DAO, Service)
  • View: ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ฒ˜๋ฆฌ๊ฒฐ๊ณผ๋ฅผ ์œ ์ €(ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ) ๋ณด์—ฌ์ฃผ๋Š” ์—ญํ• (html, jsp, thymeleaf)
  • Controller : ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  Model , View ์ค‘๊ฐœํ•˜๋Š” ์—ญํ• (Model, View ์—ฐ๊ฒฐ ๋‹ค๋ฆฌ)

์ฆ‰์‹œ ๋กœ๋”ฉ(EAGER) vs ์ง€์—ฐ ๋กœ๋”ฉ(LAZY)

  • ์ฆ‰์‹œ ๋กœ๋”ฉ(EAGER): ์กฐํšŒ์‹œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์กฐํšŒ

  • ์ง€์—ฐ ๋กœ๋”ฉ(LAZY): ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์‹ค์ œ ์‚ฌ์šฉ ๋  ๋•Œ ์กฐํšŒ

N+1 ๋ฌธ์ œ

  • ๋ณดํ†ต ORM์„ ์‚ฌ์šฉํ•  ๋•Œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋ฌธ์ œ๋กœ ์˜ˆ๋ฅผ ๋“ค์–ด, ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์„ ์กฐํšŒํ•  ๋•Œ, ๊ฐ ๊ฒŒ์‹œ๊ธ€์˜ ์ž‘์„ฑ์ž ์ •๋ณด๋ฅผ ๊ฐœ๋ณ„์ ์œผ๋กœ ์กฐํšŒํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ

  • EAGER ๋ฐฉ๋ฒ• ์‚ฌ์šฉ -> JPA๋ฅผ ์˜ˆ๋ฅผ ๋“ค๋ฉด Join Fetch๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ํ•œ๋ฒˆ์˜ ์ฟผ๋ฆฌ๋กœ ํ•จ๊ป˜ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•

  • ๋ฐฐ์น˜ ์‚ฌ์ด์ฆˆ ์„ค์ • -> EAGER๊ฐ€ ๋ถ€๋‹ด์Šค๋Ÿฌ์šฐ๋ฉด ๋ฐฐ์น˜์‚ฌ์ด์ฆˆ๋ฅผ ์„ค์ •ํ•ด์„œ ์กฐํšŒ๋Š” ๋ฐฉ์‹

  • ์—ฐ๊ด€๊ด€๊ณ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ, ํ•˜๋‚˜์˜ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ ธ์„ ๋•Œ, N ๋งŒํผ ์—ฐ๊ด€๋œ ์ฟผ๋ฆฌ ์ถ”๊ฐ€ ์‹คํ–‰

  • ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์€ Fetch Join , @EntityGraph ์‚ฌ์šฉ

์Šคํ”„๋ง ํ•„ํ„ฐ (Spring Filter) vs ์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ(Spring intercepter)

ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์— ๋”ฐ๋ผ ๋‘˜์„ ๊ตฌ๋ถ„ ํ•  ์ˆ˜์žˆ๋‹ค. ์Šคํ”„๋ง ํ•„ํ„ฐ (Spring Filter)๋Š” ๋””์ŠคํŒจ์ฒ˜ ์„œ๋ธ”๋ฆฟ(DispatcherServlet)์œผ๋กœ ์š”์ฒญ์ด ๊ฐ€๊ธฐ์ „์— ์‹คํ–‰๋˜์ง€๋งŒ

์Šคํ”„๋ง ์ธํ„ฐ์…‰ํ„ฐ(Spring intercepter)๋Š” Controller๋กœ ์š”์ฒญ์ด ๊ฐ€๊ธฐ์ „์— ์‹คํ–‰๋œ๋‹ค.

@Requestbody,@RequestParam,@ModealAttribute

  • @Requestbody : ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „์†กํ•˜๋Š” JSON ํ˜•ํƒœ์˜ HTTP Body ๋‚ด์šฉ์„ MessageConveter๋ฅผ ํ†ตํ•ด ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ฃผ๋Š” ์—ญํ• , Getter , Setter ์—†์ด๋„ ์ •์ƒ์ ์œผ๋กœ ํ• ๋‹น

  • @RequestParam :1๊ฐœ์˜ HTTP ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ›๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ, ๋””ํดํŠธ๊ฐ’ true(ํ•„์ˆ˜)

  • @ModealAttribute: ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ „์†กํ•˜๋Š” ํผ(form) ํ˜•ํƒœ์˜ HTTP Body์™€ ์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ์ƒ์„ฑ์ž๋‚˜ Setter๋กœ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ

JPA

  • ์ž๋ฐ”์—์„œ RDB๋ฅผ ์šด์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์ž๋ฐ” API
  • ์ž๋ฐ” ๊ฐ์ฒด์™€ DB ํ…Œ์ด๋ธ” ๊ฐ„์˜ ์—ฐ๋™์„ ์šฉ์ดํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ORM ๊ธฐ๋Šฅ ์ œ๊ณต
  • SQL ์ž‘์„ฑ ์—†์ด๋„ ๊ฐ์ฒด ์ง€ํ–ฅ์ ์œผ๋กœ DB ์กฐ์ž‘ ๊ฐ€๋Šฅ

JPA ๊ตฌํ˜„์ฒด
Hibernate, EclipseLink

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ

  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜๊ตฌ ์ €์žฅํ•˜๋Š” ํ™˜๊ฒฝ
  • ์—”ํ‹ฐํ‹ฐ ์ƒ๋ช… ์ฃผ๊ธฐ / ์ƒํƒœ ๊ด€๋ฆฌ
  • JPA์˜ ์บ์‹ฑ , ์“ฐ๊ธฐ ์ง€์—ฐ, ๋ณ€๊ฒฝ ๊ฐ์ง€ ๊ธฐ๋Šฅ ์ œ๊ณต

ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ

@Transactional ์–ด๋…ธํ…Œ์ด์…˜ ๋ฐ EntityManager๋ฅผ ํ†ตํ•ด ์ง์ ‘ ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘, ์ปค๋ฐ‹ , ๋กค๋ฐฑ ๊ฐ€๋Šฅ

ORM

  • ๊ฐ์ฒด ๊ด€๊ณ„ ๋งคํ•‘ ์˜๋ฏธ, ๊ฐ์ฒด์ง€ํ–ฅ์–ธ์–ด์—์„œ ๊ฐ์ฒด์™€ RDB์˜ ํ…Œ์ด๋ธ”์„ ์ž๋™์œผ๋กœ ๋งคํ•‘ํ•ด์ฃผ๋Š” ๊ธฐ์ˆ  , ๋‹ค์–‘ํ•œ DB์™€ ํ˜ธํ™˜

์ฐธ๊ณ 

profile
๋…ธ๋ ฅ์€ ๋ฐฐ์‹ ํ•˜์ง€ ์•Š์•„ ๐Ÿ”ฅ

0๊ฐœ์˜ ๋Œ“๊ธ€