스프링 핵심 원리 - 기본편 | 관심사의 분리

Yunny.Log ·2022년 5월 24일
0

Spring Boot

목록 보기
55/80
post-thumbnail
  • Appconfig : 애플리케이션의 전체 동작 방식을 구성(config)하기 위해 구현 객체 생성 & 연결하는 책임을 가지는 별도의 설정 클래스 make
public class AppConfig {
    //생성자를 주입시켜주는 역할 (외부의 appconfig에서 service에 생성자 주입)
    public MemberService memberService() {
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

    //orderservice의 구체적인 것은 여기서 선택
    //생성자를 주입해줘야 한다
    public OrderService orderService() {
        //누군가 orderService로 조회하게 된다면 아래 두개가 들어가게 됨
        return new OrderServiceImpl(
                new MemoryMemberRepository(),
                new FixDiscountPolicy()); //이것으로 알아서 주입시켜주는 중
    }
}
  • appconfig는 애플리케이션의 실제 동작에 필요한 구현객체 생성
  • 이를 통해 serviceImpl 은 실행될 때 appconfig에서 넣어주는 policy로 생성자가 발동된다.
  • serviceimpl은 이제 완전히 인터페이스에만 의존하고, 어떤 할인정책이 들어오든지간에 신경 전혀 no no
  • AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성
  • AppConfig는 생성한 객체 인스턴스의 참조(레퍼런스)를 생성자를 통해서 주입(연결)

public class OrderServiceImpl implements  OrderService{
    //지금 철저하게 인터페이스에만 의존을 하고 있다.
    //final 로 선언되면 생성자든, 직접 이든 주입되어야 한다.
    private  final MemberRepository memberRepository; //= new MemoryMemberRepository();
    //private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy; // = new RateDiscountPolicy();

    //생성자 선언해서 final로 선언된 애들에 생성자 선언
    //지금 생성자에 뭐가 주입되냐면 , appconfig에서 넣어주는 discountpolicy가 주입되는 중
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        //설계가 잘된 이유 : 할인과, 주문의 책임이 잘분리됐기 떄문
        // 할인의 로직이 바뀌면 할인 쪽만 가서 변경해주면 된다.
        // 할인은 딱 할임만 주문은 할인에 관여하지 않기 때문에 책임과 역할이 잘 나눠짐

        //discount Policy 가 없었다면, 할인 로직을 order 에서 수행해줬어야 한다

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

}
  • MemberServiceImpl 의 생성자를 통해서 어떤 구현 객체를 주입할지는 오직 외부( AppConfig )에서 결정
  • MemberServiceImpl 은 이제부터 의존관계에 대한 고민은 외부에 맡기고 실행에만 집중
  • 생성자를 통해 어떤 구현 객체가 들어올지(주입될지)는 알 수 없는 상황
  • 이제 서비스 단에서 자신이 엮일(의존성을 가질) 아이들이 설정되는 것은, 자기 안에서 처리되지 않고 외부에서 나에게 할당, 즉 주입을 해준다,

AppConfig 리팩토링

Before

public class AppConfig {
    //생성자를 주입시켜주는 역할 (외부의 appconfig에서 service에 생성자 주입)
    public MemberService memberService() {
        return new MemberServiceImpl(new MemoryMemberRepository());
    }

    //orderservice의 구체적인 것은 여기서 선택
    //생성자를 주입해줘야 한다
    public OrderService orderService() {
        //누군가 orderService로 조회하게 된다면 아래 두개가 들어가게 됨
        return new OrderServiceImpl(
                new MemoryMemberRepository(),
                new FixDiscountPolicy());
    }
    //appconfig는 애플리케이션의 실제 동작에 필요한 `구현객체 생성`
}

After

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

=> 역할과 구현 클래스가 보다 명확해진 것을 확인 가능

  • 이렇게까지 진행을 하면 우리는 오로지 인터페이스에만 의존하는 서비스 구조를 만들게 되었다
    => 이는 유지, 확장에 매우 유연해지는 구조를 보여줄 것이다.

새로운 구조와 할인 정책 적용

  • 기존에는 FixDiscountPolicy -> RateDiscountPolicy로 변경할 때 클라이언트가 참조하고 있는 구현체 값을 직접 변경해줬어야 했다.

  • 이제는 그럴 필요 없이, 이러한 구현체들이 등록되어주는 것을 관리하는 appconfig에서만 설정해주면 된다.

FixDiscountPolicy

RateDiscountPolicy

서비스는 이제 구현체의 영향을 받지 않으며, 오로지 AppConfig만 변화
아래와 같이 Appconfig에서 참조해주는 아이만 변경해주면 된다.

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

결론

  • 생성자를 적절하게 주입시켜주는 Config , 즉 구성 영역과
  • 자신이 맡은 임무만 반복적으로 수행하는 service 단 등등의 실행 영역이
    => 온전히 분리가 됨으로써 구현체가 바뀌는 것은 오로지 구성 영역이 담당하게 됨
    => 실행 영역은 오로지 추상화된 인터페이스만 의존하면서 DIP, OCP (변경에 무감각해지기) 를 지킬 수 있게 됨

0개의 댓글