본문 바로가기

SERVER/Spring

[Spring] IoC와 DI

  •  스프링의 핵심 개념을 나타내는 삼각형 중 가장 처음에 접해볼 만한 IoC와 DI에 대해 이해해보자. 

스프링 삼각형


DI(Dependency Injection) : 의존성 주입.

의존성이 뭐길래 의존성을 주입한다는 걸까? 먼저 의존성에 대한 이해를 돕기 위해 다음과 같은 코드가 있다고 하자. 개발자가 카페를 생성하고, 카페는 내부적으로 오늘의 커피로 아메리카노를 생성한다. Cafe 객체가 Americano 객체를 사용하는 것은, 다른 표현으로는 Cafe가 Americano에 의존한다고 얘기할 수 있다. 이 경우, 개발자가 직접 new 를 이용해서 아메리카노 객체를 생성하고 있으므로, 내부에서 의존성을 만들고 있다고 볼 수 있다.

 

public class Cafe {
    private Coffee today;

    public Cafe() {
        this.today = new Americano();
    }

}

 

그렇다면, 오늘의 커피를 아메리카노가 아닌 라떼로 바꾼다고 해보자. 내부에서 커피를 직접 생성하고 있으므로 클라이언트 코드 뿐 아니라 Cafe 내부 코드가 계속 수정되어야 한다. 

만약, Cafe가 Coffee를 직접 생성하는 것이 아니라, 외부에서 의존성을 주입받는다면, 내부 코드의 수정이 일어나지 않아도 되는 것이다!

 

public class Cafe {
    private Coffee today;

    public Cafe(Coffee today) {
        this.today = today;
    }
}

public class Host{
	public void main(String[] args){
    	Coffee today = new Latte();
    	Cafe cafe = new Cafe(today);
    }
}

 

public class Cafe {
    private Coffee today;
    
    public Coffee getCoffee(){
    	return today;
    }

    public void setCoffee(Coffee today){
    	this.today = today;
    }

}

public class Host{
	public void main(String[] args){
    	Coffee today = new Latte();
    	Cafe cafe = new Cafe();
        cafe.setCoffee(today);
    }
}

 

내부에서 따로 빼서 외부에서 생성된 객체를 주입시켜 생성자나 setter를 통해 사용할 수 있다. 이 경우 오늘의 커피가 변경되어도 Host 코드만 수정하고, Cafe 코드는 그대로 둘 수 있다. DI를 통해 모듈간 결합도(의존성)이 낮아지므로 더 유연하고 효율적인 관리, 유지보수가 가능해진다.

(스프링에서는 객체(스프링 컨테이너가 생성 및 제어하는 객체를)를 Bean이라고 부르고, 객체가 생성되는 곳은 Bean 컨테이너라고 부른다.)

 


IoC(Inversion of Control) : 제어의 역전.

말그대로, 객체에 대한 제어권이 개발자에서 컨테이너로 역전됨을 의미한다. 컨테이너가 직접 Bean(객체)의 생성, 생명주기 관리, 소멸까지의 제어권을 가지고있기에 스프링은 모든 의존성 객체를 스프링이 실행될 때 생성한 후, 필요한 곳에 주입하는 방법으로 제어하게 된다.