나만 보는 일기장

DI Framework - (2) @Inject, @Component 본문

개발/Android

DI Framework - (2) @Inject, @Component

Patrick0422 2021. 9. 6. 20:54

현재 안드로이드에서 쓰는 DI Framework는 Dagger2, Hilt, Koin이 있는데, 내가 이해한 이 셋은 이렇다.

 

Dagger2  | 자바 + 코틀린 사용 가능, 컴파일 할 때 오류 검출, 어렵다

Hilt         | Dagger 기반, Dagger보다 쉽지만 큰 프로젝트에 쓰기엔 아직 이른듯

Koin        | 자바 사용 불가, 런타임에 오류 검출

 

이 셋에 대한 자세한 정보는 아래 글을 읽으면 될 것 같다.

https://velog.io/@sysout-achieve/Android-DI-Framework-%EC%84%A0%ED%83%9D%EC%A7%80Dagger2-Koin-Hilt

 

Gradle 설정

https://github.com/google/dagger - Dagger 깃허브 페이지

// Add Dagger dependencies
dependencies {
  implementation 'com.google.dagger:dagger:2.x'
  annotationProcessor 'com.google.dagger:dagger-compiler:2.x'
}

 

모델 구조

오늘 사용할 예제는 내가 보는 강의에서 쓰는 걸로 가져왔다. 

class SmartPhone (val battery: Battery, val memoryCard: MemoryCard, val simCard: SIMCard){

}

class Battery {

}

class MemoryCard {

}

class SIMCard (val serviceProvider: ServiceProvider) {

}

class ServiceProvider {

}

의존성 구조

이 예제에서 SmartPhone은 Battery, MemoryCard, SIMCard에 의존성을 가지고 있고, SIMCard는 또 ServiceProvider에 의존성을 가진다.

 

@Inject 어노테이션

Dagger2에게 의존성 주입을 맡기기 위해서는 생성자에 @Inject 어노테이션을 통해 권한을 주어야 한다.

class SmartPhone @Inject constructor(
    val battery: Battery,
    val memoryCard: MemoryCard,
    val simCard: SIMCard) {

}

 

 

하지만 위에서 SmartPhone의 생성자엔 매개변수가 3개가 들어가 있는데, 이 3개의 매개변수 또한 @Inject를 해주어야 한다. 그렇게 하지 않으면 Dagger2가 battery와 memoryCard, simCard의 객체를 생성하지 못해 객체를 생성할 수 없을 것이다.

 

모두 @Inject를 적어주면 이런 식으로 나온다.

class SmartPhone @Inject constructor(
    val battery: Battery,
    val memoryCard: MemoryCard,
    val simCard: SIMCard) {

}

class Battery @Inject constructor(){

}

class MemoryCard @Inject constructor(){

}

class SIMCard @Inject constructor(serviceProvider: ServiceProvider){

}

class ServiceProvider @Inject constructor(){

}

 

@Component 어노테이션

이제 의존성 주입을 위해 Dagger2가 자동 생성한 코드를 사용하기 위해서, @Component 어노테이션이 붙은 인터페이스를 생성해야 한다.

 

이 인터페이스에 우리가 선언하는 함수로 의존성 주입이 이루어지게 된다.

함수의 이름은 중요하지 않고, Dagger2는 각 함수의 return 타입으로 역할을 추론하게 된다.

@Component
interface SmartPhoneComponent {
    fun getSmartPhone() : SmartPhone
}

 

Comments