컨테이너는 인스턴스의 생명주기를 관리한다.
생성된 인스턴스들에게 추가적인 기능을 제공한다.
예를 들어 Servlet을 실행해주는 WAS는 Servlet 컨테이너를 가지고 있다고 말한다.
개발자가 서블릿 클래스를 잘성했지만, 실제로 메모리에 올리고 실행하는 것은 WAS가 가지고 있는 Servlet컨테이너이다. Servlet 컨테이너는 동일한 서블릿에 해당하는 요청을 받으면, 또 메모리에 올리지 않고 기존의 메로리에 올라간 서블릿을 실행하여 그 결과를 웹 브라우저에게 전달한다.
컨테이너는 Spring의 핵심이다. Container는 개발자를 대신하여, Bean을 생성하고, 관리하고, 제거한다. Container가 Bean을 관리해주기에, 개발자는 모듈 간에 의존 및 결합으로 인해 발생하는 문제로부터 자유로울 수 있다. 따라서, 개발자는 Annotation만 남겨주면 Container가 개발자가 원하는 상황에 코드를 실행한다.
@Controller
public class HomeController {
@GetMapping("/")
public String home(){
return "home";
}
}
컨테이너는 겉으로 드러나지 않고 작동한다. 예시로 run 메서드를 호출시기는 코드를 살펴보자.
@SpringBootApplication
public class HelloSpringApplication {
public static void main(String[] args) {
SpringApplication.run(HelloSpringApplication.class, args);
}
}
개발자가 run 메서드를 호출하진 않지만, Container에 의해 run 메서드가 자동으로 호출된다.
일반적으로 모듈 간의 상호작용은 메서드로 이루어진다.
이렇듯 Container가 개발자를 대신하여 메서드가 호출될 때와 메서드가 필요한 자원을 전달하는 설계 구조를 Inversion of Control(IOC)라 한다. IOC는 메서드가 필요로 하는 자원을 코드가 실행되는 타임에 전달하며, 이를 Dependency Injection이라 한다.
IoC(Inversion of Control)는 우리나라 말로 '제어의 역전'이라고 부른다. 다른 많은 프로긂들과는 다르게 제어의 역전 패턴이 자바 웹 개발에서 특히 인기를 끄는 이유는 프로그램의 생명주기에 대한 주도권이 웹 애플리케이션 컨테이너에 있기 때문이다. 예를 들어, 게임 엔진을 만드는 경우에는 초기화, 실행, 종료와 같이 애플리케이션의 흐름 제어에 관한 부분을 직접 만든다. 그리고 실행에는 메인 루프(main loop)가 포함되어 프로그램이 종료되기 전까지 게속 실행 안에서 동작한다.
그런데 자바 기반의 웹 프로그램 개발 시에는 여러분들이 브라우저에 naver.com을 입력하면 그 URL이 DNS 서버를 거쳐 서버에 전달되고, 서버에서는 doGet, doPost와 같은 메서드들이 파라미터와 함께 호출된다. 이런 상황에서 파일 처리나 데이터베이스 처리를 하는 클래스들의 인스턴스 관리를 해야하고, 일괄적으로 인스턴스 관리를 하기 위해서 객체의 생성을 관리할 수 있는 도구의 필요성이 대두되었다. 이와 같은 의미로 디자인 패턴의 원칙 중에는 의존 관계 역전 원칙(Dependency Inversion Principle)이 있다.
의존관계 역전 원칙은 두 가지 내용을 담고 있다.
단순하게 말해서 인터페이스를 활용함으로써 결합도를 낮추게 하자는 뜻이다. 그런데 자바에서는 인터페이스를 사용하더라도 결국 인스턴스화하기 위해서는 반드시 객체 생성에 필요한 코드가 수반되므로 결합도를 완전히 분리해 낼 수 없다. 결국 프로그램이 온전히 동작하기 위해서는 인스턴스화할 수 있는 코드에 대한 의존성을 갖게 된다. 그리고 이를 대신 해결해 주는것이 바로 의존성 주입(DI, Dependency Injection)이다.
의존성 주입은 클래스나 인터페이스들을 사용하기 위해서 해야 하는 행위들, 예를 들어서 고속도로 톨게이트를 통과할 때는 차를 멈추고 손을 뻗어서 통행권을 뽑고 가야한다. 자동차로 고속도로를 주행할 수 있지만 고속도로를 주항해가 위해서 통행권을 뽑는 행위에 대한 의존성을 가지고 있는 것이다. 그런데 하이패스 단말기를 부착한 차량들은 의존성을 하이패스 단말기가 대신 주입해 주므로 의존성에 필요한 행위들을 하지 않고 통과할 수 있다. 이렇게 생각하면 왜 객체 생성 주입 인터페이스 주입 등등의 표현을 쓰지 않고 의존성 주입(DI)이란 용어로 고착되었는지 이해하기 쉬울 것이다. 최근에는 제어의 역전 (IoC)라는 말은 뜻이 너무 광범위하고 일반적 이여서 제어의 역전보다는 의존성 주입을 많이 쓴다.