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

 

1. ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ๊ฐœ๋ฐœ

- ์š”๊ตฌ์‚ฌํ•ญ ๋ณ€๊ฒฝ (1000์› ํ• ์ธ์—์„œ 10% ํ• ์ธ์œผ๋กœ)

- [์• ์ž์ผ] -> ๊ณ„ํš์— ๋”ฐ๋ฅด๋‹ค๋ณด๋‹จ ๋ณ€ํ™”์— ๋Œ€์‘ํ•˜๊ธฐ!

- fix discount policy ๋ง๊ณ  rate discount policy ๊ฐœ๋ฐœํ•ด์ฃผ๋ฉด๋จ  

public class RateDiscountPolicy implements DiscountPolicy {

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

-  ๋ฉ”์„œ๋“œ ๋ช…์— cmd + shift + t ํ•˜๋ฉด 'create new test' ๋‚˜์˜ด

   Junit 5 / ์ด๋ฆ„์€ ์›๋ž˜ ๋ช…์— 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
    assertThat(discount).isEqualTo(1000);
  }
  @Test
  @DisplayName("VIP๊ฐ€ ์•„๋‹ˆ๋ฉด ํ• ์ธ์ด ์ ์šฉ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.")
  void vip_x() {
    //given
    Member member = new Member(2L, "memberBASIC", Grade.BASIC);
    //when
    int discount = discountPolicy.discount(member, 10000);
    //then
    assertThat(discount).isEqualTo(0);
  }
}

* assertions -> option enter -> add on-demand static import for 'org.assertj.core.api.Assertions'

(static import)


2. ์ƒˆ๋กœ์šด ํ• ์ธ ์ •์ฑ… ์ ์šฉ๊ณผ ๋ฌธ์ œ์ 

ํ• ์ธ ์ •์ฑ…์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ์šฉํ•ด๋ณด์ž

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

 

* ๋ฌธ์ œ์ 

- ์—ญํ• ๊ณผ ๊ตฌํ˜„ ๋ถ„๋ฆฌ ํ–ˆ๋‹ค / ๋‹คํ˜•์„ฑ ํ™œ์šฉ, ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„๊ฐ์ฒด ๋ถ„๋ฆฌ

- OCP DIP (๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„ ์›์น™ SOLID ์›์น™ ์ค€์ˆ˜ํ–ˆ๋‚˜?)
   -> NO!

        OCP : ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ? -> ๋ฉค๋ฒ— ์„œ๋น„์Šค ์ฝ”๋“œ ์ˆ˜์ •ํ•ด์•ผํ•จ

        DIP   : ์ฃผ๋ฌธ ์„œ๋น„์Šค ํด๋ผ์ด์–ธํŠธ(OrderServiceImpl)๋Š” DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ

                   ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค) ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ตฌ์ฒด(๊ตฌํ˜„) ํด๋ž˜์Šค์—๋„ ์˜์กดํ•˜๊ณ ์žˆ๋‹ค. 

                   ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค) ์˜์กด - DiscountPolicy

                   ๊ตฌํ˜„(ํด๋ž˜์Šค) ์˜์กด        - FixDiscountPolicy / RateDiscountPolicy

 

* ๋ฌธ์ œ ํ•ด๊ฒฐ

ํด๋ผ์ด์–ธํŠธ (OrderServiceImpl) ์ด ์ธํ„ฐํŽ˜์ด์Šค(Discount Policy) ์—๋งŒ ์˜์กดํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋ฉด ๋จ

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

ใ„ด ๊ตฌํ˜„์ฒด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— NullPointerException ๋ฐœ์ƒ 

 

ํ•ด๊ฒฐ๋ฐฉ์•ˆ

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


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

AppConfig

ใ„ดhello.cored

public class AppConfig {
  public MemberService memberService() {
    return new MemberServiceImpl(new MemoryMemberRepository());
  }
  public OrderService orderService() {
    return new OrderServiceImpl(
            new MemoryMemberRepository(),
            new FixDiscountPolicy());
  }
}

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

- ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ๊ตฌํ˜„์ฒด๊ฐ€ ๋“ค์–ด๊ฐ

