[Spring] IoC, DI
제어의 역전 IoC (Inversion of Control)
제어의 역전 (IoC)은 애플리케이션 흐름의 주도권이 뒤바뀌는 것을 뜻한다.
public interface MemberService {
void join(Member member);
Member findMember(Long memberId);
}
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
//
}
public interface MemberRepository {
void save(Member member);
Member findById(Long memberId);
}
public class MemoryMemberRepository implements MemberRepository {
//
}
MemberServiceImpl 클래스에서 memberRepository는 new 키워드를 사용해서 만든 인스턴스를 참조한다.
MemberServiceImpl이라는 클라이언트가 MemberRepository의 구현체를 의존하고 있고 개발자가 직접 의존관계를 설정하고 있다. 이러한 경우엔 MemberRepository의 구현체가 변경되면 memberRepository = new xxMemberRepository()로 변경하면서 SOLID 5원칙 중 하나인 OCP를 위반하게 된다.
또한 자세히 보면 추상화(MemberRepository)와 구체화(MemoryMemberRepository) 둘 다 의존하면서 추상화에 의존하고 구체화에 의존하면 안 된다는 원칙인 DIP 또한 위반하고 있다.
OCP, DIP를 위반하고 있는 상황에서 해결할 수 있는 방법은 MemberServiceImpl이 인터페이스에만 의존하고 외부에서 구현체를 대신 생성해서 넣어주면 된다.
public class MemberServiceImpl implements MemberService {
// private final MemberRepository memberRepository = new MemoryMemberRepository();
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
//
}
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
}
AppConfig라는 외부에서 구현체를 정하게 되면서 MemberServiceImpl는 인터페이스만 의존할 수 있고(DIP) 구현체가 바뀌더라도 OCP를 지킬 수 있게 된다.
위처럼 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전(IoC)라고 한다.
의존관계 주입 DI (Dependency Injection)
의존관계 주입(DI)은 IoC의 좀 더 구체적인 의미라고 생각할 수 있다.
수정한 코드에서 MemberServiceImpl은 MemberRepository 인터페이스에만 의존하고 실제로는 어떤 구현체가 사용되는지 모른다.
이렇게 애플리케이션 실행 시점에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 의존관계가 연결되는 것을 의존관계 주입이라고 한다.
의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고 클라이언트가 호출하는 대상의 타입 인스턴스를 변경하면서 인터페이스와 객체 인스턴스의 의존관계를 쉽게 변경할 수 있다.
스프링은 객체에 간단한 설정을 해주는 것만으로 IoC/DI 컨테이너를 사용해서 연관 있는 객체들끼리 의존관계를 맺어준다. 덕분에 개발자는 핵심 로직에만 집중할 수 있게 된다.
참고 자료 : 김영한님 스프링 핵심 원리 - 기본편
'Programming > Spring' 카테고리의 다른 글
[Spring] 예외처리 - ExceptionHandler, ControllerAdvice (0) | 2022.10.30 |
---|---|
[Spring] Spring MVC 구조 (0) | 2022.10.25 |
[Spring] 스프링 의존관계 주입 방법 (0) | 2022.10.24 |
[Spring] 컴포넌트 스캔(ComponentScan) (1) | 2022.10.23 |
[Spring] 싱글톤과 스프링 컨테이너 (0) | 2022.10.20 |