[Spring] IoC(Inversion of Control), DI(Dependency Injection)
Spring의 3대 요소라고 하는 IoC, DI, AOP중 IoC와 DI에 대해 정리해보자
IoC(Inversion of Control)
- 그대로 해석하면 제어의 역전이다. 제어권을 프레임워크가 갖는 것을 의미한다. 즉, 개발자에게 제어권이 없기 때문에 제어(Control)가 역전(Inversion)되었다고 한다. 여기서 제어란, 프로그램의 흐름이나 객체의 생성과 같은 것을 의미한다.
- IoC관점에서 각자의 역할
1) 개발자는 코드의 흐름이나 객체생성에 관련된 코드를 직접 작성하지 않는다.
2) 개발자는 프레임워크가 제공하는 설정방법을 사용하여 코드를 설정만 한다.
3) 프레임워크는 이 설정을 보고 객체를 생성하고 코드가 동작하는 순서를 결정하여 실행한다.
헐리우드 원칙
객체지향 프레임워크와 클래스 라이브러리의 큰 차이점은 프레임워크가 어플리케이션 코드를 호출한다는 것이다. 일반적으로는 애플리케이션 코드가 클래스 라이브러리를 호출한다. 이러한 제어의 역전은 헐리우드 원칙이라고도 불린다.
우리에게 전화(call)하지 마세요. 우리가 당신을 부를(call) 것입니다.
코드로 보면 좀 더 간단하다. 대표적인 예시로 Template method 패턴이 있다. 쉽게 이야기 하면 각각의 처리 클래스에 공통 인터페이스나 공통 기초 클래스를 두고 클라이언트 코드에서 다형성을 사용할 수 있게 하는 것이다.
public class GreetingService {
private final Greeter greeter;
public GreetingService(Greeter greeter) {
this.greeter = greeter;
}
public void doGreet() {
greeter.sayHello();
}
}
위의 예시처럼 GreetingService는 외부에서 생성된 객체를 사용한다. 객체 생성의 책임이 없다.
public class Main {
public static void main(String[] args) {
new GreetingService(new KoreanGreeter()).greet();
}
}
객체 생성의 제어역전을 위해 KoreanGreeter 클래스의 객체를 Main클래스에서 생성하여 제공한다.
스프링에서는 제어의 역전 개념을 중요한 개념으로 삼고 있으며, 객체를 관리하는 주체를 "스프링 컨테이너"라고 한다.
DI(Dependency Injection)
앞서 말했듯이 스프링에서는 객체들을 관리하기 위해 제어의 역전을 사용한다. 그리고 이러한 제어의 역전을 구현하기 위해 사용하는 방법이 DI이다. 그대로 해석하면 의존성 주입이라는 뜻으로 어떤 클래스가 다른 클래스에 의존한다는 의미이다.
- IoC의 패턴 중 하나
- Object 간의 의존성을 낮춘다.
- 외부에서 객체를 생성하고 전달한다.
DI의 방법
1) Constructor Injection
// 생성자 주입 방식을 사용하므로, 주입 대상 스프링빈에 적절한 생성자가 필요하다.
public GreetingService(Greeter greeter) {
this.greeter = greeter;
}
2) Setter Injection
// final keyword 이므로 객체를 생성한뒤 greeter 변수에 값을 할당할 수 없다.
// private final Greeter greeter;
private Greeter greeter;
// Setter Injection 기본 생성자가 필요하다.
public GreetingService() {
}
public void setGreeter(Greeter greeter) {
System.out.println("setGreeter invoked!");
this.greeter = greeter;
}
3) Field Injection
public class GreetingService {
@Autowired
private Greeter greeter;
public void greet() {
greeter.sayHello();
}
}
참고
NHN Academy 교육자료