본 포스팅은 Dagger에 대한 내용을 다루며, 아래 문서를 베이스로 작성되었습니다. 아직 번역되지 않은 문서다 보니 학습 목적으로 재정리를 해보았습니다.


얼마 전 Android Dev Submit 2019이 있었습니다. Day 2 때 “An Opinionated Guide to Dependency Injection on Android” 제목의 세션이 있었습니다. 바로 결론부터 이야기하자면 Android에서 Dependency Injection으로 Dagger를 사용하라는 내용의 광고(?)입니다.

19분의 짧은(?) 분량이니 시간날 때 한번 보시기 바랍니다.

Dagger! Recommended by Google!

Gmail, Photos, Youtube 등 구글 앱에서도 이미 사용하고 있답니다.

Dependency Injection

Dagger를 이야기하기 전에 DI 이야기를 안할 수가 없습니다. DI를 알지 못하고서는 Dagger를 논할 수가 없는데, Dagger가 DI (Dependency Injection)를 도와주는 툴이기 때문이죠.

아래와 같은 코드를 보시죠. MoviesPresenter에서는 포스팅을 가져오기 위해 MoviesRepository 의존성을 갖고 있습니다. 이때 MoviesRepository를 의존성 (dependency) 라고 하며, MoviesPresenter가 MoviesRepository에 의존한다고 표현합니다.

class MoviesPresenter: MoviesContract.Presenter {

    private val moviesRepository: MoviesRepository = MoviesRepository()
    // ...
}

그런데 위 코드에서 MoviesRepository가 생성되는 부분을 보면, MoviesPresenter 안에서 직접 생성하고 있습니다. 이렇게 직접 생성하게 되면 두 객체가 서로 단단히 결합하게 되어 이후 코드 변경에 대응하기가 어려워 집니다. Scale, Testing 관점에서 다소 취약해지는 부분이죠. 관련해서 익히 배운 개념이 있죠?

낮은 결합도, 높은 응집도

high coherence and low coupling

결합도는 낮추고, 응집도를 높여야 합니다. 그럼 위와 같이 결합도가 높은 코드를 어떻게 낮출지 보겠습니다.

class MoviesPresenter(
    private val moviesRepository: MoviesRepository
): MoviesContract.Presenter {
    // ...
}

이전 코드와 다르게 MoviesRepository를 생성하고 있지 않습니다.

여기서 잠깐!

Injection 뜻이 뭐죠?
바로 “주입”이란 뜻을 갖고 있습니다.
즉 Dependency Injection은 “의존성 주입”입니다.

이제 다시 위 코드를 보면 외부에서 MoviesRepository 객체를 생성하여 MoviesPresneter 생성자 인자로 주입시켜주는 것이 보이시나요?

처음에 보면 별거 아닌 차이같지만, 이 작은 차이는 추후 기능 확장/변경과 테스트 코드 작성 시 어마어마한 이점을 가지고 오게 됩니다.

Why Dagger?

DI에 대해서는 간단히 이해했는데, 그래서 왜 Dagger를 써야 하나 궁금할 겁니다. 사실 저 역시 많은 앱들을 만들었지만, Dagger를 쓴 적은 없습니다. 위에서 보여드린 것처럼 직접 의존성을 주입해주었죠. 공식 문서에서도 다음과 같은 표를 제시하며 필요에 따라 의존성 주입 방법을 결정하라고 가이드하고 있습니다.

https://developer.android.com/training/dependency-injection#choosing-right-di-tool

제 경우는 개인 프로젝트의 경우 규모가 작기 때문에 굳이 Dagger를 쓰지 않았고, 실무 프로젝트에서의 경우는 규모는 있지만 팀원들과의 합의가 이루어지지 않아 사용하지 않았습니다. (팀원들 뿐만 아니라 저 역시 준비가 안되어 있기 때문에…)

위에서 예를 들었던 코드가 아래와 같이 확장되는 경우를 보시죠.

class MoviesPresenter(
    private val moviesRepository: MoviesRepository,
    private val usersRepository: UsersRepository,
    private val thumbnailsRepository: ThumbnailsRepository,
    private val favoritesRepository: FavoritesRepository,
    ...
): PostingsContract.Presenter {
    // ...
}

MoviesRepository 뿐만 아니라 다양한 의존성이 필요해진 경우입니다. ( 물론 그냥 예시니 참고만 하세요. ) 이런 경우 외부에서 각 객체를 생성해서 주입해줘야 하며 앞으로 이런 변화가 계속 될 경우 코드 변경량이 많아지고 관리 포인트가 점점 늘어나게 됩니다.

이런 부분을 개선하고자 등장한 것이 바로 DI Tool입니다. Java 진영에서는 Spring이 대표적이고, Dagger 외에 Koin도 주목받았었죠.
(구글에서 이번에 Dagger를 Recommend 하고, 공식 문서, 코드랩을 제공했기 때문에 이제 Dagger로 평정된 것 같긴 합니다.)

다음 포스팅부터 Dagger에 대해 본격적으로 알아보도록 하겠습니다.


0 Comments

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다