IoC, DI, 컨테이너
스프링 핵심 원리 - 기본편 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 초급 프레임워크 및 라이브러리 웹 개발 서버 개발 Back-End Spring 객체지향 온
www.inflearn.com
의존관계 주입 DI(Dependency Injection)
Spring에서 의존관계 주입이란 다음과 같이 정의한다.
어떤 객체에 스프링 컨테이너가 또 다른 객체에 의존성을 맺어주는 행위
- 인터페이스와 어떤 구현체를 보면 누가 누구한테 의존하고 있는지 알 수 있다.
- 의존관계는 정적인 클래스 의존관계와, 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계 둘을 분리해서 생각해야 한다.
- 일단 클래스(OrderServiceImpl) 가 인터페이스(MemberRepository, DiscountPolicy)에 의존한다고 하자.
정적인 클래스 의존 관계
애플리케이션을 실행하지 않아도, 즉 import 코드만 보고도 의존관계를 쉽게 판단, 분석할 수 있는 클래스간의 의존 관계이다.
클래스가 사용하는 import 코드만 보고 의존관계를 쉽게 판단할 수 있다. 정적인 의존관계는 애플리케이션을 실행하지 않아도 분석할 수 있다. 설계된 클래스 다이어그램을 보면 OrderServiceImpl 이 인터페이스(MemberRepository, DiscountPolicy)에 의존한다는 것을 알 수 있다. 그런데 이러한 클래스 의존관계 만으로는 실제 어떤 객체가 OrderServiceImpl에 주입 될지 알 수 없다. 왜냐하면 인터페이스의 구현체가 무엇이 올지 알수없기 때문이다. 밑의 코드를 보면 인터페이스는 아직 구현체로 객체를 생성하지 않았다.
import hello.core.discount.DiscountPolicy;
import hello.core.member.MemberRepository;
@Component
public class OrderServiceImpl implements OrderService{
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
/.../
}
동적인 객체 인스턴스 의존 관계
애플리케이션 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결된 의존 관계다.
스프링의 의존관계 주입(DI)라는 말이 동적인 객체 인스턴스 의존관계를 의미하는데, 정확하게 다시 말하면 그 정의는 다음과 같다.
- 애플리케이션 실행 시점(런타임)에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 클라이언트와 서버의 실제 의존관계가 연결 되는 것을 의존관계 주입이라 한다.
- 객체 인스턴스를 생성하고, 그 참조값을 전달해서 연결된다.
- 의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고, 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.
- 의존관계 주입을 사용하면 정적인 클래스 의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.
위의 정적인 클래스 의존관계와 다른점을 코드로 비교해보자.
import hello.core.discount.DiscountPolicy;
import hello.core.member.MemberRepository;
import org.springframework.stereotype.Component;
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
위 코드를 보면 OrderServiceImpl의 생성자에 실제 구현체를 주입해주는 방식을 볼 수 있다. 의존관계를 주입해주는 방식은 여러가지 이지만 생성자에 주입해주는 방식을 보통 쓴다. 생성자의 파라미터를 보면 실제 구현체가 무엇인지는 코드 상에서는 알 수가 없다. 아까 말했듯이 애플리케이션 실행시점에 외부에서 실제 구현체를 생성해서 주입해주기 때문에 실행시점에 어떤 구현체가 주입되는지 알게되는 것이다.
제어의 역전 IoC(Inversion of Control)
스프링을 쓰기 전에 일반적인 상황에서는 개발자가 직접 객체를 제어해야 했다. new 연산자를 통해 객체를 생성하고, 객체의 의존성을 맺어주고, 초기화를 해주는 등등의 방식으로 말이다.
스프링에서는 이런 개발자가 해야할 번거로운 작업을 덜어주는 방식을 제공한다. 스프링에서는 xml파일 또는 애노테이션 방식으로 스프링 컨테이너에 Bean(객체)를 등록하기만 하면 스프링 컨테이너는 Bean(객체)의 생명주기(생성->의존관계 설정->초기화->소멸)을 전부 관리해준다.
즉, 객체에 대한 제어권이 스프링 컨테이너에 역전되므로 제어의 역전(IoC)라고 하는 것이다.
- 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전(IoC)이라고 한다.
- 즉 클라이언트 구현 객체가 스스로 필요한 서버 구현 객체를 생성하고, 연결하고, 실행하는 것이 아니고, 클라이언트 구현 객체는 자신의 로직을 실행하는 역할만 담당한다.
- 프로그램의 제어 흐름은 외부에서 조종해주는 것이다.
IoC 컨테이너, DI 컨테이너
- IoC를 담당하는 클래스, 즉 외부에서 조종해주는 '외부' 를 지칭하는 클래스는
- 객체를 생성하고 관리하면서 의존관계를 연결해 주고
- IoC컨테이너, DI 컨테이너 라고 한다.
- 의존관계 주입에 초점을 맞추어 최근에는 주로 DI 컨테이너라고 한다.
'Spring Framework > Spring 기본원리' 카테고리의 다른 글
@Qualifier, @Primary (0) | 2022.04.12 |
---|---|
좋은 객체지향설계의 5가지 원칙 (0) | 2021.01.21 |