Backend

<Spring> Spring Bean, IoC/DI ์ •๋ฆฌ 1

wjdtkdgns 2023. 10. 3. 23:20

๐Ÿ“Œ IoC

๐ŸŸข IoC ๋ž€?

IoC๋Š” Inversion of Control์˜ ์•ฝ์ž๋กœ ‘์ œ์–ด์˜ ์—ญ์ „’์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„๋‹ค.

์ด๋•Œ, ‘์ œ์–ด์˜ ์—ญ์ „’์€ ๋ฌด์Šจ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฑธ๊นŒ?

 

์ œ์–ด

๊ฐ์ฒด ์ƒ๋ช…์ฃผ๊ธฐ๋‚˜ ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ์„ ์ง์ ‘ ์ œ์–ดํ•œ๋‹ค ⇒ ๊ฐ์ฒด ์ƒ๋ช…์ฃผ๊ธฐ๋‚˜ ๋ฉ”์„œ๋“œ์˜ ํ˜ธ์ถœ์„ ์ง์ ‘ ๊ด€๋ฆฌํ•œ๋‹ค

์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ “์ œ์–ด”

public class A {
    private B b;

    public A() {
        this.b = new B();
    }
}

A ํด๋ž˜์Šค์—์„œ B๋ฅผ ํ•„๋“œ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ์ƒ์„ฑ์ž ๋‚ด๋ถ€์—์„œ ์ง์ ‘ ์ƒ์„ฑํ•ด ํ•„๋“œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ๊ฐ์ฒด ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ์ฝ”๋“œ๋ผ๊ณ  ๋งํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์—ญ์ „

ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ”„๋ฆ„์„ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ

public class A {
    private B b;

    public A(B b) {
            this.b = b;
    }
}

์ด์ „ ์ฝ”๋“œ์™€ ๊ฐ™์ด A ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ์ฝ”๋“œ์—์„œ๋Š” ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ B๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์žˆ๋‹ค.

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

 

๐ŸŸข IoC๊ฐ€ ์™œ ํ•„์š”ํ•œ๊ฐ€?

๊ฐ์ฒด์ง€ํ–ฅ ์›์น™์„ ์ž˜ ์ง€ํ‚ค๊ธฐ ์œ„ํ•ด!

์—ญํ• ๊ณผ ๊ด€์‹ฌ์„ ๋ถ„๋ฆฌํ•ด ์‘์ง‘๋„๋ฅผ ๋†’์ด๊ณ  ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋ฉฐ,

์ด์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๐ŸŸข IoC์™€ DIP

๋ชฉ์ 

ํ•œ ํด๋ž˜์Šค์˜ ๋ณ€๊ฒฝ์— ๋”ฐ๋ฅธ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋“ค์˜ ์˜ํ–ฅ์„ ์ตœ์†Œํ™”๋”ฐ๋ผ์„œ IoC์™€ DIP๋Š” ๊ฐ™์ด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์ฆ‰, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ง€์†๊ฐ€๋Šฅํ•˜๊ณ  ํ™•์žฅ์„ฑ ์žˆ๊ฒŒ ๋งŒ๋“ ๋‹ค.

ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ์„ ๋А์Šจํžˆ ํ•˜๊ธฐ ์œ„ํ•จ

 

 

IoC์™€ DIP์˜ ๋น„๊ต

๊ฐ™์€ ๋ชฉ์ ์„ ๊ฐ€์กŒ์ง€๋งŒ IoC๋Š” ์ œ์–ด์˜ ์—ญ์ „, DIP๋Š” ์˜์กด ๋ฐฉํ–ฅ์˜ ์—ญ์ „์ด๋‹ค.

IoC์™€ DIP๋Š” ๋ชจ๋‘ principle(์›์น™)์ด๋‹ค.

 

๐Ÿ“Œ Spring Bean

๐ŸŸข ์˜์กด์„ฑ์ด๋ž€?

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
		...
}

public class B {
		...
}

A ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„  B ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•ด์•ผํ•œ๋‹ค.

์ด๋•Œ, A ํด๋ž˜์Šค๋Š” B ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ๊ฐ€์ง„๋‹ค๊ณ  ๋งํ•œ๋‹ค.

