1. 관심사의 분리
앞선 포스팅에서 살펴본 코드들은 구현체가 직접 다른 구현체를 불러오는 것과 상황이었다.
-> DiscountPolicy의 구현 객체를 직접 클라이언트인 OrderServiceImpl에서 지정하여 사용하던 경우가 이에 해당.
이런 상황은 클라이언트가 추상에만 의존해야 하는 상황이 아닌 구체에도 의존학 되는 DIP 위반을 불러일으키고 이를 해결하기 위해서는 관심사를 철저하게 분리해서 사용해야 한다.
관심사의 분리란?
예를 들어 극단에 배우와 공연 기획자가 있다고 할 때 배우가 디렉팅에 참여해 상대 배우를 직접 고르는 상황이 우리의 이전 포스팅에서 살펴보았던 상황이라면, 우리는 앞으로 공연 기획자와 배우의 역할을 철저히 나누어 사용할 수 있게 해야 DIP 위반 문제가 발생하지 않게 된다.
2. AppConfig 이전의 상황
package hello.core.member;
//관례상 구현체가 1개인 경우엔 이름뒤에 Impl를 쓴다,.
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
@Override
public void join(Member member) {
memberRepository.save(member);
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
private final MemberRepository memberRepository = new MemoryMemberRepository();
코드를 살펴보면 MemberServiceImpl가 직접 구체적인 설정을 직접 진행하던 상황. 이와 같은 상황은 마치 배우가 디렉팅까지 참여해 상대 배우까지 캐스팅하고 제작하는 것과 비슷한 상황이다.
3. AppConfig
환경설정과 구성에 관한것은 이제 AppConfig에서 진행한다.
- 구현 객체의 생성 - 연결을 별도의 책임으로 관리하게 된다.
- Application 전체를 설정, 구성한다는 의미로 AppConfig가 사용된다.
<OrderServiceImpl>
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
<MemberServiceImpl>
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
<AppConfig>
package hello.core;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
public class AppConfig {
public MemberService memberService(){
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService(){
return new OrderServiceImpl(new MemoryMemberRepository(),new FixDiscountPolicy());
}
}
AppConfig의 역할
구현 객체: 애플리케이션의 실제 동작에 필요한 것을 의미한다.
AppConfig는 생성한 객체를 인스턴스의 참조(레퍼런스)를 생성자를 통해 주입(연결)해준다.
AppConfig 사용의 결과
의존 관계는 외부(AppConfig)에 맡기고 실행에만 집중하게 된다. 👉 관심사의 분리
<의존관계 주입 시>
<의존관계 주입 / 의존성 주입>
- AppConfig를 통해서 의존관계를 생성자를 통해서 주입해주는 것을 의존성 주입, 의존관계 주입이라고 한다.
- 이때 클라이언트는 구체를 의존하지 않고 인터페이스만을 의존해서 DIP 문제가 발생하지 않게 된다.
- 또한 AppConfig에서는 구현 객체를 결정해주면 되기 때문에 따로 코드를 변경하지 않아도 되기 때문에 이와 관련한 문제 또한 발생하지 않게 된다.
'Back-End > Spring' 카테고리의 다른 글
[Spring][스프링 기본편] - 10.IOC, DI, 그리고 컨테이너 (0) | 2022.01.20 |
---|---|
[Spring][스프링 기본편] - 9. AppConfig 리팩토링 (0) | 2022.01.17 |
[Spring][스프링 기본편] - 7. DIP OCP 위반과 NPE (0) | 2022.01.15 |
[Spring][스프링 기본편] - 6. 주문과 할인 도메인 개발과 테스트 (0) | 2022.01.13 |
[Spring][스프링 기본편] - 5. 주문과 할인 도메인 설계 (0) | 2022.01.13 |