왜 필요할까
printer로 출력하는 간단한 요구가 있을 때
Printer 클래스를 만들어서 Controller가 Printer 클래스를 이용하여 출력하도록 구현하고, 실제로 사용하는 Main에서는 Controller만 알도록 한다.
Web으로도 보여지게 해달라는 추가 요구가 있을 경우
여러 구현 방법이 있을 수 있지만, 여기서는 Controller가 Printer와 Web의 객체를 가지고 있고 각 각의 구현체를 사용하는 메서드를 만들었다. 위에서 말한 것 처럼 Main에서는 Contorller를 통해 하고자 하는 방식으로 사용한다.
구조를 조금 개선해보면
구조를 조금 개선해보면, Presenter라는 interface를 만들어서 Printer와 Web이 이를 구현하도록 하여 Controller에서는 Presenter 타입의 속성을 가지도록 하고, 사용할 때 new Controller(new Printer()) 또는 new Controller(new Web())과 같은 방법으로 구체 클래스에 대한 의존 관계를 끊고 추상 클래스에 의존하게 된다. 이렇게 직접적으로 의존성을 주입해주는 것을 Manual-Dependecny Injection이라고 한다. 틀린 설명일 수 있어서, 자세한 설명은 안드로이드 개발자 사이트 Manual dependency injection에서 볼 수 있다.
Dependency Injection
Dependency
두 개의 클래스 또는 모듈이 의존관계에 있다고 할 때, 방향성을 가져야 한다. 의존 한다는 건 의존대상이 변하면 그것에 의존하고 있는 클래스/모듈도 영향을 받는다는 것을 의미한다. 위의 두번째 상황에서 다른 방식의 출력이 추가될 경우 혹은 각각의 출력 구체 클래스가 변경되는 경우 Controller도, Main도 영향을 받기 때문에 Controller는 출력 방식인 구체 클래스에, Main은 Controller에 의존 한다고 할 수 있다.
(반대로, Controller 클래스는 Main에, 구체 클래스들은 Controller를 모르기 때문에 의존하지 않는다 하고, 의존하지 않는다는 것은 영향을 받지 않는다는 것이다.)
Injection
의존성을 사용하려는 객체(클라이언트)에 넘겨주는 것
DI의 동작 방식은 이름 그대로 외부로부터의 주입이다. 하지만 단지 외부에서 파라미터로 오브젝트를 넘겨줬다고 해서, 즉 주입해줬다고 해서 다 DI가 아니라는 점을 주의하자. 주입받는 메서드 파라미터가 이미 특정 클래스 타입으로 고정되어 있다면 DI가 일어날 수 없다. DI에서 말하는 주입은 다이나믹하게 구현 클래스를 결정해서 제공받을 수 있도록 인터페이스 타입의 파라미터로 이뤄져야 한다.
<토비의 스프링 3.1> 1.7 의존관계 주입(DI)