본문 바로가기
Android Application/앱 설계

안드로이드 DI, DIP 예시(with hilt)

by sdchjjj 2023. 4. 4.
728x90

안녕하세요.

이번 포스팅에서는 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

 

안드로이드 힐트(hilt) 의존성 주입 구현

안녕하세요. 이번 포스팅에서는 hilt를 사용한 dependency injection을 간단하게 구현해 보겠습니다. 언어: 코틀린 sdk vsersion - compile: 33 - min: 21 - target: 33 저는 아래의 포스팅에서 사용한 소스에 적용해

it-of-fortune.tistory.com

 

적용은 다른 포스팅에서 작성한 소스에 이어서 진행하겠습니다.

https://it-of-fortune.tistory.com/34

 

안드로이드 Repository pattern 간단 예시(with MVVM pattern)

안녕하세요. 이번 포스팅에서는 repository pattern을 간략하게 적용한 예시를 구현해 보겠습니다. UI의 표시 영역은 MVVM 패턴을 적용하여, MVVM + Repository pattern 구성이 됩니다. 저는 아래 포스팅에서

it-of-fortune.tistory.com

 

먼저, 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

이런 식의 관계가 형성되었고 각자 필요한 객체를 의존성 주입을 통해 사용할 수 있게 되었습니다.

 

figure1. run

정상적으로 refactoring 되었습니다.

 

이상 포스팅을 마치겠습니다.

 

감사합니다.

728x90

댓글