Dagger2의 IOC Container 구성
앞의 글에서 Dagger2의 3가지 구성요소 Container, Module, Provider에 대해 배웠다.
- Component : 클래스의 인스턴스를 모아놓는 저장소(Container) 역할. 각 인스턴스들은 Module 단위로 제공된다.
- Module : Module 단위로 클래스의 인스턴스를 모아놓는 역할
- Provider : 클래스의 인스턴스를 제공(Provide)해주는 역할
이제 각 부분이 어떤 역할을 하는지 알았으므로 더욱 상세히 정리해보고자 한다.
Dagger2을 이용해 의존성 주입 구현하기
앞의 글에서 다음과 같은 그림을 본 적이 있다.
<그림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을 만들 것이다.
패키지 구조는 <그림4>와 같으며
코드는 다음과 같다. 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)폴더에 다음과 같은 클래스들을 생성해준다.
바로 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
}
최종적인 구조는 다음과 같이 된다.
정리
즉, 우리가 구현하는 Component는 Interface이며, Dagger에서 해당 인터페이스를 구현하는 클래스를 자동 생성해주며, 해당 클래스를 통해 Provider에 의해 제공되는 변수를 Inject할 수 있었다.
자 이제 흐름을 파악했으면 다음 글에서는 어떻게 의존성을 주입하는지 알아보자.