관리 메뉴

나만을 위한 블로그

[Android] 모듈 생성 시 Android Library, Java or Kotlin Library 선택 방법 본문

Android

[Android] 모듈 생성 시 Android Library, Java or Kotlin Library 선택 방법

참깨빵위에참깨빵_ 2025. 9. 11. 23:13
728x90
반응형

이전에 app, data, domain, presentation의 4가지 모듈로 멀티 모듈을 구성하는 포스팅을 썼었다.

 

https://onlyfor-me-blog.tistory.com/1052

 

[Android] 멀티 모듈 프로젝트 구성하고 hilt 적용하기

지금까지 app 모듈 안에 data, domain, presentation 폴더를 만들고 그 안에서 작업해 온 사람도 있을 것이다.그러나 이렇게 하면 삐끗하면 클린 아키텍처를 어길 수 있으니, 실제로 저 이름을 가진 모듈

onlyfor-me-blog.tistory.com

 

방법을 확인하기 전에 사족을 좀 쓰려고 한다.

모듈을 생성할 때 가장 큰 고민 중 하나는 Android Library와 Java or Kotlin Library 중 뭘 선택하냐일 것이다.

이건 이지선다로 선택할 수 있다. 아래의 질문에 맞다고 답한다면 Android Library를 선택해 모듈을 만들면 된다.

 

  • 모듈 내에 안드로이드 의존성(임포트문에서 android.로 시작하는 패키지)이 포함된 파일이 있어야 하는가?

 

예를 들어 android.os.Bundle, androidx.activity.ComponentActivity 같이 android로 시작하는 패키지가 단 1개라도 있어야 한다면 Android Library로 만들어야 한다. 순수 자바 / 코틀린 모듈로 만들면 안드로이드 의존성 없이 자바 / 코틀린만으로 작동하는 로직을 담을 모듈을 만들겠다는 뜻이기 때문에, 당연히 android로 시작하는 패키지를 쓸 수 없다. 쓰더라도 찾을 수 없다는 컴파일 에러만 발생한다.

그래서 Android Library 모듈 대신 순수 코틀린 모듈을 만들고, 인터페이스로 추상화해서 상위 모듈인 Android Library 모듈에서 구현하는 방향을 고려해야 한다.

 

당연히 무슨 말을 하는 건지 이해가 안 될 수 있다. 위에서 말한 android.os.Bundle을 써야 하는 경우를 예시로 들어본다.

순수 코틀린만 존재하는 domain 모듈에서 Bundle을 써서 뭔가 저장하고 불러와야 하는 상황이 왔다고 가정한다.

domain 모듈 특성 상 Bundle을 사용할 수 없으니 인터페이스를 사용한 추상화로 Bundle을 사용하는 로직의 실제 구현을 다른 모듈에 떠넘기는 것이다.

예를 들어 domain 모듈에 아래와 같은 인터페이스를 만든다.

 

interface KeyValueStore {
    fun putString(key: String, value: String)
    fun getString(key: String): String?
}

 

그리고 domain 모듈에 있는 usecase 등이 이 인터페이스에 의존하게 만든다.

 

class UserUseCase(private val store: KeyValueStore) {
    fun saveUserName(name: String) = store.putString("username", name)
    fun loadUserName(): String? = store.getString("username")
}

 

이 domain 모듈의 의존성은 보통 presentation 모듈에 존재할 테니, presentation 모듈에 KeyValueStore를 구현한 Bundle을 사용하는 로직을 작성한다.

 

class KeyValueStoreImpl(private val bundle: Bundle) : KeyValueStore {
    override fun putString(key: String, value: String) = bundle.putString(key, value)
    override fun getString(key: String) = bundle.getString(key)
}

 

이후에는 UserUseCase의 인스턴스를 제공할 때 생성자 매개변수로 KeyValueStoreImpl을 주입하면 된다.

hilt를 사용한다면 provide 함수도 잊지 말고 만들어 준다. usecase의 provide 함수 구현은 생략한다.

 

@Module
@InstallIn(ActivityComponent::class)
object BundleModule {

    @Provides
    fun provideKeyValueStore(activity: ComponentActivity): KeyValueStore {
        val bundle = activity.intent.extras ?: Bundle()
        return BundleKeyValueStore(bundle)
    }
}

 

반응형
Comments