study gomi

[Hilt] Hilt의 의존성 그래프 본문

App/Android

[Hilt] Hilt의 의존성 그래프

공부하곰 2024. 11. 25. 10:06
728x90
반응형

1. 의존성 그래프

- 의존성 주입을 위한 객체 관계를 나타내는 구조

- Hilt가 의존성을 생성하고 주입하는 과정을 시각적으로 이해하도록 도와줌.

더보기

cf_ 의존성 그래프란?

의존성 그래프는 객체 간의 의존성을 노드(Node)와 간선(Edge)으로 표현한 구조.

  • 노드(Node) : 생성 가능한 객체(클래스나 데이터).
  • 간선(Edge): 노드 간의 의존 관계.

예를 들어 ViewModel이 Repository를 필요로 하고, Repository가 Service를 필요로 한다면 그래프는?

ViewModel --> Repository --> Service

2. 생성 원리

- Hilt는 코드에서 @Inject, @Provides, @Binds 등의 주석을 분석하여 의존성 그래프를 생성

더보기

cf_ 의존성 그래프 생성 주요 과정

 

1. 노드 생성

1-1. Inject가 클래스의 생성자에 선언되어 있다면 Hilt는 해당 클래스를 그래프의 노드로 추가

class Repository @Inject constructor(private val service: Service)

- 여기서 Repository는 노드가 됨.

- Service도 노드로 추가

 

1-2. @Provides 메서드도 노드를 추가

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Provides
    fun provideService(): Service = ServiceImpl()
}

- 이 경우 Service 타입의 노드가 그래프에 추가 됨.

 


2. 간선 생성

2-1. 생성자나 함수의 매개변수를 분석하여 의존 관계를 만든다.

class ViewModel @Inject constructor(private val repository: Repository)

- 이 경우 ViewModel 노드는 Repository 노드와 연결 됨.

 

2-2. 주입된 객체가 또 다른 의존성을 가진다면 그래프는 확장됨.

class Repository @Inject constructor(private val service: Service)
class Service @Inject constructor(private val apiClient: ApiClient)

 

2-3. 확장된 의존성 그래프의 결과

ViewModel --> Repository --> Service --> ApiClient

3. 의존성 주입의 범위 관리

 - Hilt는 의존성의 생명주기를 관리하기 위해 범위(Scope)를 사용.

- 각 범위는 의존성 그래프의 하위 집합을 정의하며 아래와 같은 기본 범위를 제공.

  • SingletonComponent: 애플리케이션 전역에서 하나의 인스턴스만 생성.
  • ActivityRetainedComponent: ViewModel의 생명주기 동안 유지.
  • ActivityComponent: Activity의 생명주기 동안 유지.
  • FragmentComponent: Fragment의 생명주기 동안 유지.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
    @Singleton
    @Provides
    fun provideService(): Service = ServiceImpl()
}

- @Singleton은 Service 객체가 애플리케이션 전체에서 하나의 인스턴스만 유지됨을 보장


4. 의존성 주입 과정

4-1. 의존성 탐색

- Hilt는 객체가 필요한 시점(ViewModel 생성 등)에 의존성을 탐색한다.

class ViewModel @Inject constructor(private val repository: Repository)

- Hilt는 ViewModel이 필요로 하는 Repository를 의존성 그래프에서 찾는다.

 

4-2. 객체 생성

- 필요한 의존성이 그래프에 없다면 Hilt는 @Inject 또는 @Provides를 통해 객체를 생성

- 예: repositoryService를 필요로 하면 Service를 먼저 생성하고 Repository를 생성

 

4-3. 의존성 연결

- 생성된 객체를 연결, 필요로 하는 곳에 주입.


5. 의존성 그래프 예제

5-1. 구성 요소

class ApiClient @Inject constructor()

class Service @Inject constructor(private val apiClient: ApiClient)

class Repository @Inject constructor(private val service: Service)

