Claire's Study Note

[์Šคํ”„๋ง ๊ธฐ๋ณธ] 05. ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

by Hi.Claire
๋ฐ˜์‘ํ˜•

๐Ÿ–ฅ๏ธ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ (๊น€์˜ํ•œ, ์ธํ”„๋Ÿฐ)

์„น์…˜5. ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

05-1. ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์‹ฑ๊ธ€ํ†ค

๋Œ€๋ถ€๋ถ„์˜ ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‹ค.

(๋ฌผ๋ก  ๋ฐฐ์น˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜, ๋ฐ๋ชฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋“ฑ ์›น์ด ์•„๋‹Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ๋„ ์–ผ๋งˆ๋“ ์ง€ ๊ฐ€๋Šฅํ•˜๋‹ค.)

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ณดํ†ต ์—ฌ๋Ÿฌ ๊ณ ๊ฐ์ด ๋™์‹œ์— ์š”์ฒญ์„ ํ•œ๋‹ค.

์ด๋•Œ ์Šคํ”„๋ง ์—†๋Š” ์ˆœ์ˆ˜ํ•œ DI ์ปจํ…Œ์ด๋„ˆ(์˜ˆ : AppConfig)๋Š” ๊ณ ๊ฐ์ด ์š”์ฒญ์„ ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ์‹ฌํ•˜๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๋”ฑ 1๊ฐœ๋งŒ ์ƒ์„ฑ๋˜๊ณ  ๊ณต์œ ๋˜๋„๋ก ์„ค๊ณ„ํ•˜๋ฉด ๋œ๋‹ค.

-> ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด

 

์Šคํ”„๋ง ์—†๋Š” ์ˆœ์ˆ˜ํ•œ DI ์ปจํ…Œ์ด๋„ˆ

 

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : ๊ฐ•์˜์ž๋ฃŒ

 

test/java/hello/core/singleton/SingletonTest.java

package hello.core.singleton;

import hello.core.AppConfig;
import hello.core.member.MemberService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class SingletonTest {

    @Test
    @DisplayName("์Šคํ”„๋ง์—†๋Š” ์ˆœ์ˆ˜ํ•œ DI ์ปจํ…Œ์ด๋„ˆ")
    public void pureContainer() {

        AppConfig appConfig = new AppConfig();

        // 1. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
        MemberService memberService1 = appConfig.memberService();

        // 2. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
        MemberService memberService2 = appConfig.memberService();

        // ์ฐธ์กฐ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฒƒ์„ ํ™•์ธ
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        // memberService1 != memberService2
        assertThat(memberService1).isNotSameAs(memberService2);
    }

}

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

memberService1๊ณผ memberService2์˜ ์ฐธ์กฐ๊ฐ’์ด ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

 

05-2. ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์€ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋”ฑ 1๊ฐœ๋งŒ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ 2๊ฐœ ์ด์ƒ ์ƒ์„ฑํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์•„๋‘์–ด์•ผ ํ•œ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ ์šฉํ•˜๊ธฐ

    1. static ์˜์—ญ์— ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด์„œ ์˜ฌ๋ ค๋‘”๋‹ค.

    2. ์ด ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์˜ค์ง getInstance() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 

    3. private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ž„์˜๋กœ new ํ‚ค์›Œ๋“œ๋กœ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.

 

(์ฐธ๊ณ ) static๊ณผ ์‹ฑ๊ธ€ํ†ค์— ๋Œ€ํ•œ ์ •๋ฆฌ

https://moominie.tistory.com/14

 

06-5. ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„์™€ ์ •์  ๋ฉค๋ฒ„

06. ํด๋ž˜์Šค 06-5. ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„์™€ ์ •์  ๋ฉค๋ฒ„ ์ธ์Šคํ„ด์Šค(instance) ๋ฉค๋ฒ„ ๊ฐ์ฒด๋งˆ๋‹ค ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฉค๋ฒ„ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค)๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ•„๋“œ์™€ ๋ฉ”์†Œ๋“œ ์ธ์Šคํ„ด์Šค ํ•„๋“œ : ํž™ ์˜์—ญ์˜ ๊ฐ์ฒด๋งˆ๋‹ค ๊ฐ€