- ํด๋ผ์ด์–ธํŠธ(๋ฉค๋ฒ„์„œ๋น„์Šค) ์ƒ์„ฑ๋  ๋•Œ ๊ตฌํ˜„์ฒด๊ฐ€ ์ฃผ์ž…๋จ

 

 ๋ฉค๋ฒ„ ์„œ๋น„์Šค

public class MemberServiceImpl implements MemberService {
  private final MemberRepository memberRepository;
  public MemberServiceImpl(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

-> ์„ค๊ณ„ ๋ณ€๊ฒฝ์œผ๋กœ MemberServiceImpl์€ MemoryMemberRepository๋ฅผ ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค.

-> ๋‹จ์ง€ MemberRepository ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•œ๋‹ค.

-> MemberServiceImpl ์ž…์žฅ์—์„œ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด์˜ฌ์ง€(์ฃผ์ž…) ์•Œ ์ˆ˜ ์—†๋‹ค.

-> MemberServiceImpl์˜ ์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ• ์ง€๋Š” ์˜ค์ง ์™ธ๋ถ€(AppConfig)์—์„œ ๊ฒฐ์ •๋œ๋‹ค.

-> MemberServiceImpl์€ ์ด์ œ๋ถ€ํ„ฐ '์˜์กด ๊ด€๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์€ ์™ธ๋ถ€'์— ๋งก๊ธฐ๊ณ  '์‹คํ–‰'์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋œ๋‹ค.

 

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

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

 -> DI (dependency injection) ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…

 

์ฃผ๋ฌธ ์„œ๋น„์Šค

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;
  }

-> ๊ฒฐ๊ตญ ๋ฉค๋ฒ„ ์„œ๋น„์Šค๊ฐ€ ๊ตฌํ˜„(ํด๋ž˜์Šค)๊ฐ€ ์•„๋‹Œ ์—ญํ• (์ธํ„ฐํŽ˜์ด์Šค)์— ์˜์กดํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ

 

AppConfig ์‹คํ–‰

- MemberApp

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

- OrderApp

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

 

Test ์—ญ์‹œ ์ˆ˜์ •ํ•ด์ค˜์•ผํ•จ

public class MemberServiceTest {

  MemberService memberService;

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

  @Test
  void join() {
    // given
    Member member = new Member(1L, "memberA", Grade.VIP);

    // when
    memberService.join(member);
    Member findMember = memberService.findMember(1L);

    // then
    Assertions.assertThat(member).isEqualTo(findMember);

  }
class OrderServiceTest {
  MemberService memberService;
  OrderService orderService;

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

