의존성이란?
- 서로 다른 객체 사이에 의존 관계가 있다는 것
주입이란?
- 외부에서 객체(또는 데이터) 를 생성해서 넣는 것 (생성자를 통해)
의존성 주입이란?
- 프로그램 디자인이 결합도를 느슨하게 되도록 하고, 의존관계 역전 원칙과 단일 책임 원칙을 따르도록 클라이언트 생성에 대한 의존성을 클라이언트의 행위로부터 분리하는 것
즉, 기존의 의존성을 개선하여 "(개선된) 의존성을 외부에서 주입할 수 있는 방식" 으로 바꾸는 것이다.
의존성 주입의 장점 / 사용하는 이유 은/는?
- 객체 간의 의존성을 줄여서 코드의 재활용성이 높아진다. / 확장성이 높아진다.
- 객체 간의 결합도가 낮아져 유연한 코드가 된다. / 유연한 프로그램을 작성 가능
- 유지 보수가 쉬워진다.
- Unit Test 가능해진다. (특정 객체에 대한 의존성을 없애고, Test 객체 주입가능해진다.)
참고) 객체지향 프로그래밍(OPP) 의 5대 원칙 중 DIP(= Dependency Inversion Principle, 의존 관계의 분리)에 대한 간략한 설명
- 추상화된 것(= Protocol)은 구체적인 것(= 객체 또는 인스턴스) 에 의존하면 안되고, 구체적인 것이 추상화된 것에 의존해야 한다.
- 즉, 구체적인 객체는 추상화된 객체(프로토콜)에 의존해야 한다는 뜻이다.
의존성 주입 방식
- Constructor Injection (생성자 주입)
- Property Injection (프로퍼티 주입)
- Method Injection (함수 주입)
Constructor Injection (생성자 주입)
class someViewModel {
let dependency: SomeNetworkServiceType
init(dependency: SomeNetworkServiceType) {
self.dependency = dependency
}
func viewModelFunction() {
dependency.fetchData()
print("dependency에서 가져온 data를 business logic으로 처리")
}
}
let dependency = SomeNetworkService()
let viewModel = someViewModel(dependency: dependency)
Property Injection (프로퍼티 주입)
class SomeViewModel {
var denpendency: SomeNetworkServiceType!
func viewModelFunction() {
denpendency.fetchData()
print("dependency에서 가져온 data를 business logic으로 처리")
}
}
let dependency = SomeNetworkService()
let viewModel = SomeViewModel()
viewModel.denpendency = dependency
Method Injection (함수 주입)
class SomeViewModel {
var dependency: SomeNetworkServiceType!
func viewModelFunction() {
dependency.fetchData()
print("dependency에서 가져온 data를 business logic으로 처리")
}
func setUpDependency(_ dependency: SomeNetworkServiceType) {
self.dependency = dependency
}
}
let dependency = SomeNetworkService()
let viewModel = SomeViewModel()
viewModel.setUpDependency(dependency)
결론
- 코드의 확장성과 유지보수성을 생각한다면 의존성 주입은 필수불가결이다.
- 의존성 주입하는 3가지 방법 중 관리하기 쉬운 것은 생성자 주입이다.