์ฆ‰, ํ•œ ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์˜์กด์„ฑ์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

public static void main(String[] args) {
    A a = new A(new B());
}

๊ทธ๋ž˜์„œ A ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ์œ„์™€ ๊ฐ™์€ ๊ตฌ๋ฌธ์ด ํ•„์š”ํ•˜๋‹ค.

ํด๋ž˜์Šค ๊ฐ„์— ์˜์กด ๊ด€๊ณ„๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ํ•œ ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋€” ๋•Œ ๋‹ค๋ฅธ ํด๋ž˜์Šค๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

Spring์€ Spring Bean์„ ํ†ตํ•ด ์œ„์™€ ๊ฐ™์€ ์˜์กด์„ฑ ๋ฌธ์ œ๋ฅผ ๋” ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค.

 

๐ŸŸข Spring Bean์ด๋ž€?

Spring document์—์„œ Bean์— ๋Œ€ํ•ด ์ด๋ ‡๊ฒŒ ์“ฐ์—ฌ์žˆ๋‹ค.

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container.

๊ฐ„๋‹จํžˆ ๋งํ•ด, ์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด์ด๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ๋ž€ ๋ฌด์—‡์ผ๊นŒ?

 

๐ŸŸข ์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ๋ž€?

The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.

๋นˆ์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค.

document์— ๋‚˜์˜จ ์„ค๋ช…์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ApplicationContext ๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ IoC ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋Œ€ํ‘œํ•œ๋‹ค.

ApplicationContext๋Š” ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๋งŒ๋“ค์–ด์ง„๋‹ค.

์ด์— ๋นˆ ์กฐํšŒ, ์ด๋ฒคํŠธ ๋ฐœํ–‰, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์กฐํšŒ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Test
void findAllBean(){
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {
        Object bean = applicationContext.getBean(beanDefinitionName);
        log.info("name=" + beanDefinitionName + " object=" + bean);
    }
}

 

์œ„๋Š” ๋ชจ๋“  ๋นˆ์„ ์กฐํšŒํ•˜๋Š” ํ…Œ์ŠคํŠธ๋‹ค.

์œ„ ๊ฒฐ๊ณผ ๊ฐ’์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ApplicationContext ๋ฅผ ํ†ตํ•ด ๋นˆ์— ๋Œ€ํ•œ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐ŸŸข ๋นˆ ์Šค์ฝ”ํ”„

๋นˆ์€ ์ƒ์„ฑ๋˜๊ณ  ์กด์žฌํ•˜๊ณ  ์ ์šฉ๋˜๋Š” ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ๋นˆ ์Šค์ฝ”ํ”„๋ผ๊ณ  ํ•œ๋‹ค.

์Šคํ”„๋ง์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ์Šค์ฝ”ํ”„๋ฅผ ์ง€์›ํ•œ๋‹ค.

  • ์‹ฑ๊ธ€ํ†ค : ๊ธฐ๋ณธ ์Šค์ฝ”ํ”„, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ๊ฐ€์žฅ ๋„“์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„
  • ํ”„๋กœํ† ํƒ€์ž… : ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•˜๊ณ  ๋”๋Š” ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š” ๋งค์šฐ ์งง์€ ๋ฒ”์œ„์˜ ์Šค์ฝ”ํ”„
  • ์›น ๊ด€๋ จ ์Šค์ฝ”ํ”„
    • request : ์›น ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐˆ๋•Œ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„
    • session : ์›น ์„ธ์…˜์ด ์ƒ์„ฑ๋˜๊ณ  ์ข…๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„
    • application : ์›น์˜ ์„œ๋ธ”๋ฆฟ ์ปจํ…์ŠคํŠธ์™€ ๊ฐ™์€ ๋ฒ”์œ„๋กœ ์œ ์ง€๋˜๋Š” ์Šค์ฝ”ํ”„

๋นˆ์˜ ์Šค์ฝ”ํ”„๋Š” @Scope ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Scope("prototype")
@Component
public class Prototype {
    ...
}