moominie.tistory.com

 

test/java/hello/core/singleton/SingletonService.java

package hello.core.singleton;

public class SingletonService {

    // 1. static ์˜์—ญ์— ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด์„œ ์˜ฌ๋ ค๋‘”๋‹ค.
    private static final SingletonService instance = new SingletonService();

    // 2. ์ด ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋ฉด ์˜ค์ง getInstance() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    public static SingletonService getInstance() {
        return instance;
    }

    // 3. private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ž„์˜๋กœ new ํ‚ค์›Œ๋“œ๋กœ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.
    private SingletonService() {

    }

    public void logic() {
        System.out.println("์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด ๋กœ์ง ํ˜ธ์ถœ");
    }
}

 

test/java/hello/core/singleton/SingletonTest.java

package hello.core.singleton;

import hello.core.AppConfig;
import hello.core.member.MemberService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;

public class SingletonTest {

    @Test
    @DisplayName("์Šคํ”„๋ง์—†๋Š” ์ˆœ์ˆ˜ํ•œ DI ์ปจํ…Œ์ด๋„ˆ")
    public void pureContainer() {

        AppConfig appConfig = new AppConfig();

        // 1. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
        MemberService memberService1 = appConfig.memberService();

        // 2. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑ
        MemberService memberService2 = appConfig.memberService();

        // ์ฐธ์กฐ๊ฐ’์ด ๋‹ค๋ฅธ ๊ฒƒ์„ ํ™•์ธ
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        // memberService1 != memberService2
        assertThat(memberService1).isNotSameAs(memberService2);
    }

    @Test
    @DisplayName("์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ ์šฉํ•œ ๊ฐ์ฒด ์‚ฌ์šฉ")
    public void SingletonServiceTest() {

        // new ์—ฐ์‚ฐ์ž๋กœ ๊ฐ์ฒด ์ƒ์„ฑ ๋ถˆ๊ฐ€
//        SingletonService singletonService = new SingletonService();

        // 1. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
        SingletonService singletonService1 = SingletonService.getInstance();

        // 2. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
        SingletonService singletonService2 = SingletonService.getInstance();

        // ์ฐธ์กฐ๊ฐ’์ด ๊ฐ™์€ ๊ฒƒ์„ ํ™•์ธ
        System.out.println("singletonService1 = " + singletonService1);
        System.out.println("singletonService2 = " + singletonService2);

        // singletonService1 == singletonService2
        assertThat(singletonService1).isSameAs(singletonService2);
    }

}

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

singletonService1๊ณผ singletonService2์˜ ์ฐธ์กฐ๊ฐ’์ด ๊ฐ™์€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ ์šฉํ•˜๋ฉด ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ์˜ฌ ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ , ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•ด์„œ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆ˜ ๋งŽ์€ ๋ฌธ์ œ์ ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ฌธ์ œ์ 

    - ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๋งŽ์ด ๋“ค์–ด๊ฐ„๋‹ค.

    - ์˜์กด๊ด€๊ณ„์ƒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ญํ• ์ด ์•„๋‹Œ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กดํ•œ๋‹ค. (์˜ˆ : MemberServiceImpl.getInstance())

        -> DIP๋ฅผ ์œ„๋ฐ˜ํ•œ๋‹ค.

    - ์œ„์™€ ๊ฐ™์€ ์ด์œ ๋กœ OCP๋ฅผ ์œ„๋ฐ˜ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.

    - ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

    - ๋‚ด๋ถ€ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

    - private ์ƒ์„ฑ์ž๋กœ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์–ด๋ ต๋‹ค.

    - ๊ฒฐ๋ก ์ ์œผ๋กœ ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.

    - ์•ˆํ‹ฐํŒจํ„ด์œผ๋กœ ๋ถˆ๋ฆฌ๊ธฐ๋„ ํ•œ๋‹ค.

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์Šคํ”„๋ง์€ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ• ๊นŒ?

 

