Image
Android/Dependency Injection

[Dagger2] 2. Dagger2에서 Injection이 일어나는 방식

Dagger2의 IOC Container 구성

앞의 글에서 Dagger2의 3가지 구성요소 Container, Module, Provider에 대해 배웠다.

그림1. Dagger2의 구성요소

  • Component : 클래스의 인스턴스를 모아놓는 저장소(Container) 역할. 각 인스턴스들은 Module 단위로 제공된다.
  • Module : Module 단위로 클래스의 인스턴스를 모아놓는 역할
  • Provider : 클래스의 인스턴스를 제공(Provide)해주는 역할

이제 각 부분이 어떤 역할을 하는지 알았으므로 더욱 상세히 정리해보고자 한다.

 

Dagger2을 이용해 의존성 주입 구현하기

앞의 글에서 다음과 같은 그림을 본 적이 있다.

그림2. CPU 인터페이스화

<그림2>는 의존성을 약화시키기 위한 인터페이스의 역할에 대해 설명하면서 나온 그림이다. CPU Time을 구하기 위해  CPU Time을 구하는 함수를 가진 CPU Interface를 둠으로써 CPU Time을 특정 클래스에 의존하지 않고 가져올 수 있었다.

 

Dagger2의 Component에 대해 조금 더 깊이 들어가면 Component는 <그림2>의 방식으로 인터페이스 역할을 하게 된다. 아래 예제1에서 어떻게 Component가 인터페이스 역할을 하는지 살펴볼 수 있다. 지금부터는 실 코드의 예제와 함께한다.

 

예제1

예제 링크 : https://github.com/seyoungcho2/Dagger2Example

먼저 우리는 다음과 같이 String을 제공(Provide)하는 구조로 String Component와 String Module을 만들 것이다. 

그림3. 예제1 Component, Module, String 구조

패키지 구조는 <그림4>와 같으며

그림4. 예제1 패키지 구조

코드는 다음과 같다. RunExample.kt는 아래에서 확인 가능하다.

@Component(modules = [StringModule::class])
interface StringComponent{
    fun injectString(student: Student)
}
@Module
class StringModule {
    @Provides
    fun providesString() = "StringA"
}
class Student(){
    @Inject lateinit var name: String
}

그런데 이 코드들에서 신기한 점이 있다. StringComponent가 interface로 되어있는 것이다. Dagger에서는 컴파일 타임에 Component Interface의 Annotation을 읽어 java(generated)폴더에 다음과 같은 클래스들을 생성해준다.

그림5. 자동으로 생성되는 DaggerStringComponent

바로 StringComponent Interface를 구현하는 DaggerStringComponent 클래스를 생성해주는 것이다. 

public final class DaggerStringComponent implements StringComponent {
  ..
  public static StringComponent create() {
    return new Builder().build();
  }
  ..
  private Student injectStudent(Student instance) {
    Student_MembersInjector.injectName(instance, StringModule_ProvidesStringFactory.providesString(stringModule));
    return instance;
  }
  ..
}

 

DaggerStringComponent 클래스에서는 StringComponent Interface를 구현하는 DaggerStringComponent 객체를 반환하는 create()란 메서드를 제공한다. 이를 이용해 만들어진 DaggerStringComponent 인스턴스로 Student에 Inject를 하게 되면 String 타입으로 되어 있는 name 필드가 Inject되는 것이다.

 

우리는 이렇게 만들어진 DaggerStringComponent를 다음과 같이 사용할 수 있다. *RunExample.kt

fun main(){
    val person = Student()
    DaggerStringComponent.create().injectString(person)
    println(person.name) // StringA
}

 

최종적인 구조는 다음과 같이 된다.

그림6. Injection Using Dagger

 

정리

즉, 우리가 구현하는 Component는 Interface이며, Dagger에서 해당 인터페이스를 구현하는 클래스를 자동 생성해주며, 해당 클래스를 통해 Provider에 의해 제공되는 변수를 Inject할 수 있었다.

 

자 이제 흐름을 파악했으면 다음 글에서는 어떻게 의존성을 주입하는지 알아보자.

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com