STUDY๐Ÿ„

[Spring ๊ธฐ๋ณธ] 3. ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ์ดํ•ด2- ๊ฐ์ฒด ์ง€ํ–ฅ ์›๋ฆฌ ์ ์šฉ

์ด๋ฆฌ์ญ 2025. 3. 26. 18:40

์•ˆ๋…•ํ•˜์„ธ์š”!

์ €๋ฒˆ ์„น์…˜์—์„œ ํ•˜๋˜ ๊ฒƒ์„ ์ด์–ด ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ…(์ •๋ฅ  ํ• ์ธ ์ •์ฑ…)์„ ๊ฐœ๋ฐœํ•ด๋ณด๊ณ  ์Šคํ”„๋ง์œผ๋กœ ์ „ํ™˜์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

๊ณ ๊ณ !!


1. ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ๊ฐœ๋ฐœ - ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…(RateDiscountPolicy)

์ €๋ฒˆ ์„น์…˜์—์„œ ํ–ˆ๋˜ ๊ฒƒ๋“ค์— ์ด์–ด ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ…์„ ํ™•์žฅํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

<์ƒํ™ฉ>

  • ์•…๋• ๊ธฐํš์ž: ์„œ๋น„์Šค ์˜คํ”ˆ ์ง์ „์— ํ• ์ธ ์ •์ฑ…์„ ์ง€๊ธˆ์ฒ˜๋Ÿผ ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์ด ์•„๋‹ˆ๋ผ ์ข€ ๋” ํ•ฉ๋ฆฌ์ ์ธ ์ฃผ๋ฌธ ๊ธˆ์•ก ๋‹น ํ• ์ธํ•˜๋Š” ์ •๋ฅ (%) ํ• ์ธ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
    ์˜ˆ๋ฅผ ๋“ค์–ด์„œ ๊ธฐ์กด ์ •์ฑ…์€ VIP๊ฐ€ 10,000์›์„ ์ฃผ๋ฌธํ•˜๋“  20,000์›์„ ์ฃผ๋ฌธํ•˜๋“  ํ•ญ์ƒ 1,000์›์„ ํ• ์ธํ–ˆ๋Š”๋ฐ, ์ด๋ฒˆ์— ์ƒˆ๋กœ ๋‚˜์˜จ ์ •์ฑ…์€ 10%๋กœ ์ง€์ •ํ•ด๋‘๋ฉด ๊ณ ๊ฐ์ด 10,000์› ์ฃผ๋ฌธ ์‹œ 1,000์›์„ ํ• ์ธํ•ด์ฃผ๊ณ , 20,000์› ์ฃผ๋ฌธ ์‹œ 2,000์›์„ ํ• ์ธํ•ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ์ˆœ์ง„ ๊ฐœ๋ฐœ์ž: ์ œ๊ฐ€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ์€ ์•„๋‹ˆ๋ผ๊ณ  ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ..
  • ์•…๋• ๊ธฐํš์ž: ์• ์ž์ผ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ์„ ์–ธ ๋ชจ๋ฆ…๋‹ˆ๊นŒ? ๊ณ„ํš์„ ๋”ฐ๋ฅด๊ธฐ๋ณด๋‹ค ๋ณ€ํ™”์— ๋Œ€์‘ํ•˜๊ธฐ๋ฅผ...
  • ์ˆœ์ง„ ๊ฐœ๋ฐœ์ž: ... (ํ•˜์ง€๋งŒ ๋‚œ ์œ ์—ฐํ•œ ์„ค๊ณ„๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„ ์›์น™์„ ์ค€์ˆ˜ํ–ˆ์ง€ ํ›„ํ›„)
์• ์ž์ผ ์†Œํ”„ํŠธ์›จ์–ด ๊ฐœ๋ฐœ ์„ ์–ธ

๊ณต์ •๊ณผ ๋„๊ตฌ๋ณด๋‹ค ๊ฐœ์ธ๊ณผ ์ƒํ˜ธ์ž‘์šฉ์„
ํฌ๊ด„์ ์ธ ๋ฌธ์„œ๋ณด๋‹ค ์ž‘๋™ํ•˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด๋ฅผ
๊ณ„์•ฝ ํ˜‘์ƒ๋ณด๋‹ค ๊ณ ๊ฐ๊ณผ์˜ ํ˜‘๋ ฅ์„
๊ณ„ํš์„ ๋”ฐ๋ฅด๊ธฐ๋ณด๋‹ค ๋ณ€ํ™”์— ๋Œ€์‘ํ•˜๊ธฐ๋ฅผ

 

์ˆœ์ง„ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ •๋ง ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„ ์›์น™์„ ์ž˜ ์ค€์ˆ˜ํ–ˆ์„๊นŒ์š”?

๊ทธ๋ฆฌ๊ณ , ์ด๋ฒˆ์—๋Š” ์ฃผ๋ฌธํ•œ ๊ธˆ์•ก์˜ %๋ฅผ ํ• ์ธํ•ด์ฃผ๋Š” ์ƒˆ๋กœ์šด ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์„ ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

RateDiscountPolicy ์ถ”๊ฐ€

 

์šฐ์„  ์„น์…˜2์—์„œ ํ–ˆ๋˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ์ผœ์„œ ๊ธฐ์กด์— ๋งŒ๋“ค์—ˆ๋˜ discount๋ผ๋Š” ํŒจํ‚ค์ง€์— RateDiscountPolicy๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

DiscountPolicy๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ๊ตฌํ˜„์ฒด์ด๋ฏ€๋กœ ์ „์—๋ž‘ ๋˜‘๊ฐ™์ด implements๋ฅผ ํ•˜๊ณ  Alt + Enter๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„(์˜ค๋ฒ„๋ผ์ด๋“œ)์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class RateDiscountPolicy implements DiscountPolicy{
    
    private int discountPercent = 10; //10% ํ• ์ธ

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return price * discountPercent /100;
        }
        else {
            return 0;
        }
    }
}

10% ํ• ์ธ์ด๋ฏ€๋กœ private int discountPercent = 10;์ด๋ž€ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ, VIP ๋“ฑ๊ธ‰๋งŒ ํ• ์ธ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ if๋ฌธ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทผ๋ฐ ์ด ์‹... ๊ณผ์—ฐ ์ž˜ ๋˜๋Š” ๊ฑธ๊นŒ์š”?

ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ „์—์ฒ˜๋Ÿผ ์ผ์ผ์ด ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ๋งŒ๋“ค๊ณ  ํ•˜๊ธฐ ํž˜๋“ค์ž–์•„์š”.

๊ทธ๋ž˜์„œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ด์šฉํ•ด๋ณผ๊ฒŒ์š”.

์œˆ๋„์šฐ๋Š” ctrl + shift + t, ๋งฅ์€ command + shift + t๋ฅผ ๋ˆ„๋ฅด๋ฉด 

์˜์–ด๋กœ ๋˜์–ด์žˆ์œผ๋ฉด Create New Test๋กœ ๋œฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋œน๋‹ˆ๋‹ค. ์ƒˆ ํ…Œ์ŠคํŠธ ์ƒ์„ฑ์„ ๋ˆŒ๋Ÿฌ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋Š” JUnit5๋กœ ๋†”๋‘๊ณ  ํด๋ž˜์Šค ์ด๋ฆ„์€ ๊ธฐ์กด์˜ RateDiscountPolicy์—์„œ ๋’ค์— Test๋ฅผ ๋ถ™ํž™๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๊ณ  ๋ฐ‘์— ๊ฑฐ๋Š” ์•„๋ฌด๊ฒƒ๋„ ๊ฑด๋“ค์ง€ ์•Š๊ณ , ํ™•์ธ์„ ๋ˆ„๋ฅด๋ฉด ์ƒˆ๋กœ์šด ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค ์ƒ์„ฑ๋œ๊ฑฐ ๋ณด์ด์‹œ๋‚˜์š”?