05-3. ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ํ•™์Šตํ•œ ์Šคํ”„๋ง ๋นˆ์ด ๋ฐ”๋กœ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š” ๋นˆ์ด๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

    - ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์ ์šฉํ•˜์ง€ ์•Š์•„๋„ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

    - ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ ์—ญํ• ์„ ํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‹ฑ๊ธ€ํ†ค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ผ ํ•œ๋‹ค.

    - ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ด๋Ÿฐ ๊ธฐ๋Šฅ ๋•๋ถ„์— ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ชจ๋“  ๋‹จ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

        -> ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์œ„ํ•œ ์ง€์ €๋ถ„ํ•œ ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด๊ฐ€์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

        -> DIP, OCP, ํ…Œ์ŠคํŠธ, private ์ƒ์„ฑ์ž๋กœ๋ถ€ํ„ฐ ์ž์œ ๋กญ๊ฒŒ ์‹ฑ๊ธ€ํ†ค์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

test/java/hello/core/singleton/SingletonTest.java

(์ƒ๋žต)

    @Test
    @DisplayName("์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์™€ ์‹ฑ๊ธ€ํ†ค")
    public void springContainer() {

        ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

        // 1. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
        MemberService memberService1 = ac.getBean("memberService", MemberService.class);

        // 2. ์กฐํšŒ : ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
        MemberService memberService2 = ac.getBean("memberService", MemberService.class);

        // ์ฐธ์กฐ๊ฐ’์ด ๊ฐ™์€ ๊ฒƒ์„ ํ™•์ธ
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        // memberService1 == memberService2
        assertThat(memberService1).isSameAs(memberService2);
    }
    
(์ƒ๋žต)

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

memberService1๊ณผ memberService2๋Š” ์ฐธ์กฐ๊ฐ’์ด ๊ฐ™๋‹ค.

์ฆ‰, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์Šคํ”„๋ง ๋นˆ์„ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

 

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : ๊ฐ•์˜์ž๋ฃŒ

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ๊ณ ๊ฐ์˜ ์š”์ฒญ์ด ์˜ฌ ๋•Œ๋งˆ๋‹ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•ด์„œ ํšจ์œจ์ ์œผ๋กœ ์žฌ์‚ฌ์šฉํ•œ๋‹ค.

 

(์ฐธ๊ณ ) ์Šคํ”„๋ง์˜ ๊ธฐ๋ณธ ๋นˆ ๋“ฑ๋ก ๋ฐฉ์‹์€ ์‹ฑ๊ธ€ํ†ค์ด์ง€๋งŒ ์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹๋งŒ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•œ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋’ค์˜ ๋นˆ ์Šค์ฝ”ํ”„์—์„œ ์•Œ์•„๋ณด์ž.

 

05-4. ์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹์˜ ์ฃผ์˜์ 

    - ๋ฌด์ƒํƒœ(stateless)๋กœ ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.

        -> ์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹์€ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•ด์„œ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋Š” ์ƒํƒœ๋ฅผ ์œ ์ง€(stateful)ํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.

    - ํŠน์ • ํด๋ผ์ด์–ธํŠธ์— ์˜์กด์ ์ธ ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค.

    - ํŠน์ • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์•ˆ๋œ๋‹ค.

    - ๊ฐ€๊ธ‰์  ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค.

    - ํ•„๋“œ ๋Œ€์‹ ์— ์ž๋ฐ”์—์„œ ๊ณต์œ ๋˜์ง€ ์•Š๋Š” ์ง€์—ญ๋ณ€์ˆ˜, ํŒŒ๋ผ๋ฏธํ„ฐ, ThreadLocal ๋“ฑ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

    - ์Šคํ”„๋ง ๋นˆ์˜ ํ•„๋“œ์— ๊ณต์œ  ๊ฐ’์„ ์„ค์ •ํ•˜๋ฉด ํฐ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์  ์˜ˆ์‹œ