class ViewModel @Inject constructor(private val repository: Repository)

 

5-2. 그래프

ViewModel --> Repository --> Service --> ApiClient

- 참고: 그렇다면 그래프의 루트 노드는?? ↓

더보기

- 의존성 그래프에서 루트 노드는 특정 클래스(예: ApiClient) 자체가 아니라 의존성을 필요로 하는 시작점.

- 일반적으로 ViewModel이나 그 의존성을 주입받는 컴포넌트(Activity, Fragment 등)이다.

 

1. 루트 노드의 정의

  • 의존성 그래프의 루트 노드는 의존성을 요청하는 출발점.
  • Hilt에서 이는 보통 컴포넌트(예: @HiltViewModel, @AndroidEntryPoint로 주석 처리된 Activity/Fragment)다.
  • 그래프의 탐색은 이 루트 노드에서 시작해 필요한 의존성을 따라 내려간다.

2. 예제의 구조 좀 더 자세히

class ApiClient @Inject constructor()

class Service @Inject constructor(private val apiClient: ApiClient)

class Repository @Inject constructor(private val service: Service)

@HiltViewModel
class MyViewModel @Inject constructor(private val repository: Repository)
ViewModel --> Repository --> Service --> ApiClient
  • 루트 노드: MyViewModel (Hilt가 이 ViewModel을 필요로 할 때 그래프를 탐색 시작).
  • MyViewModel은 Repository를 요청.
  • Repository는 Service를 요청.
  • Service는 ApiClient를 요청
3. 의존성 요청 과정 다시 살펴보기
  • ViewModel 요청: MyViewModel이 요청되면 Hilt는 ViewModel이 의존하는 Repository를 찾는다.
  • Repository 요청: Repository를 생성하기 위해 Service가 필요.
  • Service 요청: Service를 생성하기 위해 ApiClient가 필요.
  • ApiClient 생성: ApiClient는 의존성이 없으므로 바로 생성.
  • 순차 주입: 생성된 객체를 상위 객체에 주입하며 그래프를 완성.

4. 말단(leaf) 노드?

- 여기서는 ApiClient가 의존성 그래프에서의 "말단(leaf) 노드".

- 의존성이 없는 클래스이므로 요청받기 전까지 생성되지 않는다.

- 이 객체는 직접 요청되지 않으며 상위 노드(예: Service)가 요청될 때만 생성됨.

 

5. 의존성 그래프의 루트는 어디서 결정?

- Hilt에서 루트는 컴포넌트와 연결된다.

  • Hilt 컴포넌트(SingletonComponent, ActivityComponent 등)는 특정 생명주기에서 그래프를 관리, 루트 역할을 함.
  • Hilt 컴포넌트가 의존성을 필요로 하는 경우 그래프 탐색이 시작됨.

- 예

  • @HiltViewModel: ActivityRetainedComponent를 통해 관리되는 ViewModel.
  • @AndroidEntryPoint가 있는 Activity/Fragment: 각 컴포넌트가 그래프 탐색의 루트가 됨.

요약

- 루트 노드는 컴포넌트에서 시작됨.

- ApiClient 같은 말단 노드는 의존성의 마지막 지점

- Hilt가 그래프를 탐색하여 필요한 객체를 순차적으로 생성하고 연결

5-3. 주입 과정

  • ViewModel이 필요할 때 Hilt는 Repository를 확인.
  • Repository를 생성하려면 Service가 필요.
  • Service를 생성하려면 ApiClient가 필요.
  • 최종적으로 모든 객체가 생성되고 연결된다.

6. 장점

  • 자동화: 객체 생성과 관리가 자동으로 이루어짐.
  • 재사용 가능성: 동일한 객체를 여러 클래스에서 재사용 가능.
  • 유지보수 용이: 의존성 관계를 한눈에 파악할 수 있어 코드 유지보수가 쉽다.

728x90
반응형