๊ทธ๋Ÿผ ์—ฌ๊ธฐ์„œ ํ…Œ์ŠคํŠธ๋ฌธ์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class RateDiscountPolicyTest {

    RateDiscountPolicy discountPolicy = new RateDiscountPolicy();

    @Test
    @DisplayName("VIP๋Š” 10% ํ• ์ธ์ด ์ ์šฉ๋˜์–ด์•ผ ํ•œ๋‹ค.") //ํ•œ๊ธ€๋กœ ์ด๋ฆ„์„ ์“ธ ์ˆ˜ ์žˆ์Œ
    void vip_o() {
        //given //ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ฐ–์ถ”๋Š” ๋‹จ๊ณ„, ์ด๋Ÿฐ ํ™˜๊ฒฝ์ด ์ฃผ์–ด์กŒ์„ ๋•Œ
        Member member = new Member(1L, "memberVIP", Grade.VIP);

        //when //ํ…Œ์ŠคํŠธ ํ•  ์ƒํ™ฉ์„ ์ง„ํ–‰ํ•˜๋Š” ๋‹จ๊ณ„, ์ด๋ ‡๊ฒŒ ํ–ˆ์„ ๋•Œ
        int discount = discountPolicy.discount(member, 10000);

        //then //์˜ˆ์ƒํ•œ ๋Œ€๋กœ ์ž˜ ์ž‘๋™ํ–ˆ๋Š”์ง€ ํ…Œ์ŠคํŠธ, ์ด๋ ‡๊ฒŒ ๋œ๋‹ค
        Assertions.assertThat(discount).isEqualTo(1000);
    }

}

@Test๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ…Œ์ŠคํŠธ๋ฌธ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , @DisplayName("aa")์€ JUnit5 ์ด์ƒ๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š”๋ฐ, ""์•ˆ์— ๋“ค์–ด๊ฐ€์žˆ๋Š” ์„ค๋ช…(์ด๋ฆ„)์ด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋ฐ‘์— ๋œน๋‹ˆ๋‹ค.

ํ•œ๊ธ€๋กœ ์ด๋ฆ„์„ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๋˜‘๊ฐ™์ด given, when, then์„ ํ•ด์ค„๊ฑด๋ฐ์š”.

  • Member member = new Member(1L, "memberVIP", Grade.VIP);
    • ํ…Œ์ŠคํŠธ ์ „ "memberVIP"๋ผ๋Š” ๋ฉค๋ฒ„ํ˜• ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ํšŒ์› ๊ฐ€์ž… ์ „์— ํšŒ์› ๊ฐ€์ž… ์ฐฝ์— ํšŒ์›์˜ ์ •๋ณด๋“ค์„ ์ ์–ด๋†“๊ธฐ๋งŒ ํ•œ ์ƒํƒœ์™€ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.
  • int discount = discountPolicy.discount(member, 10000);
    • VIP ๋“ฑ๊ธ‰์ธ ์ด ํšŒ์›์ด 10,000์›์งœ๋ฆฌ ๋ฌผ๊ฑด์„ ๊ตฌ์ž…ํ–ˆ์„ ๋•Œ ํ• ์ธ๋˜๋Š” ๊ธˆ์•ก์„ int ๋ณ€์ˆ˜๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • Assertions.assertThat(discount).isEqualTo(1000);
    • Assertions๋Š” JUnit์—์„œ ์ œ๊ณตํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋“ค์˜ ์ง‘ํ•ฉ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
      ๊ทธ ์ค‘ ์ €ํฌ๋Š” ๋น„๊ต ๋Œ€์ƒ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” assertThat()์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • ์ €ํฌ๋Š” 2๋ฒˆ์งธ when์—์„œ ๋‚˜์˜จ ๋ณ€์ˆ˜ discount๋ฅผ ๋น„๊ต ๋Œ€์ƒ์— ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ•ด๋‹น ๋ณ€์ˆ˜(ํ• ์ธ๋˜๋Š” ๊ธˆ์•ก)๊ฐ€ 1000์ด ๋งž์•„์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@DisplayName์„ ํ†ตํ•ด ์ด๋ฆ„์ด ๋œจ๊ณ , ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋‹ค๊ณ  ๋œน๋‹ˆ๋‹ค.

์œ„์˜ โœ”๏ธํ‘œ์‹œ ์•ˆ ๋ˆ„๋ฅด๋ฉด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ ๋ฐ‘์— ์žˆ๋Š” ๋‚ด์šฉ ์•ˆ ๋œจ๋”๋ผ๊ตฌ์š”. ์ €๋งŒ ๊ทธ๋Ÿฐ๊ฑด์ง€ ๋ชจ๋ฅด๊ฒ ๋Š”๋ฐ ์•”ํŠผ ์•ˆ ๋‚˜์˜ค๋ฉด ์ € ์ฒดํฌ ํ‘œ์‹œ ๋ˆŒ๋Ÿฌ๋ณด์„ธ์š”. ๋‚˜์˜ฌ ๊ฒ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ๊ฑด ํ…Œ์ŠคํŠธ๋ฌธ์€ ๊ผญ ์‹คํŒจํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฌธ๋„ ๋งŒ๋“ค์–ด๋ด์•ผํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‹คํŒจํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฌธ๋„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

@Test
    @DisplayName("VIP๊ฐ€ ์•„๋‹ˆ๋ฉด ํ• ์ธ์ด ์ ์šฉ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.")
    void vip_x() {
        //given
        Member member = new Member(2L, "memberBASIC", Grade.BASIC);

        //when
        int discount = discountPolicy.discount(member, 10000);

        //then
        Assertions.assertThat(discount).isEqualTo(1000);
    }

์•„๊นŒ ํ…Œ์ŠคํŠธ๋ฌธ๊ณผ ์ฝ”๋“œ๋Š” ๋น„์Šทํ•œ๋ฐ VIP๊ฐ€ ์•„๋‹ˆ์–ด์•ผ ํ•˜๋ฏ€๋กœ ๋“ฑ๊ธ‰๊ณผ ์ด๋ฆ„์„ BASIC์œผ๋กœ ๋ฐ”๊ฟ”๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌ๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‚˜์˜ฌ๊นŒ์š”?

์ด๋ ‡๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋œน๋‹ˆ๋‹ค.

๋ถ„๋ช… ๊ธฐ๋Œ€ํ•œ ๊ฐ’์€ 1,000์ธ๋ฐ ์‹ค์ œ๋กœ๋Š” 0์ด ๋‚˜์™€์„œ ์˜ค๋ฅ˜๊ฐ€ ๋–ด๋‹ค๊ณ  ๋‚˜์™€์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์ด ํ…Œ์ŠคํŠธ๋ฌธ๋„ ํ…Œ์ŠคํŠธ ์„ฑ๊ณตํ•˜๋„๋ก ๋ฐ”๊ฟ”๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Assertions.assertThat(discount).isEqualTo(1000);

์ด ๋ฌธ์žฅ์—์„œ 1000์„ 0์œผ๋กœ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฐ”๊พผ ์ƒํƒœ์—์„œ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ์—” ํ…Œ์ŠคํŠธ๋ฌธ 2๊ฐœ๋ฅผ ํ•œ ๋ฒˆ์— ๋Œ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์—ญ์‹œ๋‚˜ ๋‘˜ ๋‹ค ์„ฑ๊ณตํ•œ๋‹ค๊ณ  ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

์ค‘์š”ํ•œ ๊ฒƒ์ด ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, ์œ„์— ํ…Œ์ŠคํŠธ๋ฌธ์—์„œ Assertions ์ชฝ์—์„œ ์œˆ๋„์šฐ ๊ธฐ์ค€ Alt + Enter (๋งฅ์€ ์˜ต์…˜ + Enter) ๋ˆ„๋ฅด๊ณ 

์‚ฌ์ง„์ฒ˜๋Ÿผ static import ๋ˆ„๋ฅด๋ฉด

Assertions๊ฐ€ ์‚ฌ๋ผ์ง€๊ณ  ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง‘๋‹ˆ๋‹ค.

๋˜ํ•œ, ์œ„์˜ import๋ฌธ์—์„œ import static org.assertj.core.api.Assertions.*;์ด ์ƒ๊น๋‹ˆ๋‹ค.

static import๋Š” ์ž๋ฐ” ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์ž…๋‹ˆ๋‹ค.


2. ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ์ ์šฉ๊ณผ ๋ฌธ์ œ์  - ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…(RateDiscountPolicy)์œผ๋กœ ๋ณ€๊ฒฝ

๋ฐฉ๊ธˆ ์ถ”๊ฐ€ํ•œ ํ• ์ธ ์ •์ฑ…์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ• ์ธ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl ์ฝ”๋“œ๋ฅผ ๊ณ ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

public class OrderServiceImpl implements OrderService{
	...
    //private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
...
}

์›๋ž˜๋Š” ์ •์•ก ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋˜์–ด์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— FixDiscountPolicy๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋Š”๋ฐ, ์ด์ œ ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์œผ๋กœ ์ ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— FixDiscountPolicy ์ž๋ฆฌ์— RateDiscountPolicy๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ ํ–ˆ๋Š”๋ฐ ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

<๋ฌธ์ œ์  ๋ฐœ๊ฒฌ>

1. ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ์ถฉ์‹คํ•˜๊ฒŒ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. -> OK
2. ๋‹คํ˜•์„ฑ๋„ ํ™œ์šฉํ•˜๊ณ , ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. -> OK

3. OCP, DIP ๊ฐ™์€ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„ ์›์น™์„ ์ถฉ์‹คํžˆ ์ค€์ˆ˜ํ–ˆ์Šต๋‹ˆ๋‹ค. -> ๊ทธ๋ ‡๊ฒŒ ๋ณด์ด์ง€๋งŒ ์‚ฌ์‹ค์€ X

3-1(์ค‘์š”). DIP: ์ฃผ๋ฌธ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ(OrderServiceImpl)๋Š” DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ฉด์„œ DIP๋ฅผ ์ง€ํ‚จ ๊ฒƒ ๊ฐ™์€๋ฐ์š”..?
-> ํด๋ž˜์Šค ์˜์กด ๊ด€๊ณ„๋ฅผ ๋ถ„์„ํ•ด๋ณด๋ฉด... ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค) ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ตฌ์ฒด(๊ตฌํ˜„) ํด๋ž˜์Šค์—๋„ ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
--> ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค) ์˜์กด: DiscountPolicy
--> ๊ตฌ์ฒด(๊ตฌํ˜„) ํด๋ž˜์Šค: FixDiscountPolicy, RateDiscountPolicy

3-2(์ค‘์š”). OCP: ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ์š”..?
--> ์ง€๊ธˆ ์ฝ”๋“œ๋Š” ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•ด์„œ ๋ณ€๊ฒฝํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ค๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, OCP๋ฅผ ์œ„๋ฐ˜ํ•ฉ๋‹ˆ๋‹ค.

์™œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ• ๊นŒ์š”?

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์œผ๋กœ ์˜์กด๊ด€๊ณ„๋ฅผ ๋ถ„์„ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

  • ๊ธฐ๋Œ€ํ–ˆ๋˜ ์˜์กด๊ด€๊ณ„

์ง€๊ธˆ๊นŒ์ง€ ๋‹จ์ˆœํžˆ DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์˜์กดํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

  • ์‹ค์ œ ์˜์กด๊ด€๊ณ„

๊ทผ๋ฐ ์‹ค์ œ๋กœ ๊นŒ ๋ณด๋ฉด ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl์ด DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ

FixDiscountPolicy์ธ ๊ตฌ์ฒด ํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ์˜์กดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์˜์กดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. DIP ์œ„๋ฐ˜!!

 

  • ์ •์ฑ… ๋ณ€๊ฒฝ

๊ทธ๋ž˜์„œ, FixDiscountPolicy๋ฅผ RateDiscountPolicy๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ์ˆœ๊ฐ„, OrderServiceImpl์˜ ์†Œ์Šค ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. OCP ์œ„๋ฐ˜!!

Q. ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

A. ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์ธ OrderServiceImpl์€ DiscountPolicy์˜ ์ธํ„ฐํŽ˜์ด์Šค ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ตฌ์ฒด ํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ, ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค,

๊ทผ๋ฐ ์ด๋Ÿฌ๋ฉด DIP ์œ„๋ฐ˜์ด๋ฏ€๋กœ, ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค)์—๋งŒ ์˜์กดํ•˜๋„๋ก ์˜์กด๊ด€๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ์„ค๊ณ„์™€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ์„ค๊ณ„๋ฅผ ๋ณ€๊ฒฝ

public class OrderServiceImpl implements OrderService{
	...
    //private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    private DiscountPolicy discountPolicy;
...
}

์ด๋ ‡๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ์„ค๊ณ„์™€ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด OrderServiceImpl์—์„œ ์‚ฌ์šฉํ•  discountPolicy๊ฐ€ ์ •์•ก ํ• ์ธ ์ •์ฑ…์ผ์ง€ ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์ผ์ง€ ์ง€์ •๋˜์–ด ์žˆ์ง€ ์•Š๊ณ , ์•„์˜ˆ ๊ฐ’์„ ๋„ฃ์ง€ ์•Š๋‹ค๋ณด๋‹ˆ null ๊ฐ’์ด ๋“ค์–ด๊ฐ”์Šต๋‹ˆ๋‹ค. (=ํ•˜๊ณ  ๋’ค์— ๋ญ”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์—)

์‹ค์ œ๋กœ ์‹คํ–‰์„ ํ•ด๋ณด๋ฉด NPE(Null Pointer Exception)๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

NPE๊ฐ€ ์™œ ํ„ฐ์กŒ์„๊นŒ์š”?

public class OrderServiceTest {

    MemberService memberService = new MemberServiceImpl();
    OrderService orderService = new OrderServiceImpl();

    @Test
    void createOrder() {
        Long memberId = 1L;
        Member member = new Member(memberId, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "์ดˆ์ฝœ๋ฆฟ", 10000);
        Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
    }
}

ํ˜„์žฌ OrderServiceTest ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ํ•จ์ˆ˜์ธ createOrder()์—์„œ .createOrder ํ•จ์ˆ˜๊ฐ€ ์–ด๋””์—์„œ ์“ฐ์˜€๋Š”์ง€ ํ•œ ๋ฒˆ ๋“ค์–ด๊ฐ€๋ณผ๊ฒŒ์š”.

public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private DiscountPolicy discountPolicy;
    
    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

OrderServiceImpl์—์„œ ์‚ฌ์šฉ์ด ๋˜์—ˆ๋˜ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ int discountPrice = discountPolicy.discount(member, itemPrice);๊ฐ€ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๋ฐ‘์—์„  discountPolicy๊ฐ€ ๋ถ„๋ช… ์‚ฌ์šฉ๋˜์—ˆ๋Š”๋ฐ ์•„๊นŒ ์ €ํฌ๊ฐ€ ์ผ๋˜ ๋ฌธ์žฅ์„ ๋ณด๋ฉด discountPolicy๊ฐ€ null์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl์— DiscountPolicy์˜ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ์ƒ์„ฑํ•˜๊ณ  ์ฃผ์ž…ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

=> ์ง€๊ธˆ ํ˜„์žฌ๊นŒ์ง€์˜ ์ƒํ™ฉ: DIP๋Š” ์ง€์ผฐ์œผ๋‚˜, NPE๊ฐ€ ํ„ฐ์ง. 


3. ๋ฌธ์ œ์  ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• - ์ •๋ฅ  ํ• ์ธ ์ •์ฑ… ์žˆ๊ธฐ ์ „

์œ„์—์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํด๋ผ์ด์–ธํŠธ์ธ OrderServiceImpl์— DiscountPolicy์˜ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ๋Œ€์‹  ์ƒ์„ฑํ•ด์ฃผ๊ณ  ์ฃผ์ž…ํ•ด์ค˜์•ผ ํ•œ๋‹ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ๋ถ€ํ„ฐ ์ด ์—ญํ• ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•˜๊ณ  ์ ์šฉํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

3-1. ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํ•˜๋‚˜์˜ ๊ณต์—ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๊ฐ๊ฐ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐฐ์—ญ(๋ฐฐ์šฐ ์—ญํ• )์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์‹ค์ œ ๋ฐฐ์—ญ ๋งž๋Š” ๋ฐฐ์šฐ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ๋ˆ„๊ฐ€ ํ• ๊นŒ์š”?

 