์Šคํ”„๋ง์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณ„๋‹ค๋ฅธ ์„ค์ •์„ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋‚ด๋ถ€์—์„œ ์ƒ์„ฑํ•˜๋Š” ๋นˆ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ชจ๋‘ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ ๋‹ค.

 

๐ŸŸข ์‹ฑ๊ธ€ํ†ค์˜ ๋‹จ์ 

  1. ๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•˜์ง€ ๋ชปํ•œ๋‹ค.
    ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์„ฑ์ž์˜ ์ ‘๊ทผ ์ง€์ •์ž๋ฅผ private์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
    ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๋Š” ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
    ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์ด์ ์ธ ๋‹คํ˜•์„ฑ์„ ์ ์šฉํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋œ๋‹ค.
  2. ์•ˆ์ •์„ฑ์ด ์ค‘์š”ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ•„์ˆ˜์ ์ธ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ต๋‹ค.
    ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ ํ•ด๋‹น ๊ฐ์ฒด๋Š” ๊ณต์œ  ๊ฐ์ฒด๊ฐ€ ๋˜๋ฏ€๋กœ
    ๋‹จ์œ„ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ํ…Œ์ŠคํŠธ์˜ ์ˆœ์„œ์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์ง„๋‹ค.
  3. ์˜์กด๊ด€๊ณ„์ƒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•œ๋‹ค. DIP๋ฅผ ์œ„๋ฐ˜ํ•œ๋‹ค.
  4. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•ด์„œ OCP ์›์น™์„ ์œ„๋ฐ˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.
  5. ๋‚ด๋ถ€ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
  6. private ์ƒ์„ฑ์ž๋กœ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์–ด๋ ต๋‹ค.

์ข…ํ•ฉ์ ์œผ๋กœ ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง„๋‹ค๋Š” ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

 

๐ŸŸข ์Šคํ”„๋ง๊ณผ ์‹ฑ๊ธ€ํ†ค

์Šคํ”„๋ง์€ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ, ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ๋”ฑ ํ•˜๋‚˜ ํ• ๋‹นํ•˜๊ณ , ๋’ค์˜ ํ˜ธ์ถœ ์‹œ๋งˆ๋‹ค ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

์ด๋ฅผ ์ ์šฉํ•˜๋ฉด ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•ด์„œ ํšจ์œจ์ ์ธ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

์Šคํ”„๋ง์—์„œ๋Š” ์ด๋ฅผ ์œ„ํ•ด IoC ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์˜ ๋ชจ๋“  ๋‹จ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐ŸŸข ๋นˆ๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…

์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•œ๋‹ค๊ณ  ํ•˜๋ฉด ์–ด๋””์—์„ ๊ฐ€ new ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.

public class Service {
    private final Dao dao;

    public Service(Dao dao) {
            this.dao = dao;
    }
}
Service service = new Service(new JdbcDao());

์˜ˆ์‹œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Service๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š”๋ฐ Service์˜ ์ƒ์„ฑ์ž๋กœ Dao ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋„ฃ์–ด์ฃผ๊ณ  ์žˆ๋‹ค.

Q. ๋งŒ์•ฝ Dao์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ๋ฐ”๋€๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณณ์—์„œ๋„ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚œ๋‹ค.

์„œ๋น„์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ Dao๋ฅผ ์ดˆ๊ธฐํ™”ํ•จ๊ณผ ๋™์‹œ์— ์–ด๋–ค Dao์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์„ ํƒํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ์ฑ…์ž„๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

LineService lineService = new LineServie(new StationsDao(), new LineDao(), new SectionDao());

๋˜ํ•œ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•  ๋•Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์˜์กด์„ฑ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ํ•ด๋‹น ์˜์กด์„ฑ ์ฃผ์ž… ์ˆœ์„œ๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค.

์ง์ ‘ ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์˜์กด ๊ด€๊ณ„๋ฅผ ๋ชจ๋‘ ํŒŒ์•…ํ•ด์•ผ ํ•˜๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์ด ์ƒ๊ธด๋‹ค.

