본문 바로가기
Programando/Android

[Android/Kotlin] DI(Dependency Injection)

Dependency란?

코드에서 두 모듈 간의 연결. 객체지향언어에서는 두 클래스 간의 관계라고도 말합니다. 일반적으로 어떤 클래스 A가 다른 클래스(또는 인터페이스)B를 이용할 때 A가 B에 의존한다고 합니다.

이러한 의존성에는 문제점이 있는데 만약 의존 대상인 B 클래스(또는 인터페이스)가 사라지면 A 클래스는 바로 컴파일이 불가능해지고 동작할 수 없는 상태가 되는 등 코드의 재사용성유연성을 떨어트려 코드의 유지보수를 어렵게 하는 원인이 됩니다.

 

Tight Coupling된 기존의 코드

class DataSource {
    fun getTasks() { }
}
class Repository {
    private val localDataSource: DataSource = DataSource()

    fun getTasks() {
        localDataSource.getTasks()
    }
}
fun viewModel() {
    val repository: Repository = Repository()
    repository.getTask()
}

Repository 클래스의 안에서 DataSource 객체가 생성됩니다.

즉, Repository 클래스를 만들려면 무조건 DataSource 객체가 내부에서 생성되어야 합니다. DataSource클래스 생성 없이는 Repository 클래스가 존재할 수 없기 때문에 Tight하게 Coupling되어 강한 의존성을 가집니다.

 

DI란?

Dependency Injection(의존성 주입)의 약자로 위에서 설명한 Dependency의 문제점을 해결하기 위해서 사용합니다. 즉, "객체끼리의 의존성"을 줄이거나 없앨 수 있는 디자인 패턴입니다.

여기서 말하는 Injection내부가 아닌 외부에서 객체생성해서 넣어준다는 뜻입니다.

 

의존성 주입 방법

안드로이드에서는 다음과 같은 두 가지 방식의 의존성 주입이 가능합니다.

 

반응형

 

생성자 주입(Constructor Injection)

클래스의 종속 항목을 생성자에 전달합니다.

생성자 주입(Constructor Injection) 예제 코드

class DataSource {
    fun getTasks() { }
}
class Repository(private val localDataSource: DataSource) {
    fun getTasks() {
        localDataSource.getTasks()
    }
}
fun viewModel() {
    val localDataSource: DataSourche = DataSource()
    val repository: Repository = Repository(localDataSource)
    repository.getTasks()
}

 

필드 주입/세터 주입(Field Injection/Setter Injection)

활동 및 프래그먼트와 같은 특정 Android 프레임워크 클래스는 시스템에서 인스턴스화하므로 생성자 주입이 불가능합니다. 필드 주입을 사용하면 종속 항목은 클래스가 생성된 후 인스턴스화됩니다.

필드 주입(Field Injection) 예제 코드

class DataSource {
    fun getTasks() { }
}
class Repository() {
    lateinit val localDataSource: DataSource
    fun getTasks() {
        localDataSource.getTasks()
    }
}
fun viewModel() {
    val repository: Repository = Repository()
    repository.localDataSource: DataSource = DataSource()
    repository.getTasks()
}

 

Dependency Injection의 대안

서비스 로케이터(Service Locator)

Dependency Injection 대신 Service Locator를 사용할 수도 있습니다. 서비스 로케이터 디자인 패턴은 구체적인 의존성으로부터 클래스 분리를 향상시킵니다.

의존성을 생성하고 저장한 다음 필요에 따라 이러한 의존성을 제공하는 Service Locator라고 하는 클래스를 만듭니다.

서비스 로케이터(Service Locator) 예제 코드

class DataSource {
    fun getTasks() { }
}
object ServiceLocator {
    fun getDataSource() : DataSource = DataSource()
}
class Repository() {
    private val localDataSource: DataSource = ServiceLocator.getDataSource()
    fun getTasks() {
        localDataSource.getTasks()
    }
}
fun viewModel() {
    val repository: Repository = Repository()
    repository.getTasks()
}

 

그 외

자료 참조

https://developer.android.com/training/dependency-injection 

https://tony-programming.tistory.com/entry/Dependency-의존성-이란

https://jade314.tistory.com/entry/의존성-주입-방법-생성자-주입-서비스-로케이터-Dagger등-라이브러리

반응형