
Hilt assisted injection은 Hilt가 아는 의존성과 실행 중에만 알 수 있는 값을 함께 넣어 객체를 만들 때 쓰는 방식입니다. 특히 ViewModel에 런타임 값을 넣고 싶을 때 자주 검색하게 됩니다.
하지만 먼저 볼 기준은 그 값이 navigation argument인지, DI 의존성인지, 생성 시점 런타임 객체인지 구분하는 것입니다. 이 구분 없이 assisted injection부터 쓰면 구조가 더 복잡해질 수 있습니다.

Hilt가 기본으로 잘 처리하는 것
Repository, use case, DAO, API client처럼 앱의 DI 그래프 안에서 만들 수 있는 객체는 Hilt가 생성자 주입으로 넣어주는 것이 자연스럽습니다.
@HiltViewModel
class ProfileViewModel @Inject constructor(
private val repository: ProfileRepository
) : ViewModel()이런 객체는 화면이 어떤 userId를 받았는지와 무관하게 Hilt가 제공할 수 있습니다. 그래서 assisted injection이 필요하지 않습니다.
SavedStateHandle로 충분한 경우
화면 route나 navigation argument로 넘어온 id, tab, mode 같은 값은 SavedStateHandle로 받는 경우가 많습니다. 이 값은 프로세스 재생성 상황에서도 ViewModel 상태 복원 흐름과 잘 맞습니다.
@HiltViewModel
class ProfileViewModel @Inject constructor(
private val repository: ProfileRepository,
savedStateHandle: SavedStateHandle
) : ViewModel() {
private val userId: String = checkNotNull(savedStateHandle["userId"])
}단순히 화면 인자를 읽는 것이 목적이라면 assisted injection보다 SavedStateHandle이 더 단순하고 Android 아키텍처 흐름에도 잘 맞습니다.
Hilt assisted injection이 필요한 신호
assisted injection은 DI 그래프가 만들 수 없는 값을 생성 시점에 호출자가 직접 넘겨야 할 때 의미가 있습니다. 예를 들어 런타임에 만들어진 세션 객체, 복잡한 초기 파라미터, DI 그래프에 넣기 애매한 값이 여기에 해당할 수 있습니다.
- 값이 navigation argument가 아니다
- DI container에 전역처럼 등록하면 오히려 위험하다
- 객체 생성 시점에 반드시 호출자가 넘겨야 한다
- 테스트에서 해당 값을 명시적으로 바꿔 넣어야 한다
Dagger assisted injection의 기본 모양
assisted injection은 의존성과 assisted parameter를 구분합니다. 의존성은 DI가 제공하고, assisted parameter는 factory 호출자가 넘깁니다.
class DetailPresenter @AssistedInject constructor(
private val repository: ItemRepository,
@Assisted private val itemId: String
) {
@AssistedFactory
interface Factory {
fun create(itemId: String): DetailPresenter
}
}ViewModel에 적용할 때는 AndroidX/Hilt 버전별 지원 방식과 factory 연결 방식이 달라질 수 있으므로 공식 문서 기준을 확인해야 합니다.
ViewModel에서 무리하게 쓰면 생기는 문제
ViewModel은 생성 주체가 Activity나 Fragment가 아니라 ViewModelProvider입니다. 그래서 일반 객체처럼 factory.create(…)를 직접 호출하는 흐름과 다릅니다. 이 지점에서 assisted injection을 억지로 붙이면 생성 흐름이 불필요하게 복잡해질 수 있습니다.
- navigation argument로 충분한 값을 factory 인자로 다시 넘긴다
- 프로세스 재생성 시 초기값 복원 흐름을 놓친다
- ViewModelProvider와 별도 factory 흐름이 섞인다
- 테스트에서 Hilt 설정과 factory 설정을 모두 맞춰야 한다
판단 순서
- 이 값이 Repository 같은 의존성인지 확인한다
- 화면 route argument라면 SavedStateHandle로 받을 수 있는지 본다
- DI 그래프에 넣으면 lifecycle이나 scope가 어색한지 확인한다
- 생성 시점 호출자가 반드시 넘겨야 한다면 assisted injection을 검토한다
- 테스트와 프로세스 재생성 시나리오를 같이 확인한다
테스트 관점
테스트에서는 런타임 값을 명시적으로 바꾸기 쉽다는 장점이 assisted injection의 매력입니다. 다만 ViewModel의 경우 SavedStateHandle도 테스트에서 직접 구성할 수 있으므로, 테스트 편의성만으로 assisted injection을 선택할 필요는 없습니다.
val handle = SavedStateHandle(mapOf("userId" to "42"))
val viewModel = ProfileViewModel(fakeRepository, handle)정리
Hilt assisted injection은 런타임 값을 넣는 강력한 도구지만, ViewModel 인자를 처리하는 기본 답은 아닙니다. 화면 인자는 SavedStateHandle, 앱 의존성은 Hilt 생성자 주입, 그 둘로 설명되지 않는 생성 시점 값은 assisted injection 후보로 보는 것이 안전합니다.
Hilt ViewModel 기본 흐름은 Android Developers Hilt 통합 문서를 기준으로 확인할 수 있습니다. 상태 보존 기준은 SavedStateHandle과 rememberSaveable 차이와 함께 보면 좋습니다.