DI와 IoC
DI(Dependency Injection, 의존성 주입)
DI란 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, 객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다.
이를 통해 객체 간의 결합도를 낮추고 코드의 유연성을 높일 수 있다.
의존 관계를 나타낼 때 다음 처럼 표현할 수 있다.
A —> B
A는 B에게 의존하고 있다.
의존은 무엇일까? 만약 B가 변경이 된다면 A에게 영향을 미친다는 것이다.
public class User {
Point point = new Point();
}
User 클래스는 Point 클래스의 존재를 설계 시점에서 알고 있다. 이는 User가 Point를 사용하겠다는 결정을 관리한다 이를 런타임 의존관계
라 한다.
위 코드를 IoC
방식으로 User로 부터 런타임 의존관계를 드러내는 코드를 제거하고, 제 3의 존재에게 런타임 의존관계 결정 권한을 위임한다.
public class User {
private Point point;
public User(Point point) {
this.point = point;
}
}
DI 컨테이너는 User를 만드는 시점에 생성자의 파라미터로 이미 만들어진 Point의 객체를 전달한다. 이렇게 두 객체간의 런타임 의존관계가 만들어졌다.
이렇게 생성자를 통해 DI 컨테이너가 User에게 주입해주는 것과 같다고 해서 의존관계 주입
이라 한다.
DI
는 자신이 사용할 객체에 대한 결정과 제어권을 외부로 넘기고 수동적으로 주입받은 객체를 사용한다는 점에서 IoC
의 개념과 비슷하다.
스프링 컨테이너의 IoC
는 주로 의존관계 주입
에 초점이 맞춰져 있다. 그래서 스프링 IoC
컨테이너 외 DI 컨테이너
또는 DI 프레임워크
라고 부르는 것이다.
IoC(Inversion of Control, 제어의 역행)
프로그램의 제어 흐름 구조가 뒤바뀌는 것을 말하며, 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조를 거꾸로 뒤집는 것이다.
객체를 제어하고 관리하는 역할이 개발자로부터 스프링 컨테이너에 역전 된다.
스프링 프레임워크의 가장 중요한 특징은 객체의 생성과 의존관계를 컨테이너가 자동으로 관리한다는 점이다. 이것이 스프링 IoC의 핵심 원리이다.
스프링이 제어권을 직접 만들고 관계를 부여하는 오브젝트를 bean
이라고 부르고, bean
의 생성과 관계 설정 같은 제어를 담당하는 IoC 오브젝트를 bean factory
라고 부른다.
아래는 DI의 의존관계 주입을 스프링의 IoC
로 처리하는 코드이다.
public class User {
private Point point;
public User(Point point) {
this.point = point;
}
}
@Configuration
public class UserConfig {
@Bean
public Point point() {
return new Point();
}
@Bean
public User user() {
return new User(point());
}
}
@Configuration
어노테이션은 스프링 컨텍스트에게 해당 클래스가 Bean 구성을 제공하는 클래스임을 알려주는 역할을 한다.
@Bean
어노테이션은 스프링에서 빈(Bean)으로 관리되는 객체를 정의할 때 사용된다. 이 어노테이션을 메서드에 적용하면 해당 메서드의 반환값이 스프링 컨테이너에 의해 빈으로 관리되게 된다.
@Bean
을 사용한 메서드가 있는 클래스는 반드시 @Configuration
어노테이션을 주어야 스프링 컨테이너가 빈으로 설정할 수 있다.
스프링 빈(Bean)
스프링의 빈은 스프링 컨테이너에 의해 생성, 관리되는 객체이다.
빈은 스프링 IoC 컨테이너에서 생성되며, 스프링 애플리케이션의 핵심 구성 요소 중 하나이다.⚠ 스프링 컨테이너는 빈을 싱글톤으로 관리한다.