test/java/hello/core/singleton/StatefulService.java

package hello.core.singleton;

public class StatefulService {

    private int price; // ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ํ•„๋“œ

    public void order(String name, int price) {

        System.out.println("name = " + name + ", price = " + price);

        this.price = price; // ์—ฌ๊ธฐ๊ฐ€ ๋ฌธ์ œ!
    }

    public int getPrice() {
        return price;
    }

}

 

test/java/hello/core/singleton/StatefulServiceTest.java

package hello.core.singleton;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class StatefulServiceTest {

    @Test
    void StatefulServiceSingleton() {

        ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);

        StatefulService statefulService1 = ac.getBean("statefulService", StatefulService.class);
        StatefulService statefulService2 = ac.getBean("statefulService", StatefulService.class);

        // TreadA : A์‚ฌ์šฉ์ž 10000์› ์ฃผ๋ฌธ
        statefulService1.order("userA", 10000);

        // TreadB : B์‚ฌ์šฉ์ž 20000์› ์ฃผ๋ฌธ
        statefulService2.order("userB", 20000);

        // A์‚ฌ์šฉ์ž์˜ ์ฃผ๋ฌธ๊ธˆ์•ก์€ ๊ธฐ๋Œ€์™€ ๋‹ค๋ฅด๊ฒŒ 10000์›์ด ์•„๋‹Œ 20000์›์ด ์ถœ๋ ฅ๋œ๋‹ค.
        System.out.println("userA์˜ ์ฃผ๋ฌธ ๊ธˆ์•ก : " + statefulService1.getPrice());

        assertThat(statefulService1.getPrice()).isEqualTo(20000);
    }

    public static class TestConfig {

        @Bean
        public StatefulService statefulService() {
            return new StatefulService();
        }
    }

}

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

์œ„์˜ ํ…Œ์ŠคํŠธ ์˜ˆ์ œ์—์„œ ์ตœ๋Œ€ํ•œ ๋‹จ์ˆœํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์‹ค์ œ ์“ฐ๋ ˆ๋“œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค.

ThreadA๊ฐ€ ์‚ฌ์šฉ์žA ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ThreadB๊ฐ€ ์‚ฌ์šฉ์žB ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

StatefulService์˜ price ํ•„๋“œ๋Š” ๊ณต์œ ๋˜๋Š” ํ•„๋“œ์ธ๋ฐ ํŠน์ • ํด๋ผ์ด์–ธํŠธ์— ์˜ํ•ด ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ ์‚ฌ์šฉ์žA์˜ ์ฃผ๋ฌธ๊ธˆ์•ก์€ 10000์›์ด ์•„๋‹Œ 20000์›์ด๋ผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”๋‹ค.

์‹ค๋ฌด์—์„œ ์ด๋Ÿด ๊ฒฝ์šฐ ํ•ด๊ฒฐํ•˜๊ธฐ ์–ด๋ ค์šด ํฐ ๋ฌธ์ œ๋“ค์ด ํ„ฐ์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ณต์œ ํ•„๋“œ๋Š” ์กฐ์‹ฌํ•ด์•ผ ํ•œ๋‹ค.

-> ์Šคํ”„๋ง ๋นˆ์€ ํ•ญ์ƒ ๋ฌด์ƒํƒœ(stateless)๋กœ ์„ค๊ณ„ํ•˜์ž!

 

์ง€์—ญ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ์˜ˆ

test/java/hello/core/singleton/StatefulService.java

package hello.core.singleton;

public class StatefulService {

//    private int price; // ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ํ•„๋“œ

    public int order(String name, int price) {

        System.out.println("name = " + name + ", price = " + price);

        return price;
    }

//    public int getPrice() {
//        return price;
//    }

}

 

test/java/hello/core/singleton/StatefulServiceTest.java

