김영한 강사님 - 스프링 핵심 원리 기본편
을 수강하고 정리한 글 입니다.
회원
주문과 할인 정책
회원 클래스 다이어그램


각 설계대로 순수한 자바코드로 개발하고, junit프레임워크를 통한 테스트코드까지 작성함
MemberServiceImpl.java
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
...
}
OrderServiceImpl.java
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
...
}
다형성도 활용하고 인터페이스와 구현 객체를 분리했지만, OCP와 DIP 넓게보면 SRP까지 지켜지지않았음
MemberServiceImpl은 MemberRepository(인터페이스)도 의존하고, MemoryMemberRepository(구현체)에도 의존함(OrderServiceImpl도 마찬가지)
--> DIP 위반
만약 여기서 MemberRepository의 구현체를 mysql기반 DBMemberRepository로 변경한다 가정하면, 클라이언트인 MemberServiceImpl, OrderServiceImpl 코드에 변경이 발생하게됨
--> OCP 위반
MemberServiceImpl과 OrderServiceImpl은 어떻게 보면 객체 생성까지 담당하고있음 --> SRP 위반
DIP를 위반하지 않도록 인터페이스에만 의존하도록 의존관계를 변경하면 해결이됨
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();
}
public class OrderServiceImpl implements OrderService {
//private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
private DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
이런식으로 MemverServiceImpl도 인터페이스만 의존하도록 변경하고 생성자를 통해 어떤 구현체를 주입시킴
클라이언트입장에선 어떤 구현체가 주입될지는 모르고 AppConfig만 알고있음
AppConfig가 각 클라이언트의 생성자를 통해 구현체를 주입시켜줌 이걸 DI(의존관계 주입)이라고하고, 이런 DI를 해주는 AppConfig같은 클래스를 DI컨테이너라고함
정가할인(FixDiscountPolicy) 에서 정률할인(RateDiscountPolicy)로 변경이 일어났다 가정하면,
AppConfig의 disCountPolicy() 메소드의 반환부를 RateDiscountPolicy로 변경만하면됨

위 그림에서 사용영역의 변경은 일절 일어나지않고, 구성영역의 AppConfig에만 변경이 일어남
위 3가지 DIP, OCP, SRP 위반했던 문제점이 AppConfig를 통해 해결이 됐음, 이를 다시 최종 정리해보면
제어의 역전 IoC(Inversion Of Control) : 프로그램의 제어 흐름을 직접 제어하는게 아니라 외부에서 관리하는 것을 제어의 역전이라고함
의존관계 주입 DI(Dependency Injection) : 정적인 의존 관계와 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계 둘을 분리해서 생각해야함
IoC 컨테이너, DI 컨테이너