인프런 김영한님의 강의를 듣고,
내용을 정리하며 저의 생각도 정리하였습니다.
관심사의 분리를 통한 DI와 IoC 이해하기
강의를 듣기 전부터 스프링을 공부해본 사람이라면 꼭 들어봤을 DI와 IoC에 대한 내용이 등장하기 시작한다.
의존관계 주입? 제어의 역전? 의존관계를 주입한다는게 무슨의미이고, 제어를 역전한다는게 무슨뜻인지 그 뜻이 제대로 이해가 되지 않았던 적이 많다. 이번에 강의를 들으면서 해당 개념의 이해를 하는것이 가장 큰 목적중 하나였다.
먼저 DI는 의존관계를 외부에서 주입(결정)해주는 것을 의미한다.
스프링에서는 DI 컨테이너가 이러한 역할을 담당한다.
이번 쳅터에서는 DI 컨테이너를 설명하기 위해 AppConfig가 등장한다
영한님의 강의는 무조건 이해시키려는 느낌이 아니라 이 개념을 아주 자연스럽게 접근하면서 설명해준다.
강의는 먼저 Only Java Code로 간단한 서비스를 작성하게 된다.
OrderApp은 MemberService와 OrderService를 new를 통해서 직접 생성하고,
그 안에서 memberService의 join(회원가입)과 orderService의 createOrder(주문생성)을 하는 간단한 서비스 코드이다.
스프링의 다른 어떤 기능도 구현되어있지 않고, java 코드로만 구성이 되어있다.
createOrder는 memberId로 회원정보를 찾아서, 그 정보에 따라 discountPrice를 구해와서 주문을 생성하는 로직이다.
join은 회원가입을, findMember는 memberId로 회원정보를 조회하는 기능이다.
나름 깔끔하고 군더더기 없는 서비스라고 생각하지만,
앞선 시간에 배웠던 좋은 객체지향 설계의 원칙을 위배하는 문제가 있다.
(DIP 위반)
Service내에서 추상(인터페이스)뿐만 아니라 구체(구현 클래스)에도 의존하고 있는 문제가 있다
DiscountPolicy(추상) - FixDiscountPolicy, RateDiscountPolicy(구체)
FixDiscountPolicy를 직접 의존하고 있다!
(OCP 위반)
기능을 확장시켜서 변경하면 클라이언트 코드에 영향을 주게되는 문제점이 있었다
기존 FixDiscountPolicy에서 RateDiscountPolicy로 변경되려면 직접 코드를 수정해야한다.
AppConfig - 관심사의 분리
이를 해결하기 위해서,
누군가 클라이언트인 OrderServiceImpl에 DiscountPolicy의 구현 객체를 대신 생성하고 주입시켜주어야 하는데
이를 '관심사의 분리'라고 표현하고 이때 등장하는 것이 AppConfig이다.
강의 예시에 등장하는 배우(구현 객체)는 본인의 역할인 배역(인터페이스)을 수행하는 것에만 집중하고,
공연(애플리케이션)을 구성하고 배우를 섭외하고 배역을 지정하는 역할을 '공연기획자'에게 맡기는 책임 분리를 하게 되는데 AppConfig가 바로 공연기획자라고 할 수 있다.
AppConfig는 애플리케이션의 전체 동작 방식을 구성(Config)하기 위해 구현객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스이다. 생성한 객체 인스턴스의 참조(레퍼런스)를 생성자를 통해서 연결(주입)해준다.
(이를 생성자 주입이라고 하고, 주입에는 몇가지 종류가 있다)
이제 Appconfig에서 해당 서비스들이 어떤것을 참조하는지 설정하면 된다.
MemberService / OrderService는 각각 ServiceImpl을 new로 생성하고
그 안에서 사용할 repository와 discountPolicy를 선택해준다.
DiscountPolicy는 어떤 정책의 policy를 활용할지를 역시 Appconfig에서 설정해주면 된다
( 현재는 FixDiscountPolicy를 사용! )
AppConfig의 등장으로 조금 더 좋은 객체 지향 설계가 되었다.
객체의 생성과 연결은 AppConfig가 담당하게 되고, MemeberServiceImpl은 MemberRepository인 추상에만 의존한다.이때 어떤것이 연결되어 있는지는 몰라도 된다! 그저 MemberRepository 인터페이스만 바라본다고 생각하면 된다
클라이언트인 MemberServiceImpl 입장에서 보면,
의존관계를 마치 외부(AppConfig)에서 주입해주는 것과 같다고 해서 의존관계 주입 DI(Dependency Injection)라고 부르게 된다.
AppConfig 등장 전에는 클라이언트 구현 객체가 스스로 필요한 서버 구현 객체를 생성하고, 연결하고, 실행하였다.
( 구현 객체가 프로그램의 제어 흐름을 스스로 조종 )
AppConfig 등장 후에는 구현 객체는 자신의 로직을 실행하는 역할만 담당
( 프로그램의 제어 흐름은 AppConfig가 가져간다 )
프로그램의 제어 흐름을 직접 제어하는 것이 아니라, 외부에서 관리하는 것을 제어의 역전(IoC)라 한다.
'Spring > 핵심원리' 카테고리의 다른 글
[스프링 핵심원리 - 기본편] 내용 정리6 (0) | 2023.08.30 |
---|---|
[스프링 핵심원리 - 기본편] 내용 정리5 (0) | 2023.08.27 |
[스프링 핵심원리 - 기본편] 내용 정리4 (0) | 2023.08.27 |
[스프링 핵심원리 - 기본편] 내용 정리3 (0) | 2023.08.22 |
[스프링 핵심원리 - 기본편] 내용 정리1 (0) | 2022.02.21 |