FixDiscountPolicy -> RateDiscountPolicy로 바꾸기
new 부분만 바꿔주면 된다.
하지만 여기서 중요한 부분이 있다.
현재 클래스는 분명 DiscountPolicy(추상적)에 의존하지만, FixDiscountPolicy, RateDiscountPolicy(구현체)에도 의존하고 있는 것이 보인다. 그래서 DIP 위배된다.
또한 클라이언트 코드를 변경하기 때문에 *OCP를 위반한다.
OCP(Open/Closed principle) 계방-폐쇄 원칙
-> 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
ex)
기름차 -> 전기차로 변경할 때, 나는 운전면허증만 있으면 운전할 수 있어야 하는데, 나한테 뭘 요구함.
잘못된거임
생성자 주입
주석 처리 된 부분이 원래 구현체를 의존하는 부분이었다.
그러나 생성자로 MemberRepoistiory를 받기 때문에 추상화에만 의존하게 된다. 그리고 어디에도MemoryMemberRepoistiory가 보이지 않는다. 즉, DIP를 위배하지 않게 된다.
그렇다면 MemoryMemberRepository는 누가 주는 것일까?
바로 AppConfig라는 기획자가 생성해서 생성자에 넣어준다 . 이를 생성자 주입이라 함.
정리하면
MemberServiceImpl은 클라이언트이다. 그 전 코드들은 클라이언트가 직접 어느 Repository를 쓰는지 직접 결정해야한다. 그렇다면 클라이언트는 repo도 정해야하고, 회원가입도 해야한다. SRP가 위배된다.
그리고, 코드를 보면 MemberRepoistory memberRepostiory = new MemoryMemberRepostiory() 에서 인터페이스에도 의존하고, 구현체에도 의존하게 된다. DIP가 위배된다.
그래서 전체를 포괄? 관리?하는 AppConfig를 만들어서 구현체를 만들어 회원 서비스 클라이언트에게 어떤 저장소를 사용할지 정해준다.
OrderServiceImpl도 클라이언트로 위와 마찬가지로 AppConfig를 이용하여 구현체를 만들어 주문 서비스를 요청하는 클라이언트에게 어떤 할인정책, 어떤 저장소를 사용할지 정해준다.
여기서 클라이언트 입장에서 의존관계를 AppConfig에서 정해준다. 즉, 외부에서 정해준다해서 DI라고 한다.
의존관계 주입!
ex) OrderServiceImpl에는 MemoryMemberRepository, FixDiscountPolicy 객체의 의존관계가 주입됨 라고 말할 수 있음.
AppConfig의 중요성
AppConfig는 총 기획자이다. 그래서 메서드만 보고 어떤 역할을 하는지 알아보기 쉽게 코드를 작성하면 좋다.
위 사진과 같이 메서드 이름만 보고도 어떤 것을 구현할 지 보인다.
제일 신기했던 점은 할인 정책 부분이다. 원래 우리가 정액 할인 방법을 사용했으나, 이제 정률 할인 방법을 사용한다고 가정해보자. 그러면 전의 코드는 .OrderServiceImpl에 들어가서 바꿔야했지만, AppConfig을 이용하여 discountPolicy 메서드에서 new 부분만 바꿔주면 된다. memberRepository 메서드도 마찬가지이다. 갑자기 저장소가 바뀌면 new 부분만 바꿔주면 된다.
AppConfig을 통하여 강사님께서 중요시 했던 말씀이 있다.
할인 정책을 변경할 때, 사용 영역 코드를 절대 건드리지 않고, 구성 영역의 코드로만 처리할 수 있게 된다.
IoC, DI, 컨테이너
제어의 역전 IoC ( Inversion of control)
제어 흐름을 가져갔다라는 말이 뭘까라는 생각을 해보았다.
원래 제어 흐름은 작성자인 개발자에게 있어야하지않나? 라는 생각도 든다.
초반 강의 코드를 보면 클라이언트가 orderservice 객체도 생성하고, memoryrepository도 생성한다. 이게 아마 클라이언트에게 제어 흐름이 있을 때인 것 같다.
그러나 AppConfig 생성하여 구현체를 만들어 injection을 해줄 때부터, 제어 흐름은 AppConfig에게 넘어가게 된다.
모든 흐름을 AppConfig가 가져간다.
왜 이렇게 말할까?
OrderService를 예로 들어보자.
원래는 클라이언트가 OrderService 객체를 직접 생성하고 사용했다. 그러나 이제부터 AppConfig가 OrderService를 직접 구현하여 클라이언트에게 준다. 그래서 클라이언트 입장에서는 OrderService를 구현하는 객체 중에 어떤 객체가 올 지 모르는 것이다.(예로 전화 주문., 어플 주문이 있을 때 실행하기 전까지 어느 주문인지 모른다는 뜻)
따라서 AppConfig는 클라이언트를 대신해주는 역할을 맡고있어서 제어의 역전이라고 말하는 것 같다.
의존관계 주입 DI(Dependency Injection)
제어의 역전을 말하면서 의존관계 주입을 말하게됐다.
의존관계 주입이란 솔직히 어떻게 의존관계 주입은 이런 것입니다하고 정확히 말을 못하겠다.
강의에서 말씀하셨듯이, 코드를 변경하시면서 이런 것이 의존관계 주입이다라고 하셨다. 그래서 나는 아 이런게 의존관계 주입이구나라고 느낌이 왔다. 그래도 나중에 헷갈릴 때 다시 보기 위해 내 말로 바꿔서 최대한 적어놔야겠다.
OrderSerivce를 예로 들어보자.
생성자를 보면 MemberRepository와 DiscountPolicy의 구현체를 인자로 받게 되는데, 여기서 OrderService는 어떤 구현체가 올지 모른다.
MemberRepository와 DiscountPolicy에 의존한다는 것을 알 수 있다.
그런데 여기서 누가 인자를 줄 것인가? 이 말이 즉, 누가 의존관계를 주입해줄 것이냐? 라는 생각이든다.
그것이 바로 AppConfig이다. AppConfig가 제어의 흐름을 담당하고 있어, 구현체를 생성하여 OrderServiceImpl
(OrderService의 구현체)에게 의존관계를 주입해준다.
정리하자면, 의존관계를 주입받는 대상은 어떤 객체가 주입될 지 모르고, 그 주입을 해주는 것은 제어의 흐름을 담당하고 있는 AppConfig이다.
IoC 컨테이너, DI 컨테이너
AppConfig와 같은 것을 IoC 컨테이너 또는 DI 컨테이너라고 한다.
객체를 생성하고 의존관계를 연결해준다.
출처 : 인프런 스프링 핵심 원리 - 기본편 (김영한 강사님)
'Spring 강의 > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
스프링 핵심 원리 - 의존관계 자동 주입(2022.03.12 수정) (0) | 2021.08.06 |
---|---|
스프링 핵심 원리 - 컴포넌트 스캔 (0) | 2021.08.06 |
스프링 핵심 원리 - 싱글톤 컨테이너 (0) | 2021.08.04 |
스프링 핵심 원리 - 스프링 컨테이너와 스프링 빈 (0) | 2021.08.02 |
스프링 핵심 원리 이해1 - 예제 만들기 (0) | 2021.07.30 |