안녕하세요.
이번 포스팅에서는 DI(dependency injection)와 DIP(dependency inversion principle)를 간략하게 구현해 보겠습니다.
dependency injection, 의존성 주입이란 간단하게 말해 어떤 클래스에서 다른 클래스를 사용 시, 자신이 사용할 클래스의 객체를 직접 생성하는 것이 아니라 외부에서 생성된 객체를 주입받아 사용하는 것을 뜻합니다.
dependency inversion principle, 의존관계 역전 원칙이란 상위에 있는 클래스가 하위에 있는 클래스를 사용 시, 해당 클래스를 직접 참조하는 것이 아닌 interface를 통해 상위 클래스와 하위 클래스 모두가 해당 interface에 의존하도록 구현하는 원칙입니다.
이제 예제 소스를 구현하겠습니다.
언어: 코틀린
sdk vsersion
- compile: 33
- min: 21
- target: 33
dependency injection에는 hilt를 사용합니다.
hilt와 관련된 내용은 아래 포스팅을 확인해 주세요.
https://it-of-fortune.tistory.com/26
적용은 다른 포스팅에서 작성한 소스에 이어서 진행하겠습니다.
https://it-of-fortune.tistory.com/34
먼저, PetRepository interface를 생성합니다.
PetRepository.kt
interface PetRepository {
fun getCat(): Pet
fun getDog(): Pet
}
기존에 있던 PetRepository는 PetRepositoryImpl로 이름을 수정하고 PetRepository interface를 implement 합니다.
PetRepositoryImpl.kt
class PetRepositoryImpl @Inject constructor(
private val petRemoteDataSource: PetRemoteDataSource,
private val petLocalDataSource: PetLocalDataSource
) : PetRepository{
override fun getCat(): Pet {
return petRemoteDataSource.getCat()
}
override fun getDog(): Pet {
return petLocalDataSource.getDog()
}
}
DataSource도 마찬가지로 interface를 작성하고 기존의 dataSource 클래스에서 implement 합니다.
PetLocalDataSrouce.kt
interface PetLocalDataSource {
fun getDog(): Pet
}
PetLocalDataSourceImpl.kt
class PetLocalDataSourceImpl @Inject constructor() : PetLocalDataSource {
override fun getDog(): Pet {
return Pet(
name = "바둑이",
age = 5
)
}
}
PetRemoteDataSrouce.kt
interface PetRemoteDataSource {
fun getCat(): Pet
}
PetRemoteDataSourceImpl.kt
class PetRemoteDataSourceImpl @Inject constructor() : PetRemoteDataSource {
override fun getCat(): Pet {
return Pet(
name = "나비",
age = 3
)
}
}
이렇게 하면 의존성 역전 작업을 마치게 됩니다.
이제 의존성 주입을 작업하겠습니다.
interface는 module을 통해 생성되어 주입해야 합니다.
DataModule abstract class를 생성하고, 아래와 같이 작성합니다.
DataModule.kt
@InstallIn(SingletonComponent::class)
@Module
abstract class DataModule {
@Binds
abstract fun providePetRepository(
petRepositoryImpl: PetRepositoryImpl
): PetRepository
@Binds
abstract fun providePetLocalDataSource(
petLocalDataSourceImpl: PetLocalDataSourceImpl
): PetLocalDataSource
@Binds
abstract fun providePetRemoteDataSource(
petRemoteDataSourceImpl: PetRemoteDataSourceImpl
): PetRemoteDataSource
}
이제,
viewModel -> repository interface <- repositoryImpl -> dataSource interface <- dataSourceImpl
이런 식의 관계가 형성되었고 각자 필요한 객체를 의존성 주입을 통해 사용할 수 있게 되었습니다.
정상적으로 refactoring 되었습니다.
이상 포스팅을 마치겠습니다.
감사합니다.
'Android Application > 앱 설계' 카테고리의 다른 글
안드로이드 컴포즈(jetpack compose) - state hoisting (0) | 2023.04.07 |
---|---|
안드로이드 Repository pattern 간단 예시(with MVVM pattern) (0) | 2023.04.03 |
안드로이드 MVVM 패턴 예시 (0) | 2023.04.01 |
댓글