본문 바로가기
Android/Hilt

[Android/Hilt] @Qualifier와 @Named 이해하기: 같은 타입의 여러 의존성을 구별하여 주입

by quessr 2025. 3. 7.

 

Hilt를 사용하다 보면 같은 타입의 여러 의존성을 주입해야 하는 상황이 발생할 수 있습니다.

이때, 어떤 객체를 주입해야 할지 Hilt가 알 수 있도록 구분하는 방법이 @Qualifier@Named입니다.

이번 글에서는 이 두 개념을 정리해보겠습니다.


같은 타입의 의존성 주입 문제

Hilt는 기본적으로 반환 타입을 기준으로 의존성을 주입합니다. 그러나 같은 타입의 여러 객체를 주입해야 하는 경우가 있을 수 있습니다.

예를 들어, 두 개의 String 값을 의존성으로 제공하려고 할 때 문제가 발생할 수 있습니다.

@Module
@InstallIn(SingletonComponent::class)
object StringModule {
    
    @Provides
    fun provideHelloString(): String {
        return "Hello"
    }
    
    @Provides
    fun provideWorldString(): String {
        return "World"
    }
}

 

위 코드에서는 String 타입의 의존성이 두 개 제공되므로, Hilt가 어떤 String을 주입해야 하는지 알 수 없습니다.

이를 해결하기 위해 @Qualifier 또는 @Named를 사용할 수 있습니다.


@Named: 기본 제공되는 방식

Hilt에서는 @Named 애너테이션을 사용하여 의존성을 구별할 수 있습니다.

@Named를 사용한 의존성 구분

@Module
@InstallIn(SingletonComponent::class)
object StringModule {
    
    @Provides
    @Named("hello")
    fun provideHelloString(): String {
        return "Hello"
    }
    
    @Provides
    @Named("world")
    fun provideWorldString(): String {
        return "World"
    }
}

 

위 코드에서는 String 타입의 의존성이 두 개 제공되므로, Hilt가 어떤 String을 주입해야 하는지 알 수 없습니다.

이를 해결하기 위해 @Qualifier 또는 @Named를 사용할 수 있습니다.


@Named: 기본 제공되는 방식

Hilt에서는 @Named 애너테이션을 사용하여 의존성을 구별할 수 있습니다.

@Named를 사용한 의존성 구분

@Module
@InstallIn(SingletonComponent::class)
object StringModule {
    
    @Provides
    @Named("hello")
    fun provideHelloString(): String {
        return "Hello"
    }
    
    @Provides
    @Named("world")
    fun provideWorldString(): String {
        return "World"
    }
}

 

이제 @Named("hello")@Named("world")를 사용하여 주입할 때 특정 값을 선택할 수 있습니다.

class ExampleClass @Inject constructor(
    @Named("hello") private val hello: String,
    @Named("world") private val world: String
) {
    fun printStrings() {
        println("$hello, $world!")
    }
}

 

Hilt는 @Named("hello")@Named("world")를 보고 적절한 값을 주입해 줍니다.

@Named를 사용하면 좋은 경우

  • 간단한 구별이 필요한 경우
  • 특정한 이름을 붙여서 관리하고 싶은 경우

@Qualifier: 커스텀 애너테이션 사용하기

@Named 대신 @Qualifier를 사용하면 더 명확하게 커스텀 애너테이션을 정의하여 사용할 수 있습니다.

@Qualifier를 사용한 커스텀 애너테이션 생성

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class HelloQualifier

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class WorldQualifier

 

이제 이 커스텀 애너테이션을 사용하여 String을 제공할 수 있습니다.

@Module
@InstallIn(SingletonComponent::class)
object StringModule {
    
    @Provides
    @HelloQualifier
    fun provideHelloString(): String {
        return "Hello"
    }
    
    @Provides
    @WorldQualifier
    fun provideWorldString(): String {
        return "World"
    }
}

 

주입하는 곳에서도 @Qualifier 애너테이션을 활용할 수 있습니다.

class ExampleClass @Inject constructor(
    @HelloQualifier private val hello: String,
    @WorldQualifier private val world: String
) {
    fun printStrings() {
        println("$hello, $world!")
    }
}

@Qualifier에 매개변수 전달하기

@Qualifier는 기본적으로 애너테이션이지만, 특정 값을 매개변수로 받을 수도 있습니다.

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class SizeQualifier(val width: Int, val height: Int)

 

이를 활용하면 특정 크기를 가진 객체를 구별할 수 있습니다.

@Module
@InstallIn(SingletonComponent::class)
object SizeModule {
    
    @Provides
    @SizeQualifier(50, 160)
    fun provideSmallSize(): Pair<Int, Int> {
        return Pair(50, 160)
    }
    
    @Provides
    @SizeQualifier(100, 200)
    fun provideLargeSize(): Pair<Int, Int> {
        return Pair(100, 200)
    }
}

 

주입 시에도 특정 값을 기반으로 원하는 크기를 선택할 수 있습니다.

class SizeUser @Inject constructor(
    @SizeQualifier(50, 160) private val smallSize: Pair<Int, Int>,
    @SizeQualifier(100, 200) private val largeSize: Pair<Int, Int>
) {
    fun printSizes() {
        println("Small: $smallSize, Large: $largeSize")
    }
}

 

이처럼 @Qualifier는 매개변수를 받을 수도 있어, 보다 세밀한 의존성 관리를 할 수 있습니다.


@Named vs @Qualifier 정리

구분 사용 방식 장점
@Named @Named("name") 간단한 의존성 구별에 적합
@Qualifier 커스텀 애너테이션 정의 후 사용 의미를 명확하게 표현할 수 있음
@Qualifier(값) 매개변수 포함 보다 정밀한 의존성 관리 가능

결론

  • @Named는 간단한 구분이 필요한 경우 사용하면 편리합니다.
  • @Qualifier는 커스텀 애너테이션을 통해 보다 직관적인 코드 작성을 원할 때 적합합니다.
  • @Qualifier에 매개변수를 추가하면 더 세밀한 구분이 가능합니다.
  • 같은 타입의 의존성이 여러 개 있을 때, @Named@Qualifier를 사용하여 정확한 객체를 주입해야 합니다.

 

반응형