๋˜ํ•œ ๋งŽ์€ ๊ฐ์ฒด๊ฐ€ ์ค‘๋ณต ์ƒ์„ฑ์ด ๋˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ž˜์„œ ์˜์กด์„ฑ ์ฃผ์ž…์ด ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜์—ฌ,

์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…์„ ๊ด€๋ฆฌํ•˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

 

๐ŸŸข ์Šคํ”„๋ง IoC ์ปจํ…Œ์ด๋„ˆ๋Š” ์–ด๋–ป๊ฒŒ ๋นˆ์„ ๊ด€๋ฆฌํ• ๊นŒ?

IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๋นˆ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ณผ์ •์€ ์ด๋Ÿฌํ•˜๋‹ค.

 

1. ๊ฐ์ฒด ์ƒ์„ฑ + property ์„ค์ •

 

๋จผ์ € Spring IoC ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑ์ด ๋˜๋ฉด ๋นˆ ์Šค์ฝ”ํ”„๊ฐ€ ์‹ฑ๊ธ€ํ†ค์ธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

์ด๋•Œ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์–‘ํ•œ Configuration ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ†ต์ผ๋œ Bean Definition์„ ์ƒ์„ฑํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•  POJO์™€ Bean Definition ์ •๋ณด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋นˆ์„ ์ƒ์„ฑํ•œ๋‹ค.

์ด ๊ณผ์ •์—์„œ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ํ‰๋ฒ”ํ•œ ์ž๋ฐ” ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

2. ์˜์กด ์„ค์ •

๋นˆ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ์ด ๋˜๋ฉด IoC ์ปจํ…Œ์ด๋„ˆ๋Š” ์˜์กด ์„ค์ •์„ ํ•œ๋‹ค.

์ด๋•Œ ์˜์กด์„ฑ ์ž๋™ ์ฃผ์ž…์ด ์ผ์–ด๋‚˜๊ฒŒ ๋œ๋‹ค.

 

3. ๊ฐ์ฒด ์ดˆ๊ธฐํ™” → ์‚ฌ์šฉ → ์†Œ๋ฉธ

 

๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๋‹ค ์ดˆ๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์‚ฌ์šฉ ์ „์— ์ดˆ๊ธฐํ™” ๊ณผ์ •์ด ํ•„์š”ํ•œ ๊ฐ์ฒด๋“ค์€ ์ดˆ๊ธฐํ™” ๊ณผ์ •์„ ์ง„ํ–‰ํ•œ๋‹ค.

์ดˆ๊ธฐํ™”๊ฐ€ ๋๋‚˜๋ฉด ๋“œ๋””์–ด ๋นˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ๋นˆ ์Šค์ฝ”ํ”„๊ฐ€ ์‹ฑ๊ธ€ํ†ค์ธ ๊ฐ์ฒด๋“ค๋„ ํ•จ๊ป˜ ์†Œ๋ฉธ๋œ๋‹ค.

 

๐ŸŸข ๋นˆ ์„ค์ • ๋ฐฉ๋ฒ•

๋นˆ์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค.

@Bean ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

public class Appconfig {
    @Bean
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB(beanA());
    }

    @Bean
    public BeanC beanC() {
        return new BeanC(beanA());
    }
}
@Test
void notSingleton(){
    Appconfig appConfig = new Appconfig();

    BeanA beanA1 = appConfig.beanA();
    BeanA beanA2 = appConfig.beanA();

    log.info("beanA1 = " + beanA1);
    log.info("beanA2 = " + beanA2);

    assertThat(beanA1).isNotSameAs(beanA2);
}

์œ„ ์˜ˆ์‹œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ์ถœ๋ ฅํ–ˆ์ง€๋งŒ ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค.

BeanA ๊ฐ์ฒด๊ฐ€ 2๋ฒˆ ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ์ด๋‹ค.

์ด๋Š” ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ์‹ฑ๊ธ€ํ†ค์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ?

์Šคํ”„๋ง์—์„œ ๋นˆ์„ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด, @Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค.