๋กœ๋ฏธ์˜ค์™€ ์ค„๋ฆฌ์—ฃ ๊ณต์—ฐ์„ ํ•˜๋ฉด ๋กœ๋ฏธ์˜ค ์—ญํ• ์„ ๋ˆ„๊ฐ€ ํ• ์ง€ ์ค„๋ฆฌ์—ฃ ์—ญํ• ์„ ๋ˆ„๊ฐ€ ํ• ์ง€๋Š” ๋ฐฐ์šฐ๋“ค์ด ์ •ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋ฐฐ์šฐ๊ฐ€ ์—ฐ๊ธฐ๋„ ํ•˜๊ณ  ์—ฐ๊ธฐํ•  ์‚ฌ๋žŒ๋„ ๊ตฌํ•˜๊ณ  ์ด ๋ชจ๋“  ๊ฒƒ์„ ๋‹ค ํ•  ์ˆ˜๋Š” ์—†๊ฒ ์ฃ .

 

์ด์ „ ์ฝ”๋“œ๋Š” ๋งˆ์น˜ ๋กœ๋ฏธ์˜ค ์—ญํ• (์ธํ„ฐํŽ˜์ด์Šค)์„ ํ•˜๋Š” ๋ณ€์šฐ์„(๊ตฌํ˜„์ฒด, ๋ฐฐ์šฐ)์ด ์ค„๋ฆฌ์—ฃ ์—ญํ• (์ธํ„ฐํŽ˜์ด์Šค)์„ ํ•˜๋Š” ์—ฌ์ž ์ฃผ์ธ๊ณต(๊ตฌํ˜„์ฒด, ๋ฐฐ์šฐ)์„ ์ง์ ‘ ์ดˆ๋น™ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ณ€์šฐ์„์€ ๊ณต์—ฐ๋„ ํ•ด์•ผ ํ•˜๊ณ  ๋™์‹œ์— ์—ฌ์ž ์ฃผ์ธ๊ณต๋„ ๊ณต์—ฐ์— ์ง์ ‘ ์ดˆ๋น™ํ•ด์•ผ ํ•˜๋Š” "๋‹ค์–‘ํ•œ ์ฑ…์ž„"์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

private DiscountPolicy discountPolicy = new FixDiscountPolicy();

์ด ์ฝ”๋“œ๊ฐ€ ์ง์ ‘ ์ดˆ๋น™ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

์ด์ „ ์ฝ”๋“œ์ธ๋ฐ OrderServiceImpl์—์„œ๋Š” OrderService์™€ ๊ด€๋ จ๋œ ๋กœ์ง๋งŒ ํ•ด์•ผํ•˜๋Š”๋ฐ, ์–˜๊ฐ€ DiscountPolicy๋Š” FixDiscountPolicy๋ฅผ ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ง์ ‘ ์„ ํƒํ•˜๋Š” ๋“ฑ ๊ตฌ์ฒด์ ์ธ ๊ฒƒ๊นŒ์ง€ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

<๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌ!!>

- ๋ฐฐ์šฐ๋Š” ๋ณธ์ธ์˜ ์—ญํ• ์ธ ๋ฐฐ์—ญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์—๋งŒ ์ง‘์ค‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
- ๋ณ€์šฐ์„์€ ์–ด๋˜ ์—ฌ์ž ์ฃผ์ธ๊ณต์ด ์„ ํƒ๋˜๋”๋ผ๋„ ๋˜‘๊ฐ™์ด ๊ณต์—ฐ์„ ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
- ๊ณต์—ฐ์„ ๊ตฌ์„ฑํ•˜๊ณ , ๋‹ด๋‹น ๋ฐฐ์šฐ๋ฅผ ์„ญ์™ธํ•˜๊ณ , ์—ญํ• ์— ๋งž๋Š” ๋ฐฐ์šฐ๋ฅผ ์ง€์ •ํ•˜๋Š” ์ฑ…์ž„์„ ๋‹ด๋‹นํ•˜๋Š” ๋ณ„๋„์˜ "๊ณต์—ฐ ๊ธฐํš์ž"๊ฐ€ ๋‚˜์˜ฌ ์‹œ์ ์ž…๋‹ˆ๋‹ค.
- ๊ณต์—ฐ ๊ธฐํš์ž๋ฅผ ๋งŒ๋“ค๊ณ , ๋ฐฐ์šฐ์™€ ๊ณต์—ฐ ๊ธฐํš์ž์˜ ์ฑ…์ž„์„ ํ™•์‹คํžˆ ๋ถ„๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

3-2. AppConfig ๋“ฑ์žฅ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ „์ฒด ๋™์ž‘ ๋ฐฉ์‹์„ ๊ตฌ์„ฑ(Config)ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ์ฑ…์ž„์„ ๊ฐ–๋Š” ๋ณ„๋„์˜ ์„ค์ • ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์œ„์—์„œ ์–˜๊ธฐํ•œ ๊ณต์—ฐ ๊ธฐํš์ž ๊ฐ™์€ ์—ญํ• ์ž…๋‹ˆ๋‹ค.

 

ํ•œ ๋ฒˆ ์—ญํ•  ๋งŒ๋“ค์–ด๋ณด๊ณ  ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์šฐ์„  ์ „์ฒด ๋™์ž‘ ๋ฐฉ์‹์„ ๊ตฌ์„ฑํ•˜๋Š” AppConfig๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ hello ํด๋” ์•ˆ์˜ core ํŒจํ‚ค์ง€ ์•ˆ์— ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์ œ hello ํด๋” ์•ˆ์˜ core ํŒจํ‚ค์ง€ ์•ˆ์ด๋ž€ ๋ง์„ hello.core๋กœ ์ค„์—ฌ์„œ ์–˜๊ธฐํ• ๊ฒŒ์š”.

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl();
    }
    ...
}

AppConfig๊ฐ€ ๋Œ€์‹  ์ „์ฒด์ ์ธ ์ž‘์—…์„ ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด๋†“์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ผ๋‹จ MemberServiceImpl๋กœ ๋Œ์•„๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

private final MemberRepository memberRepository = new MemoryMemberRepository();

์ด ์ฝ”๋“œ๋Š” MemberServiceImpl์ด ๋„ˆ๋ฌด ์˜ค์ง€๋ผํผ...ใ…Ž

๊ทธ๋ž˜์„œ ์ € ๋’ค์˜ new MemoryMemberRepository()๋Š” ์ง€์›๋‹ˆ๋‹ค. AppConfig์—์„œ ์ด๋Ÿฐ๊ฑด ๋‹ค ํ• ๊ฑฐ๋‹ˆ๊นŒ์š”!

 

๊ทธ๋ฆฌ๊ณ  MemberServiceImpl์— ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์ด MemberRepository์˜ ๊ตฌํ˜„์ฒด๊ฐ€ ๋ญ๊ฐ€ ๋“ค์–ด๊ฐˆ์ง€๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์•„๊นŒ ๋งŒ๋“ค์—ˆ๋˜ AppConfig ํด๋ž˜์Šค๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

์—ฌ๊ธฐ์—์„œ MemberServiceImpl์˜ MemoryMemberRepository๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

์–ด๋””์„ ๊ฐ€ AppConfig๋ฅผ ํ†ตํ•ด์„œ memberService()๋ฅผ ๋ถˆ๋Ÿฌ์„œ ์”๋‹ˆ๋‹ค.

์ด๋Ÿฌ๋ฉด MemberService ๊ตฌํ˜„์ฒด ๊ฐ์ฒด(MemberServiceImpl)๊ฐ€ ์ƒ์„ฑ๋˜๊ฒŒ ๋˜๋Š”๋ฐ ๊ทธ ๋•Œ MemoryMemberRepository๊ฐ€ 

 

MemverServiceImpl์—๋Š” MemoryMemberRepository์— ๋Œ€ํ•œ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‚˜์š”?

์—†๊ณ , ์˜ค๋กœ์ง€ MemberRepository๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์ด์ œ MemberServiceImpl์€ ์ถ”์ƒํ™”์—๋งŒ ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

