의존성 주입.
하나의 객체에서 다른 객체가 필요할 때 객체를 직접 생성하지 않고 이미 생성되어 있는 객체를 가져오는 작업을 DI(Dependency Injection), 의존성 주입이라고 한다.
한 클래스를 수정하였을 때 다른 클래스도 수정해야하는 상황을 막을 수 있다.
의존성 주입은 필요한 객체를 직접 생성하는 것이 아니라 외부로부터 필요한 객체를 받아서 사용하는 것이다.
class Programmer {
private Coffee coffee;
public Programmer() {
this.coffee = new Coffee();
}
public startProgramming() {
this.coffee.drink(); // 일단 마시고 시작하자
...
}
}
위 코드와 같이 Programmer
클래스에서startProgramming
함수가 호출되기 위해서는 Coffee
클래스를 필요로한다.
이것을 'Programmer
클래스는 Coffee
클래스의 의존성을 가진다' 라고 한다.
이처럼 코드를 설계하면 Coffee
클래스가 수정되었을 때 Programmer
클래스도 함께 수정해야하는 문제가 발생한다.
=> 결합도가 높아진다.
만약 DI를 사용하지 않고 Coffee
클래스의 상속을 받은 Cappuccino
나 Americano
클래스를 사용해야한다면 다음과 같이 직접 수정해줘야한다.
class Coffee {...} // interface로 설계할 수도 있다
// Coffee 클래스를 상속
class Cappuccino extends Coffee {...}
class Americano extends Coffee {...}
// Programmer.java
class Programmer {
private Coffee coffee;
public Programmer() {
this.coffee = new Cappuccino(); // 직접 수정
// 또는
this.coffee = new Americano(); // 직접 수정
}
...
}
이것은 매우 비효율적이기 때문에 의존성 주입을 이용하여 다음과 같이 바꿀 수 있다.
// Programmer.java
class Programmer {
private Coffee coffee;
// 그 날 마실 커피를 고를 수 있게된 개발자
public Programmer(Coffee coffee) {
this.coffee = coffee;
}
public startProgramming() {
this.coffee.drink();
...
}
}
의존성 주입은 필요한(의존하는) 클래스를 직접 생성하는 것이 아니라 주입해줌으로써 객체 간의 결합도를 줄이고 좀 더 유연한 코드를 작성할 수 있다.
참고 | Dependency Injection이란 무엇일까?
제어의 역전.
스프링 컨테이너가 필요에 따라 개발자 대신 bean들을 관리(제어)해주는 행위.
객체에 대한 제어권이 컨테이너로 역전되었다.
사용자가 자신이 필요한 객체를 생성해서 사용하는 것이 일반적이지만,
필요한 객체를 요청하면 어디서 어떻게 만들어졌는지 알 필요 없는 객체가 사용자에게 주어진다.
그러면 사용할 객체의 생성자가 바뀌더라도 사용자 입장에서는 알 수 없고 알 필요도 없다.