728x90
반응형
애플리케이션을 개발하던 중, DIP에 위반할 수 밖에 없는 상황이 왔다.
DIP
- 의존 관계를 맺을 때 변화하기 어려운 것, 거의 변화가 없는 것에 의존
- 구현 클래스에 의존하지 말고 인터페이스에 의존해야 한다.
- 역할에 의존하게 해야 한다. (역할과 구현을 철저하게 분리하도록!!)
아래 코드를 보자.
private final DiscountPolicy discountPolicy = new FixDiscountpolicy();
결국 인터페이스를 참조하는게 아닌, 직접 객체를 생성을 하게 되는 것이다.
이를 해결하려면 어떻게 해야 할까?
- 강의에서는 애플리케이션을 하나의 공연으로 비유했다.
- 각각의 인터페이스는 배역이라고 생각할때, 해당 배역을 맡게 되는 배우를 선택하는 역할은 공연 기획자가 할 것이다.
- 그러나 위 코드와 같은 경우는 기획자가 아닌 주인공(구현체)이 다른 주인공(구현체)을 직접 초빙하는 상황이다.
- 따라서 공연 기획자를 만들고, 배우와 기획자의 책임을 확실히 분리할 필요가 있다.
- 앱의 전체 동작 방식을 구성하기 위해, 구현 객체를 생성하고 연결하는 책임을 가지는 별도의 설정 클래스를 만들자.
따라서 기존에 작성했던 코드를 살펴보니 MemberServiceImpl에서 직접 MemoryMemberRepository를 호출한 것을 확인했다.
private final MemberRepository memberRepository = new MemoryMemberRepository(); // dip 위반
AppConfig에서 애플리케이션에 대한 환경설정을 모두 처리해주자.
public class MemberServiceImpl implements MemberService {
// private final MemberRepository memberRepository = new MemoryMemberRepository(); // dip 위반
private final MemberRepository memberRepository; // DIP 지킴
// memberRepository 구현체가 뭐가 들어갈지를 생성자를 통해 건네줌
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
위와 같이, MemberServiceImpl에 생성자를 만들고 구현체에 뭐가 들어갈지를 생성자를 통해 건네준다.
public class AppConfig {
public MemberService memberService(){
return new MemberServiceImpl(new MemoryMemberRepository()); // memberService 구현체, 객체 생성
}
}
그 후, AppConfig에서 인스턴스를 생성해주면 DIP를 지킬 수 있게 된다!
따라서 `MemberServiceImpl` 은 'MemoryMemberRepository`를 의존하지 않고 'MemberRepository` 인터페이스만 의존한다. (어떤 구현 객체를 주입할지는 오로지 `Appconfig` 에서 결정된다.
이와 같이 생성자를 통해서 new MemoryMemberRepository() 인스턴스가 생성된 것을 생성자 주입이라고 한다.
인스턴스(Instance) : 설계도(클래스)를 통해서 구현해야할 대상(객체)이 실제로 구현된 구체적인 실체
(인스턴스는 객체에 포함된다.)
마찬가지로, OrderService에도 적용해준다.
정리해보면,
- AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성한다.
- `MemberServiceImpl`
- `MemoryMemberRepository`
- AppConfig는 생성한 객체 인스턴스의 참조(레퍼런스)를 생성자를 통해서 주입(연결)해준다.
- `MemberServiceImpl` → 'MemoryMemberRepository`
- 클라이언트인 `MemberServiceImpl` 입장에서 보면 의존관계를 마치 외부에서 주입해주는 것 같다고 해서 DI(Dependency Injection), 의존관계 주입(의존성 주입)이라고 한다.
- 이외 TIP
- 테스트 코드에서 `@BeforeEach` 는 각 테스트를 실행하기 전에 호출한다.
728x90
반응형
'Tech > Spring' 카테고리의 다른 글
[스프링 핵심 원리] 웹 애플리케이션과 싱글톤 (0) | 2022.01.11 |
---|---|
[스프링 핵심 원리] 스프링 빈 설정 메타 정보 - BeanDefinition (0) | 2022.01.10 |
[스프링 핵심 원리] 스프링 컨테이너 기초 (0) | 2022.01.05 |
[스프링 핵심 원리] IoC, DI, 컨테이너 (0) | 2022.01.04 |
[스프링 핵심 원리] 객체 지향 설계의 5가지 원칙(SOLID), 스프링 (0) | 2021.12.22 |