DIP๋ฅผ ์ง€ํ‚ค๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๊ณ , ์ด์ œ MemberServiceImpl์€ ๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ์€ ๋ชจ๋ฅด๊ฒŒ ๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด๋Ÿฐ ๊ฒƒ์„ "์ƒ์„ฑ์ž์˜ ์ฃผ์ž…"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

OrderService๋„ ์œ„์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

AppConfig์—์„œ ์œ„์— ์ฒ˜๋Ÿผ ์ด ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

public class AppConfig {
	...
    public OrderService orderService() {
        return new OrderServiceImpl();
    }
}

์œ„์—์ฒ˜๋Ÿผ ๋˜‘๊ฐ™์ด ์ƒ์„ฑ์ž์˜ ์ฃผ์ž…์„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

OrderServiceImpl ํด๋ž˜์Šค๋กœ ๋Œ์•„๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

์—ฌ๊ธฐ์—์„  ์‚ฌ์šฉํ•˜๋Š” ํ•„๋“œ๊ฐ€ 2๊ฐœ์˜€์Šต๋‹ˆ๋‹ค.

์œ„์—์ฒ˜๋Ÿผ new ์ง์ ‘ ํ• ๋‹น์„ ๊ณผ๊ฐํžˆ ์ง€์šฐ๊ณ , ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
    ...
}

final์ด ๋˜์–ด์žˆ์œผ๋ฉด ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ํ• ๋‹น์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ AppConfig๋กœ ๋Œ์•„๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public OrderService orderService() {
        return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
    }

์•„๊นŒ์ฒ˜๋Ÿผ AppConfig๊ฐ€ OrderServiceImpl์˜ MemoryMemberRepository์™€ FixDiscountPolicy๋ฅผ ์ง์ ‘ ํ• ๋‹นํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ์œ„์—์ฒ˜๋Ÿผ DIP๋ฅผ ์ฒ ์ €ํ•˜๊ฒŒ ์ง€ํ‚ค๊ฒŒ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

OrderServiceImpl ์ž…์žฅ์—์„œ๋Š” discountPolicy์— FixDiscountPolicy๊ฐ€ ๋“ค์–ด์˜ฌ์ง€ RateDiscountPolicy๊ฐ€ ๋“ค์–ด์˜ฌ์ง€ ๋ชจ๋ฅด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค์ธ OrderService์—๋งŒ ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด์ฃ .

โœ๏ธ๋งค์šฐ ์ค‘์š”ํ•œ ๋‚ด์šฉ์ด๊ธฐ์— ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ •๋ฆฌ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.โœ๏ธ

public class AppConfig {

    public MemberService memberService() {
        return new MemberServiceImpl(new MemoryMemberRepository());
    }
    public OrderService orderService() {
        return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
    }
}
<์ •๋ฆฌ1 - AppConfig>

1. AppConfig๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹ค์ œ ๋™์ž‘์— ํ•„์š”ํ•œ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
- MemberServiceImpl
- MemoryMemberRepository
- OrderServiceImpl
- FixDiscountPolicy

2. AppConfig๋Š” ์ƒ์„ฑํ•œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ(๋ ˆํผ๋Ÿฐ์Šค)๋ฅผ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์ฃผ์ž…(์—ฐ๊ฒฐ)ํ•ด์ค๋‹ˆ๋‹ค.
- MemberServiceImpl -> MemoryMemberRepository
- OrderServiceImpl -> MemoryMemberRepository, FixDiscountPolicy

์ฐธ๊ณ !!
์ง€๊ธˆ์€ ๊ฐ ํด๋ž˜์Šค์— ์ƒ์„ฑ์ž๊ฐ€ ์—†์–ด์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋กœ ๋‹ค์Œ ์ฝ”๋“œ์—์„œ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

 

public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;

    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}
<์ •๋ฆฌ2 - MemberServiceImpl ์ƒ์„ฑ์ž ์ฃผ์ž…>

1. ์„ค๊ณ„ ๋ณ€๊ฒฝ์œผ๋กœ MemberServiceImpl์€ MemoryMemberRepository๋ฅผ ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    ๋‹จ์ง€ MemberRepository ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.
2. MemberServiceImpl ์ž…์žฅ์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด์˜ฌ์ง€(์ฃผ์ž…๋ ์ง€)๋Š” ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
3. MemberServiceImpl์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ• ์ง€๋Š” ์˜ค์ง ์™ธ๋ถ€(AppConfig)์—์„œ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
4. MemberServiceImpl์€ ์ด์ œ๋ถ€ํ„ฐ ์˜์กด ๊ด€๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์€ ์™ธ๋ถ€์— ๋งก๊ธฐ๊ณ  ์‹คํ–‰์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

<์ •๋ฆฌ3 - ํšŒ์› ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ>

1. ๊ฐ์ฒด์˜ ์ƒ์„ฑ๊ณผ ์—ฐ๊ฒฐ์€ AppConfig๊ฐ€ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
2. DIP ์™„์„ฑ: MemberServiceImpl์€ MemberRepository์ธ ์ถ”์ƒ์—๋งŒ ์˜์กดํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
                    ์ด์ œ ๊ตฌ์ฒด ํด๋ž˜์Šค๋Š” ๋ชฐ๋ผ๋„ ๋ฉ๋‹ˆ๋‹ค.
3. ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ: ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• ๊ณผ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์ด ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

ํšŒ์› ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

<์ •๋ฆฌ4 - ํšŒ์› ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ๋‹ค์ด์–ด๊ทธ๋žจ>

1. appConfig ๊ฐ์ฒด๋Š” memoryMemberRepository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ์ฐธ์กฐ๊ฐ’์„ memberServiceImpl์„ ์ƒ์„ฑํ•˜๋ฉด์„œ ์ƒ์„ฑ์ž๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
2. ํด๋ผ์ด์–ธํŠธ์ธ memberServiceImpl ์ž…์žฅ์—์„œ ๋ณด๋ฉด ์˜์กด ๊ด€๊ณ„๋ฅผ ๋งˆ์น˜ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ํ•ด์„œ DI(Dependency Injection) ์ฆ‰, ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋˜๋Š” ์˜์กด์„ฑ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

 

<์ •๋ฆฌ1 - OrderServiceImpl ์ƒ์„ฑ์ž ์ฃผ์ž…>

1. ์„ค๊ณ„ ๋ณ€๊ฒฝ์œผ๋กœ OrderServiceImpl์€ FixDiscountPolicy๋ฅผ ์˜์กดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    ๋‹จ์ง€ DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•ฉ๋‹ˆ๋‹ค.
2. OrderServiceImpl ์ž…์žฅ์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด์˜ฌ์ง€(์ฃผ์ž…๋ ์ง€)๋Š” ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
3. OrderServiceImpl์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ• ์ง€๋Š” ์˜ค์ง ์™ธ๋ถ€(AppConfig)์—์„œ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
4. OrderServiceImpl์€ ์ด์ œ๋ถ€ํ„ฐ ์‹คํ–‰์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
5. OrderServiceImpl์—๋Š” MemoryMemberRepository, FixDiscountPolicy ๊ฐ์ฒด์˜ ์˜์กด ๊ด€๊ณ„๊ฐ€ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.

AppConfig๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์— ๋งŒ๋“ค์—ˆ๋˜ MemberApp ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

์ด์ œ AppConfig๊ฐ€ ์ „์ฒด์ ์ธ ๊ฒƒ์„ ๊ด€๋ฆฌํ•˜๊ธฐ์— ๊ธฐ์กด์˜ MemberApp ํด๋ž˜์Šค๋„ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

public class MemberApp {
    public static void main(String[] args) {
        AppConfig appConfig = new AppConfig();
        appConfig.memberService();
        //MemberService memberService = new MemberServiceImpl();
        MemberService memberService = appConfig.memberService();
        ...
    }
}

