๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค2024 ์•ˆ๋“œ๋กœ์ด๋“œ/๐Ÿฟ ์˜ํ™” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์ผ์ง€

[Android : Kotlin] ์˜์กด์„ฑ ์ฃผ์ž…์˜ ๊ธฐ๋ณธ์„ ์ดํ•ดํ•ด๋ณด์ž~!

by hyeonha 2024. 12. 27.

๋ชฉ์ฐจ

    ๋“ค์–ด๊ฐ€๊ธฐ ์ „์—

    ํ”„๋กœ์ ํŠธ์—์„œ Hilt๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์— ๋ฐ”๋น  Hilt๊ฐ€ ๋‚˜์˜ค๊ธฐ๊นŒ์ง€ ํ๋ฆ„์„ ์ œ๋Œ€๋กœ ์‹œ๊ฐ„ ๋“ค์—ฌ ๊ณต๋ถ€ํ•ด๋ณด์ง€ ๋ชปํ–ˆ๋Š”๋ฐ ์•ฑ ์ถœ์‹œ๋ฅผ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๊นŒ์ง€ ๊ฑธ๋ฆฌ๋Š” ๊ธฐ๊ฐ„๋™์•ˆ ๊ทธ๋™์•ˆ ๋ชปํ–ˆ๋˜ ๊ณต๋ถ€๋ฅผ ํ•˜๋ฉฐ ๋ถ€์กฑํ•œ ๋‚ด์šฉ์„ ์ฑ„์›Œ๋ณด๋ คํ•œ๋‹ค~! ์˜ค๋Š˜์€ ์˜์กด์„ฑ ์ฃผ์ž…ํŒŒํŠธ!!

    ์•„์ž์ž

    ์˜์กด์„ฑ ์ฃผ์ž… ๊ธฐ๋ณธ

    ์•กํ‹ฐ๋น„ํ‹ฐ์—์„œ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ

    ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด๊ฐ€ ํ•„์š”
    ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ ์†Œ์Šค ๊ฐ์ฒด๊ฐ€ ํ•„์š”
    ๋ฐ์ดํ„ฐ ์†Œ์Šค ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ ์„œ๋น„์Šค ๊ฐ์ฒด๊ฐ€ ํ•„์š”
    ์„œ๋น„์Šค ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ ˆํŠธ๋กœํ• ๊ฐ์ฒด๊ฐ€ ํ•„์š”
    
    // ์ฝ”๋“œ ๊ตฌํ˜„ ์‹œ
    0. ๋ ˆํŠธ๋กœํ• ๊ฐ์ฒด ๊ตฌ์„ฑ
    1. ์„œ๋น„์Šค ๊ฐ์ฒด ๊ตฌ์„ฑ
    2. ๋ฐ์ดํ„ฐ ์†Œ์Šค ๊ฐ์ฒด ๊ตฌ์„ฑ 
    3. ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด ๊ตฌ์„ฑ
    4. ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด ๊ตฌ์„ฑ
    

     

    ์œ„์™€ ๊ฐ™์ด ์ˆœ์„œ๋Œ€๋กœ ๊ตฌํ˜„ํ•ด์ค˜์•ผํ•œ๋‹ค.

    ๋‹ค๋ฅธ ๋ถ€๋ถ„์—์„œ ๋‹ค๋ฅธ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์œ„ ๊ณผ์ •์„ ์ค‘๋ณตํ•ด์„œ ๊ตฌํ˜„ํ•„์š”

    ์ข…์† ํ•ญ๋ชฉ์„ ์ˆœ์„œ๋Œ€๋กœ ์„ ์–ธํ•ด์ค˜์•ผํ•œ๋‹ค.

    ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

    ์ปจํ…Œ์ด๋„ˆ๋กœ ์ข…์† ํ•ญ๋ชฉ ๊ด€๋ฆฌ

    • ๊ฐ์ฒด ์žฌ์‚ฌ์šฉ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ์œ„ํ•ด
    • ์ข…์† ํ•ญ๋ชฉ์„ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ์ž์ฒด ์ข…์† ํ•ญ๋ชฉ ์ปจํ…Œ์ด๋„ˆ ํด๋ž˜์Šค ์ƒ์„ฑ!
    • Application์— ๋ฐฐ์น˜ํ•˜๊ธฐ
    // Application.kt
    
    class Application : Application() {
    
    	// ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๋”ฐ๋ฅด์ง€ ์•Š์Œ
    	//  ์•ฑ ์ „์ฒด์—์„œ ๊ณต์œ ๋˜๋Š” ๊ณ ์œ ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค์ด๋‹ค. 
    	val appContainer : AppContainer() 
    	
    	}
    
    • AppContainer
    class AppContainer {
    
     val userViewModelFactory = UserViewModelFactory(userRepository)
    	
    	 private val retrofit = Retrofit
                .Builder()
                .baseUrl(movieApiBaseUrl)
                .client(OkHttpClient)
                .addCallAdapterFactory(ResultCallAdapter.Factory(retryCount))
                .addConverterFactory(json.asConverterFactory(contentType.toMediaType()))
                .build()
                
                
        
      private val userService = retrofit.create(UserService::class.java)
       
       
      private val userDataSource = UserDataSourceImpl(userService)
    	
    	val userRepository = UserRepositoryImpl(userDataSource)
    	
    
    
    • ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ ๋ทฐ ๋ชจ๋ธ ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
    class UserFragment : Fragment() {
    private lateinit var viewModel : UserViewModel
    
     override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            // Gets userRepository from the instance of AppContainer in Application
            
            val appContainer = (application as Application).appContainer
    //        viewModel = UserViewModel(appContainer.userRepository)
    
    viewModel = appContainer.userViewModelFactory.create()
        }
    }
    

     

    ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ UserRepository ๊ฐ์ฒด๋Š” ์‹ฑ๊ธ€ํ†ค์ด ์•„๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

    ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋ฉด ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด ์ƒ์„ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ dataSource, Service, retrofit์„ ๋ชจ๋‘ ๊ตฌ์„ฑํ•ด์ฃผ๋Š” ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ฒ ๋‹ค....

     

    ๋งŒ์•ฝ viewModel์ด ๋” ๋งŽ์€ ๊ณณ์—์„œ ํ•„์š”ํ•˜๋‹ค๋ฉด ํ•œ๊ณณ์—์„œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋งŒ๋“  ๋ทฐ๋ชจ๋ธ์„ appContainer๋กœ ์ด๋™ํ•˜๊ณ , ๊ทธ ์œ ํ˜•์˜ ์ƒˆ ๊ฐ์ฒด์— ํŒฉํ† ๋ฆฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์ž‡๋”ฐ.

    // T : ๋งŒ๋“ค๊ณ  ์‹ถ์€ ์–ด๋–ค ํƒ€์ž…์ด๋“  ok
    // create() ๋Š” ๊ทธ ํƒ€์ž…์˜ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ 
    interface Factory<T> {
    	fun create() : T
    	}
    	
    // UserViewModel์šฉ Factory
    class UserViewModelFactory(
        private val userRepository: UserRepository
    ) : Factory<UserViewModel> {
    // ์—ฌ๊ธฐ์„œ T : UserViewModel
        override fun create(): UserViewModel {
            return UserViewModel(userRepository)
        }
    }
    

    ๋น„๊ต

    • ๊ธฐ์กด
      • ์•กํ‹ฐ๋น„ํ‹ฐ๋‚˜ ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ ๋ทฐ๋ชจ๋ธ ์ƒ์„ฑ
      userViewModel = UserViewModel(appContainer.userRepository)
      
      
    • ๋ณ€๊ฒฝ : Factory๋ฅผ ํ†ตํ•ด AppContainer๋กœ ๋ทฐ๋ชจ๋ธ ์ƒ์„ฑ ์ฑ…์ž„์„ ์ด๋™ํ•œ๋‹ค.
    • class AppContainer { val userViewModelFactory = UserViewModelFactory(userRepository)

    ํŒฉํ† ๋ฆฌ ํŒจํ„ด

    • ๊ฐ์ฒด ์ƒ์„ฑ์„ ๋‹ด๋‹นํ•˜๋Š” ๋ณ„๋„์˜ ํด๋ž˜์Šค(ํŒฉํ† ๋ฆฌ)๋ฅผ ๋‘์–ด ๊ฐ์ฒด ์ƒ์„ฑ ๋กœ์ง์„ ์บก์Šํ™”ํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด

    ๋ฒ”์œ„

    • ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ ํ๋ฆ„์„ ๋„์ž…ํ•˜๋ฉฐ ๊ฐ์ฒด๊ฐ€ ํ•ด๋‹น ํ๋ฆ„์˜ ๋ฒ”์œ„์—๋งŒ ์žˆ๊ธฐ๋ฅผ ์›ํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ์˜ˆ๋ฅผ ๋“ค์–ด ๋กœ๊ทธ์ธ ํ๋ฆ„์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ๋น„๋ฐ€๋ฒˆํ˜ธ๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ๋Š” LoginUserData๋ฅผ ๋งŒ๋“ค ๋•Œ, ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ์ด์ „ ๋กœ๊ทธ์ธ ํ๋ฆ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜์ง€ ์•Š๊ณ  ๋ชจ๋“  ์ƒˆ ํ๋ฆ„์— ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ๋‹ค.
    class LoginContainer(val userRepository: UserRepository) {
    
        val loginData = LoginUserData()
    
        val loginViewModelFactory = LoginViewModelFactory(userRepository)
    }
    
    
    // AppContainer contains LoginContainer now
    class AppContainer {
        ...
        val userRepository = UserRepository(localDataSource, remoteDataSource)
    
        // LoginContainer will be null when the user is NOT in the login flow
        var loginContainer: LoginContainer? = null
    }
    

     

    ํ๋ฆ„ ๊ด€๋ จ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์žˆ์œผ๋ฉด ์ปจํ…Œ์ด๋„ˆ ๊ฐ์ฒด๋ฅผ ์–ธ์ œ ๋งŒ๋“ค๊ณ  ์‚ญ์ œํ• ์ง€ ํŒ๋‹จํ•ด์•ผํ•œ๋‹ค.

    ๋กœ๊ทธ์ธ ํ๋ฆ„์ด LoginActivity์— ๋…๋ฆฝ์ ์ด๋ฏ€๋กœ ์ด ์ปจํ…Œ์ด๋„ˆ์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ LoginActicity์—์„œ ๊ด€๋ฆฌํ•˜๋ฉด ๋œ๋‹ค. onCreate์—์„œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ , onDestroy์—์„œ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. 

    class LoginActivity : Activity() {
    
     private lateinit var loginViewModel: LoginViewModel
     private lateinit var loginData: LoginUserData
     private lateinit var appContainer: AppContainer
        
        
       override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
           
            appContainer = (application as MyApplication).appContainer
    
            // Login flow has started. Populate loginContainer in AppContainer
            appContainer.loginContainer = LoginContainer(appContainer.userRepository)
    
            loginViewModel = appContainer.loginContainer.loginViewModelFactory.create()
            
            loginData = appContainer.loginContainer.loginData
        }
        
        
         override fun onDestroy() {
            // Login flow is finishing
            // Removing the instance of loginContainer in the AppContainer
            appContainer.loginContainer = null
            super.onDestroy()
        }
    
    }
    

    Dagger

    ์ข…์†ํ•ญ๋ชฉ์„ ์„ ์–ธํ•˜๊ณ , ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ข…์†ํ•ญ๋ชฉ์„ ์–ด๋–ป๊ฒŒ ์ถฉ์กฑํ•˜๋Š”์ง€ ์ง€์ •ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ์•„๋ž˜๋ฅผ ๋นŒ๋“œ ์‹œ๊ฐ„์— ์ž๋™์œผ๋กœ ๊ตฌํ˜„ํ•ด์ค€๋‹ค.

    ์œ„์—์„œ ์ˆ˜๋™์œผ๋กœ ์ข…์†ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•ด๋ณด๋ฉฐ , ์—ฌ๋Ÿฌ ๋ ˆํฌ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•  ๊ฒฝ์šฐ ์ค‘๋ณต, ๋ฐ˜๋ณตํ•ด์„œ ์ž‘์„ฑํ•ด์ค˜์•ผํ•  ์ฝ”๋“œ๊ฐ€ ๋งŽ๊ฒ ๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค. ์ด๋ฅผ ํ•ด์†Œํ•ด์ฃผ๊ธฐ ์œ„ํ•ด Dagger์—์„œ๋Š” ์ˆ˜๋™์œผ๋กœ ๊ตฌํ˜„ํ•˜๋˜ ๋กœ์ง์„ ์ž๋™์œผ๋กœ ๊ตฌํ˜„ํ•ด์ค€๋‹ค.
    • ์œ„์—์„œ ์ˆ˜๋™์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋˜ AppContainer ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•ด์ค€๋‹ค.
    • AppContainer(application grapth)์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค์˜ ํŒฉํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.
    • ๋ฒ”์œ„๋ฅผ ํ†ตํ•ด ์ข…์† ํ•ญ๋ชฉ์„ ์žฌ์‚ฌ์šฉํ• ์ง€, ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์ง€ ๊ฒฐ์ •
    • ๋กœ๊ทธ์ธ ํ๋ฆ„์„ ์ฒ˜๋ฆฌํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ Dagger subcomponent๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ •ํ•œ ํ”Œ๋กœ์šฐ๋ฅผ ์œ„ํ•œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.
      • ๋”์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ ๋Œ€ ๊ฐ์ฒด๋ฅผ ํ•ด์ œํ•ด์คŒ์œผ๋กœ์จ ์„ฑ๋Šฅ ํ–ฅ์ƒ
    • ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์˜ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ ๋‹ค.
      • ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ํด๋ž˜์Šค์™€ ๊ด€๋ จํ•˜์—ฌ ํ•„์š”ํ•œ ์œ ํ˜•์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ๋‚ด๋ถ€์ ์œผ๋กœ ํŒฉํ† ๋ฆฌ ์œ ํ˜• ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑ

    ์˜ˆ์‹œ

    UserRepository ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด UserLocalDataSource, UserRemoteDataSource๊ฐ€  ํ•„์š”ํ•˜๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. 

    class UserRepository (
    	private val localDataSource : UserLocalDataSource,
    	private val remoteDataSource: UserRemoteDataSource
    ) { ... }
    

     

      Dagger๊ฐ€ UserRepository ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์žˆ๋„๋ก @Inject ์ฃผ์„์„ UserRepository ์ƒ์„ฑ์ž์— ์ถ”๊ฐ€ํ•œ๋‹ค.

    // @Inject
    // 1. Dagger๊ฐ€ UserRepository ๊ฐ์ฒด๋ฅผ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•˜๋Š”์ง€ ์•Œ๊ฒŒ ํ•ด์ค€๋‹ค.
    // 2. ์ข…์†ํ•ญ๋ชฉ์€ UserLocalDataSource ๋ฐ UserRemoteDataSource์ž„์„ ์•Œ๋ ค์ค€๋‹ค.
    
    class UserRepository @Inject constructor(
    	private val localDataSource : UserLocalDataSource,
    	private val remoteDataSource:  
    ) { ... }
    

     

    ์ด์ œ ์ข…์†ํ•ญ๋ชฉ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค˜์•ผํ•œ๋‹ค. UserLocalDataSource์™€UserRemoteDataSource์—๋„ @Inject๋ฅผ ๋ถ™์—ฌ์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค€๋‹ค.

    class UserLocalDataSource @Inject constructor() { ... }
    class UserRemoteDataSource @Inject constructor() { ... }
    

     

    Dagger ๊ตฌ์„ฑ์š”์†Œ

    Dagger๋Š” ์ข…์† ํ•ญ๋ชฉ์ด ํ•„์š”ํ•  ๋•Œ ๊ฐ€์ ธ์˜ฌ ์œ„์น˜๋ฅผ ์ฐพ๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์˜ ์ข…์† ํ•ญ๋ชฉ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

    1. ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
    2. @Component๋กœ ์ฃผ์„ ์ง€์ •

    → ์ด๋ฅผ ํ†ตํ•ด ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ ๋‹ค.

    @Component๋กœ ์ฃผ์„์„ ์ค€ interface ๋‚ด์—์„œ ํ•„์š”ํ•œ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค(UserRepository)๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

    ์ฆ‰ @Component๋Š” Dagger์—๊ฒŒ ์ด๋ ‡๊ฒŒ ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

    @Component : Dagger์•ผ ๋‚˜๋Š” ์ด๋Ÿฐ ๊ฒƒ๋“ค์ด ํ•„์š”ํ•ด. ์•Œ์•„์„œ ๋งŒ๋“ค์–ด์ค„๋ž˜?
    //@Component : Dagger๊ฐ€ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ•œ๋‹ค.
    @Component(modules = [NetworkModule::class, DatabaseModule::class])
    interface ApplicationGraph {
        fun repository(): UserRepository
    }

     

    ํ”„๋กœ์ ํŠธ ๋นŒ๋“œ ์‹œ์— Dagger๋Š” ์ž๋™์œผ๋กœ ApplicationGraph ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ธ DaggerApplicationGraph๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

    ์ด๋ฅผ ํ†ตํ•ด ์ด ๊ทธ๋ž˜ํ”„๋Š” UserRepository, UserLocalDataSource, UserRemoteDataSource ํด๋ž˜์Šค ๊ฐ„์˜ ๊ด€๊ณ„๋กœ ๊ตฌ์„ฑ๋œ ์ค‘์† ํ•ญ๋ชฉ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

    val applicationGraph : ApplicationGraph = DaggerApplicationGraph.create()
    val userRepository : UserRepository = applicationGrapgh.repotiroy()

     

    Dagger๋Š” applicationGrapgh.repository() ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋งˆ๋‹ค   UserRepository์˜ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

    val applicationGraph: ApplicationGraph = DaggerApplicationGraph.create()
    
    val userRepository: UserRepository = applicationGraph.repository()
    val userRepository2: UserRepository = applicationGraph.repository()
    
    assert(userRepository != userRepository2)

     

    ๋งŒ์•ฝ ๊ณ ์œ ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด??

     

    ๋งค๋ฒˆ UserRepository ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ??

    - ๋งŒ์•ฝ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๋ทฐ๋ชจ๋ธ์—์„œ ๊ณต์œ ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฒฝ์šฐ 

    - ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“ ๋‹ค๋Š” ์  ์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ๋กœ์ง์— ๋งž๊ฒŒ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค!

     

    ์ˆ˜๋™์œผ๋กœ ์ข…์† ํ•ญ๋ชฉ์„ ๊ตฌํ˜„ํ•  ๋•Œ๋Š” ๋™์ผํ•œ UserRepository ๊ฐ์ฒด๋ฅผ ๋ทฐ๋ชจ๋ธ ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์ง€๋งŒ Dagger์—์„œ๋Š” ๋ฒ”์œ„ ์ฃผ์„์„ ํ†ตํ•ด์„œ ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ• ๊ฑฐ์•ผ! ๋ผ๊ณ  ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค.

    ๋ฒ”์œ„ ์ง€์ •

    // Dagger์—๊ฒŒ ์ด ๊ทธ๋ž˜ํ”„์—์„œ ๋งŒ๋“œ๋Š” @Singleton ๊ฐ์ฒด๋“ค์€ ์•ฑ์ด ์‚ด์•„์žˆ๋Š” ๋™์•ˆ 
    // ๋”ฑ! ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด์„œ ์žฌ์‚ฌ์šฉํ•ด์ค˜ ๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.
    
    @Singleton
    @Component 
    interface ApplicationGraph {
    	fun repository() : UserRepository
    }

     

    UserRepository๋ฅผ ์•ฑ ์ „์ฒด์—์„œ ๋”ฑ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ค€๋‹ค. 

    ์ด๋ฅผ ํ†ตํ•ด ๋ทฐ๋ชจ๋ธ์—์„œ UserRepostory๋กœ ์ž‘์—… ์‹œ์— ์ผ๊ด€๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

    @Singleton
    class UserRepository @Inject constructor(
        private val localDataSource: UserLocalDataSource,
        private val remoteDataSource: UserRemoteDataSource
    ) { ... }
    ์ด ํŒŒํŠธ์—์„œ๋Š” ์ข…์† ํ•ญ๋ชฉ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ ค๋‚˜๊ฐ€๋ฉด์„œ, ํ•„์š”ํ•œ ๋ฒ”์œ„๋ฅผ ์ƒ๊ฐํ•ด๋ณด๋ฉด ์ข‹๊ฒ ๋‹ค. ๋ฌดํ„ฑ๋Œ€๋กœ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ์ ์ ˆํ•œ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•ด๋ณด์ž!

    Android์—์„œ Dagger๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž!

    ๊ถŒ์žฅ ์‚ฌํ•ญ

    - ๊ฐ€๋Šฅํ•˜๋ฉด ์ƒ์„ฑ์ž ์‚ฝ์ž…์„ ํ•˜๊ณ  ๊ฐ€๋Šฅํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ•˜์ž

    - @Binds -> ์ธํ„ฐํŽ˜์ด์Šค ํ˜•ํƒœ์˜ ์ข…์† ํ•ญ๋ชฉ ์‚ฝ์ž…์œผ๋กœ ์ธํ„ฐํŽ˜์ด์Šค์— ์–ด๋–ค ๊ตฌํ˜„์ด ์žˆ์–ด์•ผํ•˜๋Š”์ง€ ์•Œ๋ ค์ฃผ๊ธฐ

    - @Provides -> ํ”„๋กœ์ ํŠธ๊ฐ€ ์†Œ์œ ํ•˜์ง€ ์•Š์€ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค€๋‹ค.

    - ์‚ฌ์šฉ๋˜๋Š” ์ „์ฒด ๊ธฐ๊ฐ„์— ๋”ฐ๋ผ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•ด์ค€๋‹ค

     

    // 1. ์•ฑ์˜ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„ ์ •์˜ 
    @Component
    interface ApplicaitionComponent {...}
    
    
    // Application์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•ด appComponent๋ฅผ Application์— ๋‘”๋‹ค.
    class Application : Application() {
    	val appComponent = DaggerApplicationComponent.create()
    }

     

    ์•กํ‹ฐ๋น„ํ‹ฐ๋‚˜ ํ”„๋ž˜๊ทธ๋จผํŠธ์™€ ๊ฐ™์€ ํด๋ž˜์Šค๋Š” ์‹œ์Šคํ…œ์— ์˜ํ•ด ์ธ์Šคํ„ด์Šคํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์— Dagger๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค. 

    ๋”ฐ๋ผ์„œ ์•กํ‹ฐ๋น„ํ‹ฐ๋‚˜ ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ๋Š” ํ•„๋“œ ์‚ฝ์ž…์„ ํ†ตํ•ด์„œ ํ•„์š”ํ•œ ์ข…์† ํ•ญ๋ชฉ์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค.

     

    Activity, Fragment, Service, BroadcastReceiver, ContentProvider , ์ฆ‰ ์•ˆ๋“œ๋กœ์ด๋“œ ํ”„๋ ˆ์ž„์›Œํฌ ํด๋ž˜์Šค์—์„œ ์ƒ์„ฑ์ž ์‚ฝ์ž…์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค!! ๋”ฐ๋ผ์„œ  ํ•„๋“œ ์‚ฝ์ž…์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

    class UserFragment : Fragment()  {
    
    	@Inject lateinit var userViewModel : UserViewModel
    
    }

     

    ์•กํ‹ฐ๋น„ํ‹ฐ์—์„œ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์ œ๊ณต๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋Š”

    @Component
    interface ApplicationComponent {
    	
        fun inject(activity : LoginActivity)
        // Dagger์—๊ฒŒ  " LoginActivity๊ฐ€ ์ฃผ์ž…์„ ์š”์ฒญํ•˜๊ณ  ์žˆ์–ด. 
        // ๊ทธ๋Ÿฌ๋‹ˆ๊นŒ ๊ทธ๋ž˜ํ”„๋Š” ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ์š”์ฒญํ•˜๋Š” ๋ชจ๋“  ํ•„๋“œ์˜ ์˜์กด์„ฑ์„ ๋งŒ์กฑํ•ด์•ผํ•ด!" 
        
        // ์•กํ‹ฐ๋น„ํ‹ฐ๊ฐ€ ๊ทธ๋ž˜ํ”„์— ์ ‘๊ทผํ•˜๊ธธ ์›ํ•˜๋ฉฐ ์‚ฝ์ž…์„ ์š”์ฒญํ•œ๋‹ค๊ณ  Dagger์—๊ฒŒ ์•Œ๋ ค์ค€๋‹ค. 
    
    }

     

    class LoginActivity : Activity() {
    
    	// ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด 
        // ์ข…์† ํ•ญ๋ชฉ ๊ทธ๋ž˜ํ”„๋ฅผ ํ†ตํ•ดLoginViewModel ๊ฐ์ฒด๋ฅผ ๋ฐ›๊ณ  ์‹ถ์–ด์š”! ๋ผ๊ณ  Dagger์—๊ฒŒ ์š”์ฒญํ•˜๋Š” ๊ฒƒ
        @Inject lateinit var loginViewModel : LoginViewModel
    
    
    	override fun onCreate(savedInstanceState: Bundle?) {
            
            (applicationContext as Application).appComponent.inject(this)
            
            /*
            	1. Dagger์•ผ , LoginActivity์˜ @Inject ํ•„๋“œ ๋“ค์„ ์ดˆ๊ธฐํ™”ํ•ด์ค˜
                2. ์‹ค์ œ๋กœ ์ฃผ์ž… 
                3. ์ด์ œ loginViewModel ์‚ฌ์šฉ ๊ฐ€๋Šฅ 
            
            */ 
    
            super.onCreate(savedInstanceState)
        }
    
    }

     

    @Inject : Dagger์•ผ, LoginViewModel์€ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค๋ฉด ๋ผ! 
    
    class LoginViewModel @Inject constructor(
        private val userRepository: UserRepository
    )

     

    ๊ทธ๋Ÿฌ๋ฉด Dagger๋Š” ๋ ˆํ† ์ง€ํ† ๋ฆฌ ๊ฐ์ฒด๋ฅผ  ๊ตฌ์„ฑํ•˜๋ ค๊ณ  ํ•  ๊ฒƒ์ด๊ณ , ์ด์— ๋”ฐ๋ผ ํ•„์š”ํ•œ UserLocalDataSource, UserRemoteDataSource ๊ฐ์ฒด๋“ค์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ Dagger์—๊ฒŒ ์•Œ๋ ค์ค˜์•ผํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” @Inject constructor (...)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

    ๋ชจ๋“ˆ

    UserRemoteDataSource์—๋Š” ๋ ˆํŠธ๋กœํ•์ด ์‚ฌ์šฉ๋œ๋‹ค. ๋ ˆํŠธ๋กœํ• ๊ฐ์ฒด ๊ตฌ์„ฑ์„ ์œ„ํ•ด์„œ๋Š” ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šคํ™”๊ฐ€ ์•„๋‹Œ Retrofit.Builder()๋ฅผ ํ˜ธ์ถœํ•ด์•ผํ•œ๋‹ค.

    ์ด ๋•Œ๋Š” @Inject ๋Œ€์‹  @Module์„ ํ†ตํ•ด Dagger์—๊ฒŒ ์ด ํด๋ž˜์Šค๋Š” Dagger ๋ชจ๋“ˆ์ด์•ผ ๋ผ๊ณ  ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋‹ค.

    @Module 
    class NetworkModule {...}

     

    ์—ฌ๊ธฐ์„œ ๋ชจ๋“ˆ์€ ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์บก์Šํ™”ํ•œ ๊ฒƒ์ด๋‹ค. 

    ์•„๋ž˜์—์„œ๋Š” ๋„คํŠธ์›Œํ‚น ๊ด€๋ จ ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋กœ์ง์„ ๊ทธ๋ฃนํ™”ํ•˜๊ธฐ ์œ„ํ•ด NetworkModule ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค. 

    // 1. Dagger ๋ชจ๋“ˆ์ด์•ผ 
    @Module
    class NetworkModule {
    	
        // 2. ์ด ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋ผ
        // ํ”„๋กœ์ ํŠธ๊ฐ€ ์†Œ์œ ํ•˜์ง€ ์•Š์€ ํด๋ž˜์Šค(ex. retrofit, okHttpClient, Gson ๋“ฑ) ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค€๋‹ค.
    	@Provides
        fun provideLoginRetrofitService(
        	okHttpClient : OkHttpClient
        ) : LoginRetrofitService {
        	return Retrofit.Builder()
            		.baseUrl("https://example.com")
                    .build()
                   
                    .create(LoginService::class.java) 
        } 
        
      
    }

     

    ์ด๋ ‡๊ฒŒ ๋ชจ๋“ˆ์„ ์ •์˜ํ•ด์ค€ ํ›„ Dagger ๊ทธ๋ž˜ํ”„๊ฐ€ ์ด ๋ชจ๋“ˆ์— ๊ด€ํ•ด ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด @Component ์ธํ„ฐํŽ˜์ด์Šค์— ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•ด์ค˜์•ผํ•œ๋‹ค.

     

    // modules:  ๊ทธ๋ž˜ํ”„๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ํฌํ•จ๋˜์–ด์•ผํ•  ๋ชจ๋“ˆ์„ ์•Œ๋ ค์ฃผ๋Š” ์—ญํ•  
    @Component(modules = [NetworkModule::class])
    interface ApplicationComponent {...}

     

     

    LoginActivity๋Š” LoginViewModel์ด ํ•„์š”ํ•˜๋‹ค. Dagger๋Š” LoginViewModel & ์ข…์† ํ•ญ๋ชฉ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ด์€ ๊ทธ๋ž˜ํ”„๋ฅผ ๋นŒ๋“œํ•œ๋‹ค. 

    Dagger๋Š” ํด๋ž˜์Šค ์ƒ์„ฑ์ž์˜ @Inject๋Š” ํ†ตํ•ด ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋‹ค. ์ƒ์„ฑํ•œ ApplicationComponent ๋‚ด์—๋Š” ์ œ๊ณต ๋ฐฉ๋ฒ•์„ ์•Œ ๊ณ  ์žˆ๋Š” ๋ชจ๋“  ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค. ๋˜ํ•œ LoginRetrofitService ๊ฐ์ฒด๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด NetworkModule์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.

    ๋ฒ”์œ„

    @Singleton
    @Component(modules = [NetworkModule::class])
    interface ApplicationComponent {
    	fun inject(activity : LoginActivity)
    }
    
    @Singleton
    class UserRepository @Inject constructor(
        private val localDataSource: UserLocalDataSource,
        private val remoteDataSource: UserRemoteDataSource
    ) { ... }
    
    
    @Module
    class NetworkModule {
    	
        @Singleton
        @Provides
        fun provideLoginRetrofitService(): LoginRetrofitService { ... }
    
    }

    ์›ํ•˜๋Š” Scope๋กœ ๊ตฌ์„ฑํ•ด๋ณด์ž

    ๋กœ๊ทธ์ธ ํ๋ฆ„์„ ๊ตฌ์„ฑํ•˜๋Š” ํ™”๋ฉด์ด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ๋กœ ๋˜์–ด์žˆ๋‹ค๋ฉด ๋กœ๊ทธ์ธ ํ๋ฆ„์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ์—์„œ๋Š” ๋™์ผํ•œ LoginViewModel ๊ฐ์ฒด๋ฅผ ์žฌ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

    ๊ทธ๋ ‡๋‹ค๋ฉด ๋กœ๊ทธ์ธ ํ๋ฆ„์ด ์™„๋ฃŒ๋œ ํ›„์—๋Š” ์–ด๋–จ๊นŒ?

    ๋กœ๊ทธ์ธ ํ๋ฆ„์ด ๋๋‚ฌ๋‹ค๋ฉด ์ด์ œ ๋”์ด์ƒ LoginViewModel์ด ๋‚จ์•„์žˆ์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

    ๊ฐ ๋กœ๊ทธ์ธ ํ๋ฆ„๋งˆ๋‹ค , ๋‹ค์‹œ ๋งํ•ด ๋กœ๊ทธ์ธ ํ๋ฆ„์— ๋Œ€ํ•ด์„œ ๋‹ค๋ฅธ LoginViewModel ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค.  ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์•„์›ƒํ•œ ๊ฒฝ์šฐ์—๋Š” ์ฒ˜์Œ ๋กœ๊ทธ์ธํ–ˆ์„ ๋•Œ์™€๋Š” ๋‹ค๋ฅธ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

    ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ตฌํ˜„ ์‹œ์—๋Š” ์ด์ „ ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ๋‚จ์•„์žˆ๊ฑฐ๋‚˜ ์ด์ „ ๋ฐ์ดํ„ฐ๋‚˜ ๋‚จ์•„์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ  ๋ทฐ๋ชจ๋ธ์˜ ๋ฒ”์œ„๋ฅผ LoginActicity์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๋”ฐ๋ผ์„œ ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ผ๋ฉด ๋กœ๊ทธ์ธ ์ „์šฉ Scope๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค.

    @Component
    interface LoginComponent {}

     

    LoginActivity๋Š” ๋กœ๊ทธ์ธ ๋ณ„ ๊ตฌ์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ LoginComponent์—์„œ ์ข…์† ํ•ญ๋ชฉ์„ ๋ฐ›์•„์•ผํ•œ๋‹ค.

    @Component
    interface LoginComponent {
    	fun inject(activity : LoginActivity)
    }

     

    LoginActivity๋Š” LoginViewModel์ด ํ•„์š”ํ•˜๋‹ค. ์ด ๋•Œ LoginViewModel์€ UserRepository์— ์ข…์†๋˜๊ธฐ ๋•Œ๋ฌธ์— LoginComponent๋Š” ApplicationComponent์˜ ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค. ์ด ๋•Œ Dagger์˜ SubComponent๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ์ƒˆ ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ผ๋ถ€๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด @SubComponent์ด๋‹ค.

    ์—ฌ๊ธฐ์„œ ํ•˜์œ„ ๊ตฌ์„ฑ์š”์†Œ๋Š” ์ƒ์œ„ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ์ƒ์† ๋ฐ ํ™•์žฅํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ์ด๋‹ค.  ๋”ฐ๋ผ์„œ ์ƒ์œ„ ๊ตฌ์„ฑ์š”์†Œ์— ์ œ๊ณต๋œ ๋ชจ๋“  ๊ฐ์ฒด๋Š” ํ•˜์œ„ ๊ตฌ์„ฑ์š”์†Œ์—๋„ ์ œ๊ณต๋œ๋‹ค. ์ฆ‰ ApplicationComponent์— ์ œ๊ณต๋œ ๋ชจ๋“  ๊ฐ์ฒด๋Š” LoginComponent์—๋„ ์ œ๊ณต๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    // @SubComponent : Dagger์—๊ฒŒ ์ด ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์ž„์„ ์•Œ๋ ค์ค€๋‹ค.
    @SubComponent
    interface LoginComponent {
    	fun inject(loginActivity: LoginActivity)
    }

     

    ๋˜ํ•œ ApplicationComponent๊ฐ€ LoginComponent์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์•„๋ž˜์™€ ๊ฐ™์ด ํ•˜์œ„ ๊ตฌ์„ฑ์š”์†Œ ํŒฉํ† ๋ฆฌ๋ฅผ ์ •์˜ํ•ด์ค€๋‹ค.

    @Subcomponent
    interface LoginComponent {
    
    	@Subcomponent.Factory
        interface Factory {
        	fun create() : LoginComponent
        }
        
        fun inject(loginActivity: LoginActivity)
    }

     

    ๊ทธ๋ฆฌ๊ณ  LoginComponent๊ฐ€ ApplicationComponent์˜ ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ์ž„์„ Dagger์—๊ฒŒ ์•Œ๋ ค์ค€๋‹ค.

     

    1. ๋จผ์ € ํ•˜์œ„ ๊ตฌ์„ฑ ์š”์†Œ ํด๋ž˜์Šค๋ฅผ subcomponents ์†์„ฑ์— ์ „๋‹ฌํ•˜๋Š” ์ƒˆ๋กœ์šด ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

    @Module(subcomponents = LoginComponent::Class)
    class SubComponentModule {}

     

    2. ์ƒˆ ๋ชจ๋“ˆ์„ ApplicationComponent์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

    @Singleton
    @Component(modules = [NetworkModule::Class, SubComponentsModule::Class])
    interface ApplicationComponent { ... }

     

    ์ด์ œ LoginActivity์— ์ข…์†ํ•ญ๋ชฉ์„ ์ฃผ์ž…ํ•˜๋Š” ๊ฒƒ์€ ApplicationComponent๊ฐ€ ์•„๋‹Œ LoginComponent์ด๊ธฐ ๋•Œ๋ฌธ์— ApplicationComponent ๋‚ด๋ถ€ inject() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๋Œ€์‹  LoginComponent ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŒฉํ† ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•ด์ค€๋‹ค.

    @Singleton
    @Component(modules = [NetworkModule::class, SubcomponentsModule::Class])
    interface ApplicationComponent {
    	// fun inject(activity : LoginActivity) -> ์‚ญ์ œ 
        
        fun loginComponent() : LoginComponent.Factory
    }

     

    LoginComponent์˜ ๋ฒ”์œ„๋Š”?

    LoginComponent๋ฅผ ๋งŒ๋“ค์—ˆ๋˜ ์ด์œ ๋Š”

    1. ๋กœ๊ทธ์ธ ํ๋ฆ„ ์ค‘ ๋™์ผํ•œ LoginViewModel ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ์œ„ํ•จ

    2, ๊ฐ ๋กœ๊ทธ์ธ ํ๋ฆ„๋งˆ๋‹ค๋Š” ๋‹ค๋ฅธ ๋ทฐ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•จ

    ์ด์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ LoginComponent์˜ ์ ์ ˆํ•œ ๊ธฐ๊ฐ„์€ LoginActivity์™€ ๋™์ผํ•˜๋‹ค. ๋ชจ๋“  ์ƒˆ ํ™œ๋™์—๋Š” LoginComponent์˜ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค์™€ ์ด๋Ÿฌํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋ž˜๊ทธ๋จผํŠธ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. 

     

    ์ด๋ ‡๊ฒŒํ•จ์œผ๋กœ์จ LoginComponent๋Š” LoginActivity์˜ ์ˆ˜๋ช…์ฃผ๊ธฐ์™€ ์—ฐ๊ฒฐ๋œ๋‹ค. 

    class LoginActivity : Activity() {
    	// ๋กœ๊ทธ์ธ ๊ทธ๋ž˜ํ”„์— ๋Œ€ํ•œ ์ฐธ์กฐ
    	lateinit var loginComponent : LoginComponent
    
    }

     

    ApplicationComponent๋ฅผ ์‚ฌ์šฉํ•ด์„œ LoginComponent์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„ ๋ณ€์ˆ˜์— ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

    class LoginActivity: Activity() {
    
        lateinit var loginComponent: LoginComponent
        
        // ๋กœ๊ทธ์ธ ๊ทธ๋ž˜ํ”„์— ์˜ํ•ด์„œ ์ฃผ์ž…๋˜์–ด์•ผํ•˜๋Š” ํ•„๋“œ 
        @Inject lateinit var loginViewModel : LoginViewModel
        
         override fun onCreate(savedInstanceState: Bundle?) {
         
         // application ๊ทธ๋ž˜ํ”„๋ฅผ ์ด์šฉํ•ด์„œ ๋กœ๊ทธ์ธ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“ ๋‹ค.
         	loginComponent = (applicationContext as Application).appComponent.loginComponent().create()
           
         // ๋กœ๊ทธ์ธ ์•กํ‹ฐ๋น„ํ‹ฐ์—์„œ @Inject ํ•„๋“œ๋“ค์„ ์ดˆ๊ธฐํ™”ํ•ด์ค€๋‹ค. -> ์‚ฝ์ž… -> ๋ทฐ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•  ์žˆ๋‹ค.
           loginComponent.inject(this)
    
            super.onCreate(savedInstanceState)
        }
        
    }

     

    ์ด ์ฏค์—์„œ ๊ตฌ์กฐ๋ฅผ ํ•œ๋ฒˆ ์ •๋ฆฌํ•ด๋ณด๋ฉด 

    - Application Scope

    • ApplicationComponent : ์•ฑ ์ „์ฒด์˜ ์‹ฑ๊ธ€ํ†ค ์˜์กด์„ฑ ๊ด€๋ฆฌ 
    • NetworkModule(OkhttpClient, Retrofit)๊ณผ ๊ฐ™์€ ์ „์—ญ์ ์œผ๋กœ ํ•„์š”ํ•œ ์˜์กด์„ฑ ํฌํ•จ

    - LoginFlow Scope

    • LoginComponent๋Š” ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ๋งŒ ๋‹ด๋‹น
    • LoginViewModel์€ ์ด scope์•ˆ์—์„œ๋งŒ ์กด์žฌ
    • ๋ชจ๋“  ๋กœ๊ทธ์ธ ํ๋ฆ„๊ณผ ๊ด€๋ ค๋œ ํ™”๋ฉด๋“ค์€ ๋ทฐ๋ชจ๋ธ ๊ณต์œ 

    LoginViewModel์ด ํ•„์š”ํ•œ ๋‘๊ฐœ์˜ ํ”„๋ž˜๊ทธ๋จผํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋‘ ํ”„๋ž˜๊ทธ๋จผํŠธ ๋ชจ๋‘ ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค์™€ ํ•จ๊ป˜ ์ œ๊ณต๋œ๋‹ค.

    @ActivityScope
    @SubComponent
    interface LoginComponent {
    	
        @Subcomponent.Factory
        interface Factory {
        	fun create(): LoginComponent
        }	
        
       // LoginActivity , LoginUsernameFragment , LoginPasswordFragment ๋“ฑ 
       // ๋กœ๊ทธ์ธ๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ํ™”๋ฉด๋“ค์€ LoginComponent์— ์˜์กด์„ฑ ์ฃผ์ž…์„ ์š”์ฒญํ•œ๋‹ค.
       fun inject(loginActivity : LoginActivity)
       fun inject(usernameFragment : LoginUsernameFragment)
       fun inject(passwordFragment : LoginPasswordFragment)
       
    }

     

    ์ด์ œ LoginUsernameFragment์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฒ•์„ ๋ณด์ž

    class LoginUsernameFragment: Fragment() {
    	// ๋กœ๊ทธ์ธ ๊ทธ๋ž˜ํ”„๋กœ๋ถ€ํ„ฐ ์ฃผ์ž…๋˜์–ด์•ผํ•˜๋Š” ํ•„๋“œ
        @Inject lateinit var loginViewModel : LoginViewModel
        
         override fun onAttach(context: Context) {
            super.onAttach(context)
            
            // 1. LoginActivity๋กœ๋ถ€ํ„ฐ login๊ทธ๋ž˜ํ”„ ๊ฐ€์ ธ์˜ค๊ธฐ 
            // 2. ๊ทธ๋ž˜ํ”„๋ฅผ ์‚ฌ์šฉํ•ด์„œ @Inject ํ•„๋“œ๋“ค์„ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ
            
            (activity as LoginActivity).loginComponent.inject(this)
            
            // ์ด์ œ loginViewModel์— ์ ‘๊ทผ ๊ฐ€๋Šฅ, onCreateView์—์„œ๋„ ์ ‘๊ทผ ๊ฐ€๋Šฅ,

    Hilt 

    Dagger์™€ Hilt์˜ ์ฐจ์ด 

    • ์ฝ”๋“œ๋กœ ์‚ดํŽด๋ณด๊ธฐ
    // Dagger
    
    // Hilt

     

     

     

    728x90