Spring Framework 를 처음 접하면 IoC container / Bean / Dependecy Injection 과 같은 용어들을 접하게 된다. 물론 Bean 같은 경우 java bean 을 먼저 들어봤을진 모르겠지만 말이다. 여한튼 이러한 용어들에 대해 간단하게 설명하고 스프링 프레임워크가 어떻게 동작 하는지에 대해 살펴보도록 하겠다.
Inversion of Control Container 의 준말이다. Inversion of Control 에 대해 이해하기 이전에 Container(컨테이너) 라는 단어에 집중하자.
IoC Container 는 Bean 들이 들어있는 컨테이너 이다. 여기서 Bean 이란, IoC Container 가 관리하는 객체 를 의미한다.
절대 어렵게 받아 들이지말고, 최대한 쉽게 받아들이면 된다.
일반적으로 만들어서 사용하는 객체들 그 중 스프링컨테이너 에서 사용할 객체들이 바로 Bean 이고 그런 Bean 들이 들어가있고 관리하는 컨테이너가 IoC 컨테이너 이다.
다음으로, Inversion of Control 에 대해 알아보도록 하자.
한국말로 해석하면 제어의 역전 쯤으로 해석될 수 있는데, 제어의 역전이라는 말이 잘 와닿지는 않는다.
코드를 보며 생각해보록 하자.
public class Computer {
private Mouse mouse;
public Computer(Mouse mouse){
this.mouse = mouse;
}
}
--------------------------------------------
public interface Mouse {
void click();
}
--------------------------------------------
public class G1Mouse implements Mouse {
@Override
public void click() {
System.out.println("G1 Mouse click");
}
}
--------------------------------------------
public class G2Mouse implements Mouse{
@Override
public void click() {
System.out.println("G2 mouse clicked");
}
}
--------------------------------------------
위의 코드를 보면 컴퓨터라는 객체는 마우스 객체를 프로퍼티로 사용하고 있다.
일반적으로 이런 상황에서 우리는 어떻게 컴퓨터를 사용해 왔는가?
컴퓨터 객체를 생성할 때 필요한 마우스 객체를 직접 만들어서 넣어줬다.
그런데 스프링 컨테이너(== Ioc Container) 를 사용하면, 위처럼 직접 필요한 객체를 만들어서 넣어줄 필요가 없다. 마우스 객체를 빈으로 만들어 컨테이너에 등록해두면 필요할때 컨테이너가 알아서 객체를 주입해주는 것이다.
컴퓨터가 사용할 마우스는 어떤 마우스일까?
위처럼 나는 G1Mouse에 @Component 를 붙여 빈으로 등록했고, 등록된 빈은 IoC 컨테이너에 의해 관리되며, Computer 에서 사용할 때, 컨테이너가 자동으로 주입해주게 된다.
이와같이 의존성을 직접 주입하지 않아도 컨테이너가 주입해주기 때문에 Inversion of Control 이라고 하는 것이다. 그렇다면 Spring Framework 가 왜 이러한 IoC컨테이너, Bean 과같은 개념을 사용하는지에 대해 생각해 볼 필요가 있다.
먼저, 결합도가 낮아진다.
만약 다양한 컴퓨터 객체가 있고 그 컴퓨터들이 G1Mouse를 사용하다 G2Mouse로 변경해야된다고 생각해보자. 의존성 때문에 높아진 결합도로 굉장히 작업이 귀찮아 지고 큰 사이즈의 프로젝트라면 일일이 찾아 고치는 일은 굉장히 큰 작업이 될 것이다. 하지만 스프링컨테이너를 사용한다면 해야할 일은 @Component 를 G1Mouse 에서 G2Mouse로 변경하기만 하면 된다.
결합도에 대해서 조금 더 쉽게 느끼기 위해 결합도를 더 높인 코드를 보도록 하겠다.
두 번째, 메모리적으로나 성능적으로 유리할 수 있다.
빈의 스코프는 기본적으로 Singleton 이다. (필요하다면 바꿔줄 수도 있다) 그래서 앱을 구동할때 빈들을 모두 생성해 컨테이너가 관리하게 된다. 따라서 무의미하게 여러 객체가 생성되어 메모리를 잡아먹는일을 방지할 수 있고, 또 구동 이후에 빈에 등록된 객체들은 생성할 필요가 없기 때문에 객체를 생성하는데 사용될 자원들을 아낄 수 있는 것이다.
설명을 보면 알 수 있듯이 무조건적으로 메모리, 성능에 뛰어나다는 말은 아니지만 대부분의 상황에서 그러할 것이라는 걸 알 수 있다.