AppConfig์—์„œ MemberService์˜ ๊ตฌํ˜„์ฒด๋ฅผ ํ• ๋‹นํ–ˆ๊ณ , MemberService๊ฐ€ ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ์ž˜ ๋„ฃ์–ด์คฌ๊ธฐ ๋•Œ๋ฌธ์— appConfig.memberService()๋งŒ ํ˜ธ์ถœํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ OrderApp ํด๋ž˜์Šค์— ๋“ค์–ด๊ฐ€์„œ ์ˆ˜์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public class OrderApp {
    public static void main(String[] args) {
        AppConfig appConfig = new AppConfig();
        //MemberService memberService = new MemberServiceImpl();
        //OrderService orderService = new OrderServiceImpl();
        MemberService memberService = appConfig.memberService();
        OrderService orderService = appConfig.orderService();
        ...
    }
}

์œ„์—์ฒ˜๋Ÿผ ์ˆ˜์ •์„ ์™„๋ฃŒํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

์‹คํ–‰ํ•ด๋ณผ๊ฒŒ์š”.

MemberApp ์‹คํ–‰
OrderApp ์‹คํ–‰

๋‘˜ ๋‹ค ์‹คํ–‰์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ๋„ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ์ „์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ์ˆ˜์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

public class MemberServiceTest {
    MemberService memberService;
    //MemberService memberService = new MemberServiceImpl();
    
    @BeforeEach
    public void beforeEach() {
        AppConfig appConfig = new AppConfig();
        memberService = appConfig.memberService();
    }
    @Test
    void join() {
    	...
    }
}

MemberServiceTest ์ฝ”๋“œ ์ˆ˜์ • ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค.

@BeforeEach์— ๊ด€ํ•œ ์„ค๋ช…์€ ๋ฐ”๋กœ ๋ฐ‘์— ๋‚˜์˜ต๋‹ˆ๋‹ค.

public class OrderServiceTest {
    MemberService memberService;
    OrderService orderService;
    //MemberService memberService = new MemberServiceImpl();
    //OrderService orderService = new OrderServiceImpl();

    @BeforeEach
    public void beforeEach() {
        AppConfig appConfig = new AppConfig();
        memberService = appConfig.memberService();
        orderService = appConfig.orderService();
    }    
    @Test
    void createOrder() {
    	...
    }
}

@BeforeEach๋ž€..

ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

OrderServiceTest๊นŒ์ง€ ์ˆ˜์ • ์™„๋ฃŒํ–ˆ๊ณ , ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

MemberServiceTest ์‹คํ–‰
OrderServiceTest ์‹คํ–‰

๋‘˜ ๋‹ค ์‹คํ–‰ ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

3-3. AppConfig ๋ฆฌํŒฉํ„ฐ๋ง

ํ˜„์žฌ AppConfig๋ฅผ ๋ณด๋ฉด ์ค‘๋ณต์ด ์žˆ๊ณ , ์—ญํ• ์— ๋”ฐ๋ฅธ ๊ตฌํ˜„์ด ์ž˜ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.๐Ÿ˜ญ

๊ธฐ๋Œ€ํ•˜๋Š” ๊ทธ๋ฆผ

๊ธฐ๋Œ€ํ•˜๋Š” ๊ทธ๋ฆผ์€ ๋ถ„๋ช… ์ด๋žฌ๊ฑฐ๋“ ์š”.

์ง€๊ธˆ AppConfig์—๋Š” ์—ญํ• , ๊ตฌํ˜„ ์ด๋Ÿฐ๊ฒŒ ํ•œ ๋ˆˆ์— ์ž˜ ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

AppConfig ํด๋ž˜์Šค๋กœ ๊ฐ€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

new MemoryMemberRepository() ์ฝ”๋“œ๋ฅผ ์„ ํƒํ•œ ํ›„ Window ๊ธฐ์ค€ ctrl + Alt + M์„ ๋ˆŒ๋Ÿฌ์ค๋‹ˆ๋‹ค.

(MAC์€ Command + Option + M)

์ถ”์ฒœํ•˜๋Š” ์ด๋ฆ„๋ง๊ณ  ์ œ๊ฐ€ ์›ํ•˜๋Š” ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์˜†์— ์˜ต์…˜ ๋ฒ„ํŠผโš™๏ธ์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.

๊ธฐํƒ€ ์˜ต์…˜์„ ๋ˆ„๋ฅธ ํ›„, ์ด๋ฆ„์„ memberRepository๋กœ ํ•˜๊ณ , ๋ฐ˜ํ™˜ ํƒ€์ž…์€ ๊ตฌ์ฒด ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ์ธํ„ฐํŽ˜์ด์Šค์ธ MemberRepository๋กœ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

static ์‹คํ–‰์€ ๋ˆ„๋ฅด์‹œ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๊ณ  ๋ฆฌํŒฉํ„ฐ๋ง์„ ๋ˆ„๋ฅด๋ฉด ์ค‘๋ณตํ•˜๋Š”๊ฒŒ ์žˆ๋‹ค๊ณ  ๋œน๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๊ฐ€๋ณ๊ฒŒ ๋Œ€์ฒดํ•œ๋‹ค๊ณ  ๋ˆ„๋ฅด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

FixDiscountPolicy๋„ ์œ„์˜ ๋ฐฉ๋ฒ•์ฒ˜๋Ÿผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class AppConfig {

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

    private MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    } //์ƒˆ๋กœ ์ƒ๊ธด ๋ถ€๋ถ„

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

    private DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    } //์ƒˆ๋กœ ์ƒ๊ธด ๋ถ€๋ถ„
}

ํ•ด๋ณด๋ฉด ๊ธฐ์กด์˜ new MemoryMemberRepository์™€ new FixDiscountPolicy๊ฐ€ memberRepository()์™€ discountPolicy()๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ๋ฆฌํŒฉํ† ๋ง์„ ํ•ด ๋†“์œผ๋ฉด ์—ญํ• ๊ณผ ๊ตฌํ˜„์ด ์ž˜ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๋‚˜์ค‘์— ์ˆ˜์ •์„ ํ•ด์•ผ ํ•˜๋ฉด ์ด ์ฝ”๋“œ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.


4. ์ƒˆ๋กœ์šด ๊ตฌ์กฐ์™€ ํ• ์ธ ์ •์ฑ… ์ ์šฉ - ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋ณ€๊ฒฝ

์ฒ˜์Œ์œผ๋Ÿฌ ๋Œ์•„๊ฐ€์„œ ์ •์•ก ํ• ์ธ ์ •์ฑ…์„ ์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

FixdiscountPolicy๋ฅผ RateDiscountPolicy๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ๋ถ€๋ถ„๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ ๊นŒ์š”?

AppConfig๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค!!!

 

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

์—ฌ๊ธฐ์—์„œ FixDiscountPolicy๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์œผ๋ฉด...

๋ฐ‘์— ์‚ฌ์ง„์ฒ˜๋Ÿผ ํ•˜๋ฉด ๋˜๊ฒ ์ฃ .

๊ตฌ์„ฑ ์˜์—ญ์˜ ์ฝ”๋“œ๋งŒ ์†์„ ๋Œ€๋ฉด ๋˜๊ณ , ์‚ฌ์šฉ ์˜์—ญ์˜ ์ฝ”๋“œ๋Š” ์†์„ ์•ˆ ๋Œ€๋„ ๋˜๊ฒ ์ฃ .

 

๊ตฌ์„ฑ ์˜์—ญ์ธ AppConfig์˜ ์ฝ”๋“œ๋ฅผ ํ•œ ๋ฒˆ ์ˆ˜์ •ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public class AppConfig {
	...
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

	//์—ฌ๊ธธ ๋ณ€๊ฒฝ
    private DiscountPolicy discountPolicy() {
        return new FixDiscountPolicy();
    }
}

์›๋ž˜ ๊ธฐ์กด ์ •์•ก ํ• ์ธ ์ •์ฑ…์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฝ”๋“œ๊ฐ€ ์ด๋žฌ์Šต๋‹ˆ๋‹ค.

์ •๋ฅ  ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋ณ€๊ฒฝ์„ ํ•˜๋ ค๋ฉด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

