안드로이드 모듈 구성

이 문서는 안드로이드 모듈을 구성할 때 고려할 사항들을 설명한다. 다음 내용들은 추천 사항이며, 프로젝트나 모듈에 따라 다른 구성을 가질 수 있다.

가이드라인

  • 신규로 작성되는 모듈은 가능한 Kotlin 으로 구성한다.
  • 의존성 주입 패턴(Dependency injection pattern)을 적극적으로 활용한다.
  • 신규 모듈은 버즈빌 안드로이드 단일 리포지터리(Monorepo)인 buzz-android 에 생성한다.

모듈 생성

단위 기능으로 의미가 있고 여러 모듈에서 사용될만한 기능이라면 신규 모듈을 생성하는 것을 권장한다.

신규 모듈 생성 시 모듈 디자인과 리뷰 과정을 선행해야 하며 이를 통해 디자인 문서를 생성한다. 이후 작성한 디자인 문서를 바탕으로 적절한 레이어에 모듈을 생성하고, Readme, 기본 라이브러리, 버전, 배포, Proguard 설정을 작성한다.

앱 모듈

일반적인 application / sdk 를 구성하는 모듈 계층이다. 시스템의 최상위에서 각 모듈의 디펜던시와 조립을 담당하며 비지니스 로직은 포함하지 않는다.

앱 모듈은 피쳐 모듈과 라이브러리 모듈의 접근 권한을 갖고 있으며, 시스템 전체 의존성 주입을 관리한다.

앱 모듈은 /app 폴더 안에 생성한다.

피쳐 모듈

유저가 사용하는 단위 기능을 제공하는 모듈 계층이다. 기능별로 비지니스 로직을 포함하고 있으며 직접 구현 혹은 라이브러리 모듈을 사용하여 구현을 완성한다.

피쳐 모듈은 다른 피쳐 모듈과 라이브러리 모듈을 참조 할 수 있다. 일반적인 경우 동일 레이어 모듈 간에는 참조를 권하지 않으며, 참조를 해야 하는 경우 순환 참조가 일어나지 않도록 주의해야 한다.

피쳐 모듈은 /feature 폴더 안에 생성한다.

라이브러리 모듈

여러 피쳐 모듈에서 재사용하는 단위 로직을 분리하여 라이브러리 모듈로 구성한다. 피쳐 모듈과 라이브러리 모듈의 구분은 정확히 규칙을 정의하기에 모호한 경우가 있지만, 일반적으로 유저 관점에서의 기능인지를 주요 구분 팩터로 여긴다.

라이브러리 모듈은 다른 라이브러리 모듈을 참조 할 수 있다. 일반적인 경우 동일 레이어 모듈 간에는 참조를 권하지 않으며, 참조를 해야 하는 경우 순환 참조가 일어나지 않도록 주의해야 한다.

피쳐 모듈은 /lib 폴더 안에 생성한다.

모듈 구성

build.gradle 가이드라인

디펜던시 버전 관련 값은 rootProject.ext에 정의된 변수를 사용한다. 이를 통해 전체 모듈이 같은 디펜던시를 가지고 있게 유지할 수 있으며, 의존성 지옥(Dependency hell)으로 빠지는 것을 방지할 수 있다.

디펜던시 추가 시 implementationapi 등 의존성 설정의 차이를 분명히 파악하고 적합한 키워드를 사용한다. 내부 디펜던시를 숨김으로서 빌드 성능을 최적화 할 수 있고, 모듈을 사용할 때 복잡성을 낮출 수 있다. 자세한 내용은 Dependency configurations 문서를 참조한다.

기본 라이브러리 구성

RxJava / RxKotlin

implementation "io.reactivex.rxjava2:rxkotlin:$rootProject.ext.rxKotlinVersion"

RxJava는 옵져버 패턴(Observer Pattern)과 이터레이터 패턴(Iterator Pattern), 함수형 프로그래밍(Functional Programming)의 아이디어들로 구성된 라이브러리다. 이를 활용해서 비동기적인 동작을 손쉽게 구성할 수 있다.

RxJava를 활용해서 콜백 지옥(Callback hell)을 벗어날 수도 있다. Single을 활용해서 네트워크 요청 같은 비동기(Asynchronous) 동작의 데이터 스트림(Data Stream)을 제어할 수도 있다. 자세한 활용법은 ReactiveX를 참고한다.

Dagger 2

implementation "com.google.dagger:dagger:$rootProject.ext.daggerVersion"
implementation "com.google.dagger:dagger-android-support:$rootProject.ext.daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$rootProject.ext.daggerVersion"
annotationProcessor "com.google.dagger:dagger-android-processor:$rootProject.ext.daggerVersion"

Dagger는 자바와 안드로이드를 위한 의존성 주입(Dependency injection) 라이브러리다. Dagger를 활용해서 의존성 주입 패턴을 쉽게 구성하고 테스트할 수 있다. 의존성 주입의존성 역전 원칙에 대해서는 각각 링크된 문서들을 참고한다.

모듈 내 의존성 주입

모듈 내부에서 사용하는 의존성의 경우 Dagger의 @Component, @Subcomponent, @Module 선택 이용하여 구성한다.

Feature Layer

일반적으로 피쳐 모듈의 경우 @Component 혹은 @Subcomponent를 사용하여 별도로 의존성을 관리할 수 있도록 한다.

@Component(modules = [LibraryModule::class])
interface FeatureComponent {
    fun inject(view: View)
}
@Subcomponent(modules = [LibraryModule::class])
interface FeatureSubcomponent {
    fun inject(view: View)
}
Library Layer

라이브러리 모듈은 별도의 Scope 관리가 필요한 경우가 아니라면 @Module을 제공하는 것으로 구현을 마무리한다.

@Module
object LibraryModule {
    @Provides
    fun provideSome() = Some()
}

버즈빌, 아마도 당신이 원하던 회사!

지원하기