의존성 주입이란 개념에 대해 알기 위해서는 먼저 의존성이라는 개념부터 알아야 한다.
특정 객체 A의 내용이 다른 외부 객체 B에 의존하는 경우,
A는 B에 의존성을 가진다고 표현한다.
그래서, 의존성을 가진다는 것은 무엇을 의미할까?
코드로 예를 들어 살펴보자.
class Company {
val person:SalaryMan = SalaryMan()
fun doWork() {
person.work()
}
...
}
위 코드에서 Company는 내부에서 SalaryMan 객체를 직접 생성하고 있고,
해당 객체의 함수를 호출하여 사용하고 있다.
따라서 Company 클래스의 내용은 SalaryMan 클래스의 내용에 의존하고 있다.
이로서 두 클래스는 현재 강하게 결합되어 있는 상태이다.
이는 곧 Company 클래스의 내용을 이해하려면 SalaryMan 클래스의 내용을 알고 있어야만 한다는 뜻이고,SalaryMan 클래스의 내용이 변경된다면 Company 클래스의 내용도 함께 변경되어야 한다는 뜻이다.SalaryMan 클래스의 내용이 변경되는 경우를 생각해보자.
class SalaryMan(val salary:Int) {
fun getSalary() = salary
fun doWork(work:Work){
...
}
}
위의 코드처럼 SalaryMan 클래스가 변경되었다고 해보자.
변경된 위 클래스를 현재 Company 클래스가 사용하고 있으므로,
class Company {
val person:SalaryMan = SalaryMan(10000)
fun doWork(){
person.work(Work())
}
...
}
위와 같은 형태로 변경해 주어야 할 것이다.
앞서 언급한 것처럼 SalaryMan 클래스가 변경될 때마다 Company 클래스도 함께 변경되지 않으면 안되는 것이다. 예시로 든 위 코드가 간단해서 변경도 많지 않은 것 뿐,
만일 변경된 사항이 많고, SalaryMan 클래스를 사용하는 곳이 여러 군데 였다면,
사용된 곳마다 꼼꼼히 살피며 변경했어야 할 것이다.이는 유지보수적 관점에서 아주 비효율적인 일이다.
의존성이 존재하는 코드가 가지는 특징들은 다음으로 요약할 수 있을 것이다.
- 클래스 간의 결합도가 증가한다.
- 특정 클래스의 변경이 다른 클래스의 영향을 주게 된다.
- 유지보수적인 관점에서 상당히 비효율적인 구조가 된다.
위에서 클래스 간의 의존 관계가 어떻게 비효율적인지 알아보았다.
그럼 의존성을 약하게 하려면 어떻게 해야할까?
이 질문에서 등장한 것이 의존성 주입(Dependency Injection)이라는 개념이다.
의존성은 특정 클래스 A의 내용을 이해하려면 외부 클래스 B의 내용을 알아야 하는 것이다.
그럼 의존성을 약하게 하려면, B의 내용을 몰라도 A가 동작하는데에 문제가 없도록 하면 된다.
interface Person {
fun doWork()
}
class Company(val person:Person) {
fun doWork() {
person.doWork()
}
}
위 Company 클래스는 여전히 doWork 함수의 내용을 외부 인터페이스 Person에 의존하고 있다.
그러나, Person 인터페이스의 내용을 몰라도,Company 클래스를 이해하거나 동작하는데는 큰 문제가 없다. Comapny 클래스가 생성자를 통해 Person 인터페이스를 외부에서 주입받기 때문이다.
이런 형태라면, Person 인터페이스를 구현한 클래스의 생성자가 변경된다고 해도,
Company 클래스를 변경할 필요가 없다. 또한, doWork 함수의 내용을 변경해도 Company 클래스는 인터페이스의 함수를 그대로 실행하기 때문에 코드를 변경할 필요가 없다.
또한 인터페이스를 생성자로 받기 때문에, doWork를 각기 다르게 구현하여 여러 객체를 넣을 수 있어 이전보다 훨씬 더 유연한 코드라고 할 수 있다.
의존성 주입으로 얻을 수 있는 장점을 요약해보면 다음과 같다.
- 클래스 간의 결합도가 낮아져 클래스의 변경에 영향을 덜 받는다.
- 유지보수적인 관점에서 변경할 요소가 줄어들어 효율적인 구조가 된다.
의존성 주입의 개념에 대하여 알아보았다.
일반적으로 사용되는 의존성 주입은 라이브러리를 통해 구현되는 경우가 많은데,
다음 포스팅에서는 이에 대해 다뤄볼 예정이다.
https://tecoble.techcourse.co.kr/post/2021-04-27-dependency-injection/
https://mangkyu.tistory.com/150
https://medium.com/@jang.wangsu/di-dependency-injection-%EC%9D%B4%EB%9E%80-1b12fdefec4f