객체 지향 프로그램에서 '다른 객체를 사용하는 것'을 다르게 표현하면 '다른 객체에 의존하는 것'이라고 표현할 수 있다. 이처럼, '의존성'은 예를 들어 서비스로 사용할 수 있는 객체이다.
여기서, 다른 객체를 사용하기 위해서는 객체를 직접 생성하거나 미리 생성되어 있는 객체를 할당받아서 사용할 수 있다.
예를 들어서,
1번 케이스: A객체가 B와 C 객체를 직접 생성하여 사용하면 A는 B,C의 기능을 사용한다고 볼 수 있지만, B, C의 기능에 의존한다고도 볼 수 있다. (A가 갑이고 B, C가 을인 상황)
2번 케이스: A객체가 만들어져 있는 객체를 사용하는 경우(A가 을이요 B, C를 가지고 있는 누군가가 갑인 상황)에는 을인 A가 B나 C의 기능이 필요해 갑인 누군가에게 요청하면 갑이 A에게 B, C의 기능을 주입시켜주는 구조이다.
여기서 객체를 생성하고 라이프 사이클을 관리하고 다른 필요한 객체의 의존주입을 관리해주는 누군가를 컨테이너라 부르는데 스프링이 이 컨테이너의 역할을 한다. 이 컨테이너의 역할을 개발자의 입장에서 보면, 개발자가 객체를 제어하지 않고, 스프링 컨테이너로 객체의 제어권이 넘어갔다는 의미로 IoC(Inversion of Control), 제어의 역전이라고 한다.
정리해보면 1번 케이스는 생성부터 메모리 관리를 위한 소멸까지 해당 객체의 라이프 사이클을 개발자가 다 관리해야 하므로 강한 결합이 되는 것이고, 2번 케이스는 사용만 하면 되기 때문에 약한 결합이 된다. 객체지향 프로그램에서 약한 결합을 사용하게 되면 개발자가 관리할 것이 적어진다는 장점이 있다.
public class ExampleDI {
public static void memberUse1() {
//강한 결합 : 직접 생성
Member m1 = new Member();
}
public static void memberUse2(Member m) {
//약한 결합 : 생성된 것을 주입 받음 - 의존 주입 (Dependency Injection)
Member m2 = m;
}
}
//Member를 사용한다 --> Member의 기능에 의존한다는 의미
class Member{
String name;
String nickname;
private Member() {}
}
- Date와 같이 기존에 만들어져 제공받은 API나 Framework의 기능에도 똑같이 적용이 됨.
import java.util.Date;
public class ExampleDI {
public static void main(String[] args) {
//날짜를 구하기 위해서는 Date 클래스에 의존해야 한다.
Date date = new Date();
getDate(date);
}
public static void getDate(Date d) {
Date date = d;
System.out.println(date);
}
}
DI로 프로그램(약한 결합, 느슨한 결합)을 설계하면