  @Test
  void createOrder() {
    long memberId = 1L;
    Member member = new Member(memberId, "memberA", Grade.VIP);
    memberService.join(member);
    Order order = orderService.createOrder(memberId, "itemA", 10000);
    Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
  }
}

 

- beforeEach๋กœ ํ…Œ์ŠคํŠธ ์‹œ์ž‘ํ•˜๊ธฐ ์ „๋งˆ๋‹ค ์ƒ์„ฑ


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

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

 

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

[AppConfig ๋ฆฌํŒฉํ„ฐ๋ง]

public class AppConfig {
  public MemberService memberService() {
    return new MemberServiceImpl(memberRepository());
  }
  public OrderService orderService() {
    return new OrderServiceImpl(
            memberRepository(),
            discountPolicy());
  }
  public MemberRepository memberRepository() {
    return new MemoryMemberRepository();
  }
  public DiscountPolicy discountPolicy() {
    return new FixDiscountPolicy();
  }
}

- new MemoryMemberRepository() ์ด ๋ถ€๋ถ„์ด ์ค‘๋ณต ์ œ๊ฑฐ๋˜์—ˆ๋‹ค. ์ด์ œ MemoryMemberRepository ๋ฅผ ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ ํ•œ ๋ถ€๋ถ„๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

- AppConfig ๋ฅผ ๋ณด๋ฉด ์—ญํ• ๊ณผ ๊ตฌํ˜„ ํด๋ž˜์Šค๊ฐ€ ํ•œ๋ˆˆ์— ๋“ค์–ด์˜จ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „์ฒด ๊ตฌ์„ฑ์ด ์–ด๋–ป๊ฒŒ ๋˜์–ด์žˆ๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.


5. ์ƒˆ๋กœ์šด ๊ตฌ์กฐ์™€ ํ• ์ธ ์ •์ฑ… ์ ์šฉ

FixDiscountPolicy -> RateDiscountPolicy

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

- ์ด ๋ถ€๋ถ„๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด ๋œ๋‹ค!

-> OCP, DIP ๋ชจ๋‘ ์ง€์ผœ์ง


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

์—ฌ๊ธฐ์„œ SOLID ์ค‘ 3๊ฐ€์ง€ SRP / DIP / OCP ์ ์šฉ

 

1) SRP (๋‹จ์ผ ์ฑ…์ž„ ์›์น™)

"ํ•œ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„๋งŒ ๊ฐ€์ ธ์•ผํ•œ๋‹ค."

- SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™์„ ๋”ฐ๋ฅด๋ฉด์„œ ๊ด€์‹ฌ์‚ฌ๋ฅผ ๋ถ„๋ฆฌํ•จ

- ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ์ฑ…์ž„์€ AppConfig ๊ฐ€ ๋‹ด๋‹น

- ํด๋ผ์ด์–ธํŠธ ๊ฐ์ฒด๋Š” ์‹คํ–‰ํ•˜๋Š” ์ฑ…์ž„๋งŒ ๋‹ด๋‹น

 

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

"ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” [์ถ”์ƒํ™”]์— ์˜์กดํ•ด์•ผ์ง€ [๊ตฌ์ฒดํ™”]์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค"

- ์˜์กด์„ฑ ์ฃผ์ž… (AppConfig์—์„œ ์ƒ์„ฑํ•ด์„œ ๋„ฃ์–ด์คŒ) -> ์œ ์—ฐ์„ฑ

- ํด๋ผ์ด์–ธํŠธ์ฝ”๋“œ๊ฐ€ ์ถ”์ƒํ™” ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋„๋ก ์„ค์ •

- but ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋งŒ์œผ๋กœ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.

- AppConfig๊ฐ€ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ๋Œ€์‹  ์ƒ์„ฑํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๋ฉด์„œ DIP ๋ฌธ์ œ ํ•ด๊ฒฐ

 

3) OCP

"์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋Š” ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ์œผ๋‚˜ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€์žˆ์–ด์•ผํ•œ๋‹ค."

- ๋‹คํ˜•์„ฑ ์‚ฌ์šฉํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ๊ฐ€ DIP๋ฅผ ์ง€ํ‚ด

- ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉ ์˜์—ญ๊ณผ ๊ตฌ์„ฑ ์˜์—ญ์œผ๋กœ ๋‚˜๋ˆ”

- AppConfig๊ฐ€ ์˜์กด ๊ด€๊ณ„๋ฅผ FixDiscountPolicy -> RateDiscountPolicy๋กœ ๋ณ€๊ฒฝํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์ฃผ์ž…ํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ ์ž์ฒด๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค์ง€ ์•Š์•„๋„ ๋จ

- ์†Œํ”„ํŠธ์›จ์–ด ์š”์†Œ๋ฅผ ์ƒˆ๋กญ๊ฒŒ ํ™•์žฅํ•ด๋„ ์‚ฌ์šฉ ์˜์—ญ์˜ ๋ณ€๊ฒฝ์€ ๋‹ซํ˜€ ์žˆ๋‹ค.


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

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

- ๊ธฐ์กด ํ”„๋กœ๊ทธ๋žจ์€ ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ์Šค์Šค๋กœ ํ•„์š”ํ•œ ์„œ๋ฒ„ ๊ตฌํ˜„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๊ณ  ์‹คํ–‰ํ•จ

  (ํ•œ๋งˆ๋””๋กœ ๊ตฌํ˜„ ๊ฐ์ฒด๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ์Šค์Šค๋กœ ์กฐ์ข…)

- ๋ฐ˜๋ฉด AppConfig๊ฐ€ ๋“ฑ์žฅํ•œ ์ดํ›„ ๊ตฌํ˜„ ๊ฐ์ฒด๋Š” ์ž์‹ ์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ๋งŒ ๋‹ด๋‹นํ•œ๋‹ค.

  (AppConfig๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์˜ ์ œ์–ด ํ๋ฆ„์„ ๊ฐ€์ ธ๊ฐ)

  ex) OrderServiceImpl์€ ํ•„์š”ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ํ˜ธ์ถœํ•˜์ง€๋งŒ ์–ด๋–ค ๊ตฌํ˜„ ๊ฐ์ฒด๋“ค์ด ์‹คํ–‰๋ ์ง€ ๋ชจ๋ฆ„

- ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ์ œ์–ด ํ๋ฆ„์— ๋Œ€ํ•œ ๊ถŒํ•œ์€ ๋ชจ๋‘ AppConfig๊ฐ€ ๊ฐ€์ง€๊ณ ์žˆ๋‹ค. 

  OrderServiceImpl์€ ์ž์‹ ์˜ ๋กœ์ง์„ ์‹คํ–‰ํ•  ๋ฟ์ด๋‹ค.

 

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

- ํ”„๋ ˆ์ž„์›Œํฌ : ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ์ œ์–ดํ•˜๊ณ  ๋Œ€์‹  ์‹คํ–‰ (JUnit)

- ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ : ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ์ง์ ‘ ์ œ์–ด์˜ ํ๋ฆ„์„ ๋‹ด๋‹น (๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ง์ ‘ ํ˜ธ์ถœ)

 

3) ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… DI(Dependency Injection)

- OrderServiceImpl์€ DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กด (์‹ค์ œ ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉ๋ ์ง€ ๋ชจ๋ฆ„)

- [์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„] ์™€ [๋™์ ์ธ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค) ์˜์กด๊ด€๊ณ„ - ์‹คํ–‰์‹œ์ ์— ๊ฒฐ์ •] ์„ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ•ด์•ผํ•จ

 

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

- ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ ์˜์กด๊ด€๊ณ„ ๋ถ„์„ ๊ฐ€๋Šฅ

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

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

 

[๋™์ ์ธ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค) ์˜์กด๊ด€๊ณ„]

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

๊ฐ์ฒด ๋‹ค์ด์–ด๊ทธ๋žจ

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

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

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

- ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์œผ๋ฅด ์‚ฌ์šฉํ•˜๋ฉด ์ •์ ์ธ ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , ๋™์ ์ธ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค ์˜์กด๊ด€๊ณ„ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ

 

Ioc ์ปจํ…Œ์ด๋„ˆ, DI ์ปจํ…Œ์ด๋„ˆ

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

- ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์— ์ดˆ์ ์„ ๋งž์ถ”์–ด ์ตœ๊ทผ์—๋Š” ์ฃผ๋กœ DI ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•จ

- or ์–ด์…ˆ๋ธ”๋Ÿฌ / ์˜ค๋ธŒ์ ํŠธ ํŒฉํ† ๋ฆฌ ๋ผ๊ณ ๋„ ๋ถˆ๋ฆผ


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

AppConfig

1) @Configuration

2) @Bean

@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();
  }

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

 

MemberApp

1) ApplicationContext / AnnotationConfigApplicationContext

ใ„ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ(@Bean ๊ด€๋ฆฌ), AppConfig ํ™˜๊ฒฝ ์„ค์ • ์ •๋ณด ๊ฐ€์ง€๊ณ  @Bean ๊ฐ์ฒด ์ƒ์„ฑํ•œ๊ฑธ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋‹ค ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ•ด์คŒ

ใ„ด ๊ธฐ์กด์—๋Š” AppConfig์—์„œ ์ง์ ‘ ์ฐพ์•„์™”๋‹ค๋ฉด ์ด์ œ getBean("memberService" - ์ด๋ฆ„, MemberService.class - ํƒ€์ž…);๋กœ ๊ฐ€์ ธ์˜ด

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

    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

    Member member = new Member(1L, "memberA", Grade.VIP);
    memberService.join(member);

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

 

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, "memberA", Grade.VIP);
    memberService.join(member);

    Order order = orderService.createOrder(memberId, "itemA", 10000);

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

 

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

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

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

- ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” @Configuration์ด ๋ถ™์€ AppConfig๋ฅผ ์„ค์ •(๊ตฌ์„ฑ) ์ •๋ณด๋กœ ์‚ฌ์šฉ / ์—ฌ๊ธฐ์„œ @Bean์ด๋ผ ์ ํžŒ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ๋‘ ํ˜ธ์ถœํ•ด์„œ ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก / ์ด๋ ‡๊ฒŒ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์ด๋ผ๊ณ  ํ•จ

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

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

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

 

  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