package hello.core.singleton;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class StatefulServiceTest {

    @Test
    void StatefulServiceSingleton() {

        ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);

        StatefulService statefulService1 = ac.getBean("statefulService", StatefulService.class);
        StatefulService statefulService2 = ac.getBean("statefulService", StatefulService.class);

        // TreadA : A์‚ฌ์šฉ์ž 10000์› ์ฃผ๋ฌธ
        int priceA = statefulService1.order("userA", 10000);

        // TreadB : B์‚ฌ์šฉ์ž 20000์› ์ฃผ๋ฌธ
        int priceB = statefulService2.order("userB", 20000);

        System.out.println("userA์˜ ์ฃผ๋ฌธ ๊ธˆ์•ก : " + priceA);

        assertThat(priceA).isEqualTo(10000);
    }

    public static class TestConfig {

        @Bean
        public StatefulService statefulService() {
            return new StatefulService();
        }
    }

}

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

05-5. @Configuration๊ณผ ์‹ฑ๊ธ€ํ†ค

๋‹ค์‹œ AppConfig๋กœ ๋Œ์•„๊ฐ€์„œ ์ด์ƒํ•œ ๋ถ€๋ถ„์„ ์ฐพ์•„๋ณด์ž.

 

main/java/hello/core/AppConfig.java

(์ƒ๋žต)

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

(์ƒ๋žต)
}

 

memberService ๋นˆ์„ ๋งŒ๋“ค ๋•Œ memberRepository()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

    -> memberRepository() ๋ฉ”์†Œ๋“œ๋Š” new MemoryMemberRepository()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

orderService ๋นˆ์„ ๋งŒ๋“ค ๋•Œ์—๋„ memberRepository()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

    -> memberRepository() ๋ฉ”์†Œ๋“œ๋Š” new MemoryMemberRepository()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

๋˜ ์ž์ฒด์ ์œผ๋กœ memberRepository ๋นˆ์„ ๋งŒ๋“œ๋Š” ๋ฉ”์†Œ๋“œ๋„ ์žˆ๋‹ค.

 

๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ฐ๊ฐ ๋‹ค๋ฅธ 3๊ฐœ์˜ MemoryMemberRepository๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด์„œ ์‹ฑ๊ธ€ํ†ค์ด ๊นจ์ง€๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค.

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ์„๊นŒ?

 

๊ฒ€์ฆ ์šฉ๋„์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ถ”๊ฐ€

main/java/hello/core/member/MemberServiceImpl.java

package hello.core.member;

public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

  (์ƒ๋žต)

    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
}

 

main/java/hello/core/order/OrderServiceImpl.java

package hello.core.order;

import hello.core.discount.DiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;

(์ƒ๋žต)

    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
}

 

ํ…Œ์ŠคํŠธ

test/java/hello/core/singleton/ConfigurationSingletonTest.java

package hello.core.singleton;

import hello.core.AppConfig;
import hello.core.member.MemberRepository;
import hello.core.member.MemberServiceImpl;
import hello.core.order.OrderServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;

public class ConfigurationSingletonTest {

    @Test
    public void configurationTest() {

        ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

        MemberServiceImpl memberService = ac.getBean(MemberServiceImpl.class);
        OrderServiceImpl orderService = ac.getBean(OrderServiceImpl.class);
        MemberRepository memberRepository = ac.getBean(MemberRepository.class);

        MemberRepository memberRepository1 = memberService.getMemberRepository();
        MemberRepository memberRepository2 = orderService.getMemberRepository();

        // ๋ชจ๋‘ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค.
        System.out.println("memberService -> memberRepository1 = " + memberRepository1);
        System.out.println("orderService -> memberRepository2 = " + memberRepository2);
        System.out.println("memberRepository = " + memberRepository);

        assertThat(memberRepository1).isSameAs(memberRepository2);
        assertThat(memberRepository2).isSameAs(memberRepository);
        assertThat(memberRepository).isSameAs(memberRepository1);
    }
}

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

 

 

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ์„ธ ๊ฐœ์˜ memberRepository ๋ชจ๋‘ ์ฐธ์กฐ๊ฐ’์ด ๊ฐ™์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, memberRepository์˜ ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ณต์œ ๋˜์–ด ์‚ฌ์šฉ๋œ๋‹ค.

 

