IoC 컨테이너와 DI
Dependency Injection
어떤 객체가 사용하는 의존 객체를, 해당 객체 내부가 아닌 외부에서 주입 받아 사용하는 방법론. 크게 setter 를 사용하는 방법과 constructor를 사용하는 방법으로 나뉜다.
interface Tire {
public String roll();
}
class KoreaTire implements Tire {
@Override
public String roll() {
return "KoreaTire";
}
}
class Car {
// 의존성이 클래스 내에서 자체 생성됨.
private Tire tire = new Tire();
public void ride() {
System.out.println("ride with " + tire.roll());
}
}
...
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.ride();
}
}
class Car {
private Tire tire;
public void Car(Tire tire) {
this.tire = tire;
}
public void setTire(Tire tire) {
this.tire = tire;
}
public void ride() {
System.out.println("ride with " + tire.roll());
}
}
...
public class Main {
public static void main(String[] args) {
Car car = new Car();
Tire tire = new KoreaTire();
// setter DI
car.setTire(tire);
// constructor DI
Car car2 = new Car(tire);
car.ride();
}
}
위 코드와 같이 인터페이스를 활용하여 외부에서 의존성을 주입받게 되면, 해당 인터페이스를 구현하는 객체는 모두 주입이 가능해져 프로그램이 모듈화 되고, 해당 인터페이스를 구현한 목업 객체를 이용하면 유닛 테스트도 훨씬 쉽게 진행할 수 있다.
Inversion of Control
위 코드는 객체의 생성과 의존성 주입 등을 개발자가 직접 main 함수에서 처리하였다. 이렇게 되면, 객체 생성과 의존성 주입 관계가 바뀌게 될 경우, 매번 소스코드를 수정해 주어야 한다는 문제가 발생한다. 이를 해결하기 위해 나온 것이 IoC라는 개념이다. 개발자는 비즈니스 로직을 담은 객체를 짜는 데 주력하고, 그렇게 만들어진 객체를 생성하고, 관리하고, 의존성을 주입하는 것은 프레임워크(스프링) 에게 맡기는 것이 제어의 역전(Inversion of Control)이다.
스프링 IoC 컨테이너
- BeanFactory (자바 인터페이스)
- 어플리케이션 컴포넌트의 중앙 저장소.
-
빈 설정 소스(.xml java config class파일)로부터 빈 정의를 읽어들이고, 빈을 구성하고 제공한다.
빈
- 스프링 IoC 컨테이너가 관리하는 객체.
- 의존성 관리 (IoC 컨테이너의 주요 목적)
- 스코프 관리 : 빈은 기본적으로 싱글턴 객체 / 원하지 않으면 프로토타입 객체로 생성
- 라이프사이클 인터페이스 : 빈 객체의 생성 => 소멸 라이프사이클 사이에 훅 실행 가능
Applicatoin Context
- BeanFactory를 구현한, 실제로 가장 흔히 사용되는 Spring IoC 컨테이너 객체
- 위에 나온 기본적 기능 외에도
- 메세지 소스 처리 기능
- 이멘트 발행/구독 기능
- 리소스 로딩 기능
등의 추가 기능 제공.