Study/Android

[Hilt] @Provides를 사용하는 경우 object 키워드로 클래스를 정의해야 하는 이유

hegunhee 2024. 12. 18. 23:57

Android의 DI 라이브러리인 Hilt 공식 문서를 살펴보면

@Provides를 사용하여 인스턴스 삽입 케이스에서

@Module 애노테이션을 부착한 클래스를 object 키워드로 설정했습니다.

왜 class가 아닌 object 키워드를 사용한 지에 대해 알아보겠습니다.

object 키워드란?

Kotlin에서 object 키워드가 의미하는 바는 클래스를 정의함과 동시에 객체를 생성하는 것입니다.

즉 사용자의 객체 생성 없이 해당 객체를 사용할 수 있음을 의미합니다.

class 키워드 대신 object를 사용하면 해당 클래스의 객체는 싱글턴으로 생성됩니다.

 

그 외에 다른 용도로 object 키워드를 사용할 수가 있는데

해당 글과는 맞지 않아 적지 않겠습니다.

 

오늘 글의 예시인 ApiModule입니다.

ApiModule은 object 키워드를 사용해서 정의되었습니다.

해당 코드를 자바 코드로 디컴파일 해보겠습니다.

 

해당 객체는 싱글턴으로 바뀌며 생성자를 private로 막아뒀기 때문에

사용자가 객체를 생성할 수 없습니다. 즉 INSTANCE static 변수로만 접근이 가능합니다.

class 키워드로 Module을 정의했을 때 일어나는 일

그렇다면 Object 키워드가 아닌 class 키워드로 모듈을 정의했을 때 생성되는 코드에 대해 알아보겠습니다.

class 키워드를 사용한 ApiModule입니다.

Hilt의 경우 코드젠 방식으로 의존성 주입을 구현합니다.

java(generated)/패키지명/di 폴더로 이동하시면 만들어지는 코드를 확인하실 수 있습니다.

해당 만들어진 코드를 가지고 실제 Hilt 의존성 주입이 발생합니다.

 

생성되는 Json 팩토리부터 보겠습니다.

Json 타입의 객체를 생성하기 위해서는 ApiModule 객체가 필요하므로
팩토리가 생성될 때 ApiModule 타입의 객체를 인자로 받고 의존성을 주입할 때 module을 사용합니다.

다소 와닿지 않으니 ConverFactory.Factory Factory를 살펴보겠습니다.

여기서 ConverterFactory.Factory는 Retrofit의 객체고 Factory 타입은 Dagger의 것입니다.

 

Converter.Factory 타입의 객체를 생성하기 위해 인자로 필요한 jsonProvider와 
Converter.Factory 타입의 객체를 생성하는 ApiModule 타입 객체도 필요합니다.

해당 타입의 객체를 생성하기 위해 ApiModule 타입 객체를 어디선가 만들고 싱글톤으로 관리한다 하더라도

object 키워드로 생성한다면 ApiModule 타입 객체를 생성하고 주입하는 것은 불필요한 코드입니다.

 

이제 ApiModule을 object 키워드로 변경하고 생성되는 코드를 보겠습니다.

 

생성되는 Json 팩토리 코드를 확인하겠습니다.

더 이상 ApiModule 타입 객체는 필요 없어지고 ApiModule의 인스턴스에 접근해

Json 타입의 객체를 만드는 함수를 호출합니다.

이미  ApiModule은 싱글턴이고 함수를 직접 호출하면 되므로 더이상 해당 변수가 필요없어집니다.

 

Converter.Factory 팩토리 코드도 확인하겠습니다.

동일하게 Json 주입을 제공하는 Provider만 사용할 뿐이고

ApiModule은 싱글턴의 함수에 접근해서 해당 의존성 객체를 생성합니다.

 

이처럼 ApiModule 타입의 객체를 만들어주는 코드를 생성하지 않아도 됩니다.

언어 스펙으로 object 키워드를 사용하면 Hilt Provides 팩토리 코드가 자동 생성될 때

팩토리 코드가 편리하게 접근할 수 있습니다.

 

여기서 Provide<Json> 타입은 Factory<Json>의 부모타입입니다.

그러므로 get() 함수를 통해 의존성 주입을 실행할 수 있습니다.

 

 

이렇게 왜 provides 의 경우 object 키워드로 설정해야 하는지 알아봤습니다.