AppConfig์— ํ˜ธ์ถœ ๋กœ๊ทธ ๋‚จ๊ธฐ๊ธฐ

main/java/hello/core/AppConfig.java

(์ƒ๋žต)

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        System.out.println("call AppConfig.orderService");
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {
        System.out.println("call AppConfig.memberRepository");
        return new MemoryMemberRepository();
    }

(์ƒ๋žต)
}

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฐ๊ฐ @Bean์„ ํ˜ธ์ถœํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์„ ์ƒ์„ฑํ•œ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด memberRepository()๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด 3๋ฒˆ์ด ํ˜ธ์ถœ๋œ๋‹ค.

 

    1. @Bean memberRepository() ํ˜ธ์ถœ

    2. memberService() ๋กœ์ง์—์„œ memberRepository() ํ˜ธ์ถœ

    3. orderService() ๋กœ์ง์—์„œ memberRepository() ํ˜ธ์ถœ

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋กœ๊ทธ๊ฐ€ ์ฐํž ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

call AppConfig.memberRepository
call AppConfig.memberService
call AppConfig.memberRepository
call AppConfig.orderService
call AppConfig.memberRepository
...

 

์‹ค์ œ ์ถœ๋ ฅ ๊ฒฐ๊ณผ

 

 

๊ทธ๋Ÿฐ๋ฐ ์‹ค์ œ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด call AppConfig.memberRepository ๋Š” 1๋ฒˆ๋งŒ ์ฐํ˜€์žˆ๋‹ค.

 

05-6. @Configuration๊ณผ ๋ฐ”์ดํŠธ์ฝ”๋“œ ์กฐ์ž‘์˜ ๋งˆ๋ฒ•

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์ด๋ฏ€๋กœ ์Šคํ”„๋ง ๋นˆ์ด ์‹ฑ๊ธ€ํ†ค์ด ๋˜๋„๋ก ๋ณด์žฅํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ ‡์ง€๋งŒ ์Šคํ”„๋ง์ด ์ž๋ฐ” ์ฝ”๋“œ๊นŒ์ง€ ์–ด๋–ป๊ฒŒ ํ•˜๊ธฐ๋Š” ํž˜๋“ค๋‹ค.

AppConfig์˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ๋งŒ ๋ดค์„ ๋•Œ์—๋Š” memberRepository()๋Š” ๋ถ„๋ช… ์ด 3๋ฒˆ์ด ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค.

๊ทธ๋ž˜์„œ ์Šคํ”„๋ง์€ ํด๋ž˜์Šค์˜ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋ชจ๋“  ๋น„๋ฐ€์€ @Configuration์„ ์ ์šฉํ•œ AppConfig์— ์žˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ์šฉ ์ฝ”๋“œ

test/java/hello/core/singleton/ConfigurationSingletonTest.java

@Test
public void configurationDeep() {

    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    // AppConfig๋„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.
    AppConfig bean = ac.getBean(AppConfig.class);

    System.out.println("bean.getClass() = " + bean.getClass());
}

 

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

๊ทธ๋ž˜์„œ AppConfig๋„ ์Šคํ”„๋ง ๋นˆ์ด ๋œ๋‹ค.

AppConfig ์Šคํ”„๋ง ๋นˆ์„ ์กฐํšŒํ•ด์„œ ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

bean.getClass() = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$b8933e89

 

์ˆœ์ˆ˜ํ•œ ํด๋ž˜์Šค๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

class hello.core.AppConfig

 

๊ทธ๋Ÿฐ๋ฐ ํด๋ž˜์Šค๋ช…์— xxxCGLIB๊ฐ€ ๋ถ™์œผ๋ฉด์„œ ์ƒ๋‹นํžˆ ๋ณต์žกํ•ด์ง„ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

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

 