private DiscountPolicy discountPolicy() {
        //return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }

FixDiscountPolicy๋ฅผ ๋ฆฌํ„ดํ•˜๊ณ  ์žˆ๋˜ ๊ฒƒ์„ RateDiscountPolicy๋ฅผ ๋ฆฌํ„ดํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ๊ฐ€ ์ž˜ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ •๋ฆฌ๋ฅผ ํ•ด๋ณด์ž๋ฉด...

  • AppConfig์—์„œ ํ• ์ธ ์ •์ฑ… ์—ญํ• ์„ ๋‹ด๋‹นํ•˜๋Š” ๊ตฌํ˜„์„ FixDiscountPolicy์—์„œ RateDiscountPolicy๋กœ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด์ œ ํ• ์ธ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•ด๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ตฌ์„ฑ ์—ญํ• ์„ ๋‹ด๋‹นํ•˜๋Š” AppConfig๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    • ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์ธ OrderServiceImpl๋ฅผ ํฌํ•จํ•ด์„œ ์‚ฌ์šฉ ์˜์—ญ์˜ ์–ด๋–ค ์ฝ”๋“œ๋„ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  • ๊ตฌ์„ฑ ์˜์—ญ์€ ๋‹น์—ฐํžˆ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
    ๊ตฌ์„ฑ ์—ญํ• ์„ ๋‹ด๋‹นํ•˜๋Š” AppConfig๋ฅผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋ผ๋Š” ๊ณต์—ฐ์˜ ๊ธฐํš์ž๋กœ ์ƒ๊ฐํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
    ๊ณต์—ฐ ๊ธฐํš์ž๋Š” ๊ณต์—ฐ ์ฐธ์—ฌ์ž์ธ ๊ตฌํ˜„ ๊ฐ์ฒด๋“ค์„ ๋ชจ๋‘ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

5. ์ข‹์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์™€ 5๊ฐ€์ง€ ์›์น™์˜ ์ ์šฉ

์—ฌ๊ธฐ์„œ๋Š” ํฌ๊ฒŒ SRP, DIP, OCP ์ด๋ ‡๊ฒŒ 3๊ฐ€์ง€๊ฐ€ ์ ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

5-1. SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™

ํ•œ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„๋งŒ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด๋Š” ์ง์ ‘ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ฑ…์ž„์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™์„ ๋”ฐ๋ฅด๋ฉด์„œ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.
    • AppConfig: ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ์ฑ…์ž„ ๋‹ด๋‹น
    • ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด: ์‹คํ–‰ํ•˜๋Š” ์ฑ…์ž„ ๋‹ด๋‹น

 

5-2. DIP ์˜์กด ๊ด€๊ณ„ ์—ญ์ „ ์›์น™

ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผํ•˜๊ณ , ๊ตฌ์ฒดํ™”์— ์˜์กดํ•˜๋ฉด ์•ˆ ๋œ๋‹ค.
์˜์กด์„ฑ ์ฃผ์ž…์€ ์ด ์›์น™์„ ๋”ฐ๋ฅด๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋‹ค.
  • ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ…์„ ๊ฐœ๋ฐœํ•˜๊ณ , ์ ์šฉํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ์™œ๋ƒํ•˜๋ฉด, ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ OrderServiceImpl๋Š” DIP๋ฅผ ์ง€ํ‚ค๋ฉฐ DiscountPolicy ์ถ”์ƒํ™” ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋Š” ๊ฒƒ ๊ฐ™์•˜์ง€๋งŒ, FixDiscountPolicy ๊ตฌ์ฒดํ™” ๊ตฌํ˜„ ํด๋ž˜์Šค์—๋„ ํ•จ๊ป˜ ์˜์กดํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ DiscountPolicy ์ถ”์ƒํ™” ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ... ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋งŒ์œผ๋กœ๋Š” ์•„๋ฌด ๊ฒƒ๋„ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
  • AppConfig๊ฐ€ FixDiscountPolicy ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ๋Œ€์‹  ์ƒ์„ฑํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜์กด ๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ–ˆ์Šต๋‹ˆ๋‹ค.
    ์ด๋ ‡๊ฒŒ ํ•ด์„œ DIP ์›์น™์„ ๋”ฐ๋ฅด๋ฉด์„œ ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

 

5-3. OCP

์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋Š” ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ์œผ๋‚˜ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๋‹คํ˜•์„ฑ์„ ์‚ฌ์šฉํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ DIP๋ฅผ ์ง€์ผฐ์Šต๋‹ˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉ ์˜์—ญ๊ณผ ๊ตฌ์„ฑ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆด์Šต๋‹ˆ๋‹ค.
    • AppConfig๊ฐ€ ์˜์กด ๊ด€๊ณ„๋ฅผ FixDiscountPolicy์—์„œ RateDiscountPolicy๋กœ ๋ณ€๊ฒฝํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์ฃผ์ž…ํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.
  • ์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋ฅผ ์ƒˆ๋กญ๊ฒŒ ํ™•์žฅํ•ด๋„ ์‚ฌ์šฉ ์˜์—ญ์˜ ๋ณ€๊ฒฝ์€ ๋‹ซํ˜€์žˆ์Šต๋‹ˆ๋‹ค.

6. IoC, DI, ๊ทธ๋ฆฌ๊ณ  ์ปจํ…Œ์ด๋„ˆ

6-1. ์ œ์–ด์˜ ์—ญ์ „ IoC (Inversion of Control)

  • AppConfig๊ฐ€ ๋“ฑ์žฅํ•˜๊ธฐ ์ „...
    • ๊ธฐ์กด ํ”„๋กœ๊ทธ๋žจ์€ ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ์Šค์Šค๋กœ ํ•„์š”ํ•œ ์„œ๋ฒ„ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
      ํ•œ ๋งˆ๋””๋กœ, ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์Šค์Šค๋กœ ์กฐ์ข…ํ–ˆ๋‹ค๊ณ  ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋Š” ์ž์—ฐ์Šค๋Ÿฌ์šด ํ๋ฆ„์ด์ฃ .
  • AppConfig๊ฐ€ ๋“ฑ์žฅํ•œ ์ดํ›„...
    • ๊ตฌํ˜„ ๊ฐ์ฒด๋Š” ์ž์‹ ์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ๋งŒ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค.
      ๊ทธ๋ฆฌ๊ณ , ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์€ ์ด์ œ AppConfig๊ฐ€ ๊ฐ€์ ธ๊ฐ‘๋‹ˆ๋‹ค.
      - ex) OrderServiceImpl์€ ํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ํ˜ธ์ถœํ•˜์ง€๋งŒ, ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋“ค์ด ์‹คํ–‰๋ ์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.
    • ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์— ๋Œ€ํ•œ ๊ถŒํ•œ์€ ๋ชจ๋‘ AppConfig๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
      ์‹ฌ์ง€์–ด OrderServiceImpl๋„ AppConfig๊ฐ€ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ๊ทธ๋ฆฌ๊ณ , AppConfig๋Š” OrderServiceImpl์ด ์•„๋‹Œ OrderService ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋‹ค๋ฅธ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
      OrderServiceImpl์€ ๊ทธ๋Ÿฐ ์‚ฌ์‹ค๋„ ๋ชจ๋ฅธ ์ฑ„ ๋ฌต๋ฌตํžˆ ์ž์‹ ์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•  ๋ฟ...
  • ์ด๋ ‡๋“ฏ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์ง์ ‘ ์ œ์–ดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์™ธ๋ถ€์—์„œ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์ œ์–ด์˜ ์—ญ์ „(IoC)์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ œ์–ดํ•˜๊ณ , ๋Œ€์‹  ์‹คํ–‰ํ•˜๋ฉด ๊ทธ๊ฒƒ์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ๋งž์Šต๋‹ˆ๋‹ค. (JUnit)

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

 

 

6-2. ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… DI (Dependency Injection)

OrderServiceImpl์€ DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์‹ค์ œ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๋ ์ง€๋Š” ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

์˜์กด๊ด€๊ณ„๋Š” ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„์™€ ์‹คํ–‰ ์‹œ์ ์— ๊ฒฐ์ •๋˜๋Š” ๋™์ ์ธ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค) ์˜์กด๊ด€๊ณ„๋“ค์„ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

  • ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„