@Configuration
public class Appconfig {
    @Bean
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB(beanA());
    }

    @Bean
    public BeanC beanC() {
        return new BeanC(beanA());
    }
}
@Test
void singleton(){
    ApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);

    BeanA beanA1 = ac.getBean("beanA",BeanA.class);
    BeanA beanA2= ac.getBean("beanA",BeanA.class);

    log.info("beanA1 = " + beanA1);
    log.info("beanA2 = " + beanA2);

    assertThat(beanA1).isSameAs(beanA2);
}

@Test
void singleton2(){
    ApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);

    BeanB beanB = ac.getBean("beanB",BeanB.class);
    BeanC beanC= ac.getBean("beanC",BeanC.class);
    BeanA beanA1 = beanB.getBeanA();
    BeanA beanA2= beanC.getBeanA();

    log.info("beanA1 = " + beanA1);
    log.info("beanA2 = " + beanA2);

    assertThat(beanA1).isSameAs(beanA2);
}

ApplicationContext์˜ ๊ตฌํ˜„์ฒด์ธ AnnotationConfigApplicationContext ์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธด ๊ฐ’์€ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ AppConfig ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒผ์œผ๋ฏ€๋กœ, AppConfig ์™€ ํ•ด๋‹น ํŒŒ์ผ์— ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ ๊ฒƒ๋“ค์ด ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

BeanB๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด BeanA๊ฐ€ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•˜๊ณ , BeanC๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด BeanA๊ฐ€ ๋˜ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹ˆ๊ฒŒ ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ์Šคํ”„๋ง์ด ์ด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค.

@Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด,

์Šคํ”„๋ง์ด ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•ด์„œ ์‹ฑ๊ธ€ํ†ค์ด ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ์ €์žฅํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ๋นˆ์„ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„ ,

@Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•œ ๊ฐ์ฒด๋ฅผ ApplicationContext์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธฐ๋ฉด ๋œ๋‹ค ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐ŸŸข ๋นˆ ์„ค์ • ์‹œ ์ฃผ์˜์ 

1. ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„์˜ ๋นˆ์ด ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋ฉด ์•ˆ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„์˜ ๋นˆ์ด value๋ผ๋Š” ์ƒํƒœ๋ฅผ ๊ฐ€์งˆ ๋•Œ Thread 1์€ value์˜ ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

๊ทธ๋ฆฌ๊ณ  Thread2๋Š” value๋ผ๋Š” ๊ฐ’์„ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋ฉด Thread2๋Š” ๋งค๋ฒˆ ๋‹ค๋ฅธ ๊ฐ’์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๋‹น ๋นˆ์˜ ์ƒํƒœ๋ฅผ ํ•ญ์ƒ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๊ฐ€ ์˜๋„ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์—†๋‹ค.

๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋นˆ ์Šค์ฝ”ํ”„๋Š” ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์„ค์ •ํ•  ๊ฒฝ์šฐ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๋ฉด ์•ˆ๋œ๋‹ค.

 

2. ์˜์กด์„ฑ์„ ์ž๋™ ์ฃผ์ž…ํ•ด์•ผ ํ•  ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ๋‘ ๊ฐœ ์ด์ƒ์ผ ๊ฒฝ์šฐ

@Repository
public class StationInMemoryStationDao implements StationDao {
}
@Repository
public class StationJdbcStationDao implements StationDao {
}
@Service
public class StationService {

		private final StationDao stationDao;

		public StationService(final StationDao stationDao) {
				this.stationDao = stationDao;
		}
}

์˜์กด์„ฑ์„ ์ž๋™ ์ฃผ์ž…ํ•ด์•ผํ•  ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ๋‘ ๊ฐœ ์ด์ƒ์ด๋ผ๋ฉด,

์Šคํ”„๋ง์€ ์–ด๋–ค ๊ตฌํ˜„์ฒด๋ฅผ ์ž๋™ ์ฃผ์ž…ํ• ์ง€ ์ •ํ•˜์ง€ ๋ชปํ•ด์„œ ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ถฉ๋Œ๋กœ ์ธํ•ด์„œ ๋‹คํ˜•์„ฑ์„ ์ด์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฑด๊ฐ€?

์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ •ํ•˜๋ฉด ๋œ๋‹ค - Primary, Qualifier