์ด๋ฏธ์ง€ ์ถœ์ฒ˜ : ๊ฐ•์˜์ž๋ฃŒ

 

๊ทธ ์ž„์˜์˜ ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋กœ ์‹ฑ๊ธ€ํ†ค์ด ๋ณด์žฅ๋˜๋„๋ก ํ•ด์ค€๋‹ค.

CGLIB์˜ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์˜ˆ์ƒํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

 

AppConfig@CGLIB์˜ ์˜ˆ์ƒ ์ฝ”๋“œ

@Bean
public MemberRepository memberRepository() {
	
    if(memoryMemberRepository๊ฐ€ ์ด๋ฏธ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด?) {
    	return ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜;
    } else { 
    	// ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์—†์œผ๋ฉด ๊ธฐ์กด ๋กœ์ง์„ ํ˜ธ์ถœํ•ด์„œ MemoryMemberRepository๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก
        return ๋ฐ˜ํ™˜;
    }
}

 

@Bean์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ์ด๋ฏธ ์Šคํ”„๋ง ๋นˆ์ด ์กด์žฌํ•˜๋ฉด ์กด์žฌํ•˜๋Š” ๋นˆ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—†์œผ๋ฉด ์ƒ์„ฑํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ ํ›„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋™์ ์œผ๋กœ ๋งŒ๋“ค์–ด์ง„๋‹ค.

์ด ๋•๋ถ„์— ์‹ฑ๊ธ€ํ†ค์ด ๋ณด์žฅ๋œ๋‹ค.

 

(์ฐธ๊ณ ) AppConfig@CGLIB๋Š” AppConfig์˜ ์ž์‹ ํƒ€์ž…์ด๋ฏ€๋กœ AppConfig ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

@Configuration์„ ์ ์šฉํ•˜์ง€ ์•Š๊ณ , @Bean๋งŒ ์ ์šฉํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

main/java/hello/core/AppConfig.java

//@Configuration
public class AppConfig {

(์ƒ๋žต)

 

AppConfig์˜ @Configuration์„ ์‚ญ์ œํ•˜๊ณ  configurationDeep()์„ ๋˜‘๊ฐ™์ด ์‹คํ–‰ํ•ด๋ณด์ž.

 

bean.getClass() = class hello.core.AppConfig

 

@Configuration์„ ์‚ญ์ œํ•˜๋ฉด AppConfig๊ฐ€ CGLIB ๊ธฐ์ˆ ์—†์ด ์ˆœ์ˆ˜ํ•œ AppConfig๋กœ ์Šคํ”„๋ง ๋นˆ์— ๋“ฑ๋ก๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

๋˜ MemberRepository๊ฐ€ ์ด 3๋ฒˆ ํ˜ธ์ถœ๋œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ํ•œ ๋ฒˆ์€ @Bean์— ์˜ํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๊ณ , ๋‚˜๋จธ์ง€ ๋‘ ๋ฒˆ์€ ๊ฐ๊ฐ memberRepository()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด์„œ ๋ฐœ์ƒํ•œ ์ฝ”๋“œ๋‹ค.

 

์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด configurationTest()๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ด๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

 

๊ฐ๊ฐ ๋‹ค ๋‹ค๋ฅธ MemoryMemberRepository ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

 

์ •๋ฆฌ

    - @Bean๋งŒ ์‚ฌ์šฉํ•ด๋„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์ง€๋งŒ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

        -> memberRepository()์ฒ˜๋Ÿผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ํ•„์š”ํ•ด์„œ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ๋•Œ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

    - ์Šคํ”„๋ง ์„ค์ • ์ •๋ณด๋Š” ํ•ญ์ƒ @Configuration์„ ์‚ฌ์šฉํ•˜์ž.

 

๋ฐ˜์‘ํ˜•

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Claire's Study Note

Hi.Claire

ํ™œ๋™ํ•˜๊ธฐ