ํด๋ž˜์Šค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” import ์ฝ”๋“œ๋งŒ ๋ณด๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ •์ ์ธ ์˜์กด๊ด€๊ณ„๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„๋„ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ฐ‘์˜ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๋ณด๋ฉด OrderServiceImpl์€ MemberRepository, DiscountPolicy์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ

๊ทธ๋Ÿฐ๋ฐ ์ด๋Ÿฌํ•œ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„ ๋งŒ์œผ๋กœ๋Š” ์‹ค์ œ ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ OrderServiceImpl์— ์ฃผ์ž…๋  ์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

  • ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ์‹ค์ œ ์ƒ์„ฑ๋œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์˜์กด๊ด€๊ณ„ ์ž…๋‹ˆ๋‹ค.

๋ฐ‘์— ๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ์„ ํ•œ ๋ฒˆ ๋ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ (๋Ÿฐํƒ€์ž„)์— ์™ธ๋ถ€์—์„œ ์‹ค์ œ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•ด์„œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์˜ ์‹ค์ œ ์˜์กด๊ด€๊ณ„๊ฐ€ ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒƒ์„ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ๊ทธ ์ฐธ์กฐ๊ฐ’์„ ์ „๋‹ฌํ•ด์„œ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

 

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

โญ๊ทธ๋ฆฌ๊ณ , ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

6-3. IoC ์ปจํ…Œ์ด๋„ˆ, DI ์ปจํ…Œ์ด๋„ˆ

AppConfig์ฒ˜๋Ÿผ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋ฉด์„œ ์˜์กด๊ด€๊ณ„๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๊ฒƒ์„ IoC ์ปจํ…Œ์ด๋„ˆ ๋˜๋Š” DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ, ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์— ์ดˆ์ ์„ ๋งž์ถ”์–ด ์ตœ๊ทผ์—๋Š” ์ฃผ๋กœ DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

(์–ด์ƒ˜๋ธ”๋Ÿฌ, ์˜ค๋ธŒ์ ํŠธ ํŒฉํ† ๋ฆฌ ๋“ฑ์œผ๋กœ ๋ถˆ๋ฆฌ๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.)

 


7. ์Šคํ”„๋ง์œผ๋กœ ์ „ํ™˜ํ•˜๊ธฐ

์ง€๊ธˆ๊นŒ์ง€๋Š” ์Šคํ”„๋ง ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋กœ๋งŒ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๋“œ๋””์–ด ์Šคํ”„๋ง์„ ์‚ฌ์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์šฐ์„  AppConfig๋ฅผ ์Šคํ”„๋ง ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ”๊ฟ”๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

@Configuration
//์„ค์ • ์ •๋ณด, ๊ตฌ์„ฑ ์ •๋ณด
public class AppConfig {

    @Bean
    //๊ฐ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค @Bean ์ ์–ด์คŒ
    //์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์ ์šฉ๋จ
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

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

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

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

AppConfig ํ•จ์ˆ˜ ์œ„์— @Configuration์ด๋ผ๋Š” annotation์„ ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค.

@Configuration์ด๋ž€ ๋ญ˜๊นŒ์š”?

ํ•œ ๋งˆ๋””๋กœ ์„ค์ • ์ •๋ณด, ๊ตฌ์„ฑ ์ •๋ณด๋ฅผ ๋œปํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ๊ฐ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค @Bean์„ ๋ถ™ํ˜€์ค๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋ถ™ํ˜€์ฃผ๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์ ์šฉ์ด ๋ฉ๋‹ˆ๋‹ค.

 

์ด์ œ MemberApp ํด๋ž˜์Šค๋กœ ์ด๋™ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

public class MemberApp {
    public static void main(String[] args) {
        //AppConfig appConfig = new AppConfig();
        //MemberService memberService = appConfig.memberService();

        //์Šคํ”„๋ง์€ ApplicationContext๋กœ ์‹œ์ž‘
        //์ด๊ฒŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ๋ณด๋ฉด ๋จ.
        //@Bean์„ ๋‹ค ๊ด€๋ฆฌํ•ด์คŒ
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        //์œ„ ๋ฌธ์žฅ: AppConfig์— ์žˆ๋Š” ํ™˜๊ฒฝ ์„ค์ • ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  @Bean์„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋„ฃ์–ด์„œ ๋‹ค ๊ด€๋ฆฌํ•ด์คŒ
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
        
        Member member = new Member(1L, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Member findMember = memberService.findMember(1L);
        System.out.println("new member = " + member.getName());
        System.out.println("findMember = " + findMember.getName());
    }
}

๋ฐ”๋€ ๋ถ€๋ถ„์ด ๋ณด์ด์‹œ๋‚˜์š”?

์Šคํ”„๋ง์€ ApplicationContext๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ๋ณด๋ฉด ๋ผ์š”.

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); ๋ฌธ์žฅ์„ ํ•ด์„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

=> AppConfig์— ์žˆ๋Š” ํ™˜๊ฒฝ ์„ค์ • ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  @Bean์„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋„ฃ์–ด์„œ ๋‹ค ๊ด€๋ฆฌ๋ฅผ ํ•ด์ค€๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

 

OrderApp ํด๋ž˜์Šค๋กœ ์ด๋™ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

public class OrderApp {
    public static void main(String[] args) {
        //AppConfig appConfig = new AppConfig();
        //MemberService memberService = appConfig.memberService();
        //OrderService orderService = appConfig.orderService();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
        
        Long memberId = 1L;
        Member member = new Member(memberId, "์‹œ์›”", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "์ดˆ์ฝœ๋ฆฟ", 20000);

        System.out.println("order = " + order);
    }
}

๋‘ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์Šคํ”„๋ง ๊ด€๋ จ ๋กœ๊ทธ๊ฐ€ ๋ช‡ ์ค„ ์‹คํ–‰๋˜๋ฉด์„œ ๊ธฐ์กด๊ณผ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ

- ApplicationContext๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

- ๊ธฐ์กด์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ AppConfig๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  DI๋ฅผ ํ–ˆ์ง€๋งŒ, ์ด์ œ๋ถ€ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

- ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” @Configuration์ด ๋ถ™์€ AppConfig๋ฅผ ์„ค์ •(๊ตฌ์„ฑ) ์ •๋ณด๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  ์—ฌ๊ธฐ์„œ @Bean์ด๋ผ๊ณ  ์ ํžŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ด์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  ์ด๋ ‡๊ฒŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

- ์Šคํ”„๋ง ๋นˆ์€ @Bean์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ์˜ ๋ช…์„ ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (memberService, OrderService)

- ์ด์ „์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ AppConfig๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ์กฐํšŒํ–ˆ์ง€๋งŒ, ์ด์ œ๋ถ€ํ„ฐ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด์„œ ํ•„์š”ํ•œ ์Šคํ”„๋ง ๋นˆ(๊ฐ์ฒด)๋ฅผ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  โญ์Šคํ”„๋ง ๋นˆ์€ applicationContext.getBean() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

 

Q. ์ฝ”๋“œ๊ฐ€ ์•ฝ๊ฐ„ ๋” ๋ณต์žกํ•ด์ง„ ๊ฒƒ ๊ฐ™์€๋ฐ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ์žฅ์ ์ด ์žˆ์„๊นŒ์š”?

A. ์–ด๋งˆ์–ด๋งˆํ•œ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ์ง€๊ธˆ์€ ๋‹จ์ˆœํ•˜์ง€๋งŒ ๋‚˜์ค‘์— ๋ณต์žกํ•ด์ง€๋ฉด ๊ฐœ๋ฐœํ•˜๊ธฐ๊ฐ€ ํž˜๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ด€๋ฆฌํ•ด์คŒ์œผ๋กœ์จ ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์–ด๋งˆ์–ด๋งˆํ•ฉ๋‹ˆ๋‹ค.


์„น์…˜3๋„ ๋์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค.

๋“œ๋””์–ด ์Šคํ”„๋ง์˜ ์ฒซ ๊ฑธ์Œ์„ ํ–ˆ๋„ค์š”.

์ด์ œ๋ถ€ํ„ฐ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์Šคํ”„๋ง ๋นˆ๊ณผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์•Œ์•„๋ณผ๊ฑฐ์—์š”!

๊ทธ๋Ÿผ ์•ˆ๋…•~~