DI는 객체 지향 설계5원칙(SOLID) 중 Dependency Inversion Principle과 관련이 깊다.
💡 Dependency Inversion Principle(의존 관계 역전원칙)
상위 레벨의 객체가 하위 레벨의 객체에 의존하는 현상을 끊는것.
상위객체가 하위객체에 의존하게 된다면 하위객체가 변경될때 상위객체또한 변경해야하기 때문에 최대한 의존성을 없애는게 유지/보수에 효율적이다.
다시 말하자면 DI에는 의존 관계 역전원칙
의 개념을 내포하고있다.
DI의 핵심개념을 나누어 설명하자면 아래와 같다고 볼 수 있다.
내부에서 사용할(의존할) 객체를 외부에서 주입시키기
의존성 분리 - 객체에 의존하지말고 역할에 의존하자
첫 번째로는 내부에서 사용할 객체를 외부에서 생성하여 주입시키는 방법이다.
하위객체(내부객체)의 생명주기를 객체 내에서 담당한다고 생각해보자.
객체는 오직 해당 하위객체에 완전의존하여 해당 객체가 아닌 다른 객체로의 수정이 어려워진다.
즉, 외부 주입으로 얻을 수 있는 장점은 아래와 같다.
외부에서 주입한다고는 하나 여전히 한 타입의 객체에 의존할 수 밖에 없는 상황이다.
의존성을 분리할 수 있는 방법이 없을까?
외부에서 주입하더라도 한 타입의 객체만 주입할 수 있다면 유지,보수 시 상위/하위 객체를 모두 수정하게 되는 문제가 발생한다.
이런 문제점을 해결하기 위해방법이 바로 추상화(interface)에 의존하는 것이다.
객체에 의존하는 것이 아닌 역할을 정의하는 추상화에 의존함으로써 해당 역할에 대한 책임을 가지는 모든 객체로 수정이 가능해진다.
이 개념이 바로 IoC(Inversion Of Control)이다. 의존관계가 존재하는 두 객체를 추상화(역할)에 의존시키게 만드는 방법이다.
(예시 코드)
이를 통해 얻을 수 있는 장점이다.
하지만 여전히 문제점은 남아있다.
생명주기를 외부에서 관리함으로써 생기는 메모리 효율성에 대한 문제와 그에 따라 늘어나는 코드의 복잡성이다.
외부에서 생명주기를 책임지다 보면 같은 객체를 여러번 생성하는 문제가 비일비재할 것이다.
뿐만 아니라 DI를 직접구현하게 되면서 생기는 여러 보일러플레이트 코드들이 존재한다.
시스템이 커지면 커질수록 위 문제에 대한 복잡성이 높아지는데 이를 해결해주는 것이 DI Container 프레임워크다.
이 프레임워크는 객체 생성 책임과 객체 주입의 책임을 가지며 위의 문제점들을 해결해준다.
DI Container 내부에서 주입되는 객체들은 싱글톤 객체로 동작하여 메모리 효율을 줄여준다.