wafflestudio / seminar-2020

2020 Rookies 세미나

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Repository에서 RoomDB와 Retrofit을 함께 사용할 경우 injection 방식 및 context의 활용

veldic opened this issue · comments

(파일의 구조가 의도하셨던 것과 다르다면 그 부분도 지적해주시면 감사하겠습니다! 구현하다보니 무언가 잘못되어가는 것을 느끼고 있어서요...
TokenRepository가 아니라 LoginRepository 등으로 만들어 내부에서 Token을 따로 처리해야될 것 같다는 생각이 들었습니다.)

이번 과제에서 token을 발급받은 뒤, persist하게 유지하여야 하는 조건이 있었습니다.
이를 구현하기 위해 TokenRepository에서 Retrofit으로 http 통신을 통해 token 등을 받아오는 작업 및 room database에 저장하는 작업을 진행하려 합니다.

이 과정에서 Injection을 이용하려고 했는데 맞게 구현하고 있는 것인지 궁금하여 issue를 남깁니다. SimpleTodo 과제와 MovieDB 과제를 참고하여 진행중입니다.

https://github.com/wafflestudio/rookies/blob/e6b1718b0697f050e6a608bd8a7cb389bf480a30/android/assignment3/MovieDb/app/src/main/java/com/example/moviedb/repository/MovieRepository.kt#L5
MovieDB에서는 retrofit 사용을 위해 service를 받아오기 때문에 위와 같이 코드가 작성되어
https://github.com/wafflestudio/rookies/blob/e6b1718b0697f050e6a608bd8a7cb389bf480a30/android/assignment3/MovieDb/app/src/main/java/com/example/moviedb/di/RepositoryModule.kt#L8
이렇게 injection을 해 주었고

https://github.com/wafflestudio/rookies/blob/e6b1718b0697f050e6a608bd8a7cb389bf480a30/android/assignment2/SimpleTodo/app/src/main/java/com/sanggggg/simpletodo/room/TodoRepository.kt#L7
SimpleTodo에서는 Room database 사용을 위해 context를 받아와서 위와 같이 작성되었고
https://github.com/wafflestudio/rookies/blob/e6b1718b0697f050e6a608bd8a7cb389bf480a30/android/assignment2/SimpleTodo/app/src/main/java/com/sanggggg/simpletodo/utils/InjectionUtils.kt#L10-L16
https://github.com/wafflestudio/rookies/blob/1fce5892df9d10d93b1eb12546df100593e3767d/android/assignment2/SimpleTodo/app/src/main/java/com/sanggggg/simpletodo/ui/MainActivity.kt#L27-L29
이렇게 MainActivity의 context가 넘어가는 것을 확인하였습니다.

그렇다면 저는 retrofit과 RoomDB를 함께 구현하기 위해서 context와 service를 함께 받아와야 한다고 판단하였습니다.
그래서 TokenRepository를 다음과 같이 구현하였습니다.

  1. 다음과 같이 Injection을 하는 방식이 맞을까요?

class TokenRepository(context: Context, private val service : TokenService)
이 repository에 injection해주기 위해 RepositoryModule을 다음과 같이 설정했습니다.
val repositoryModule = module { single { TokenRepository(get(), get()) } }
위처럼 구현하게 된다면 SeminarManagerApplication에서 applicationContext가 TokenRepository에 Injection 된다고 생각했습니다.

  1. 그렇다면 SimpleTodo 코드에 있는
    https://github.com/wafflestudio/rookies/blob/1fce5892df9d10d93b1eb12546df100593e3767d/android/assignment2/SimpleTodo/app/src/main/java/com/sanggggg/simpletodo/room/TodoDatabase.kt#L20-L26
    위 부분에서 context.applicationContextcontext로 단순히 사용할 수 있을 것 같는데 맞는 방식인지 질문드립니다.

  2. 약간 늦은 질문일 수 있는데 SimpleTodo에서 InjectionUtils.kt를 사용한 이유는 단순히 Koin을 사용하지 않은 채로 DI를 구현했기 때문인가요?

  1. koin 에서 context injection 은 미리 정의된 androidApplication() 으로 가져올 수 있습니다.
val repositoryModule = module {
    single { TokenRepository(androidApplication(), get()) }
}

아래 이슈를 참고하세요
InsertKoinIO/koin#190

  1. 음... context 는 activity 의 context 일 수도 있고, service 의 context 일 수도 있고, application 의 context 일 수도 있습니다. 이때 activity 의 context 로 Db instance 를 만들게 되면 해당 activity 가 destroy 되고 나서도 그 activity 의 context 를 db 가 가지고 있어 제대로 가비지 컬렉션 되지 않는 문제도 발생할 수 있습니다. 따라서 singleton 한 db instance 에 적절한 (같은 singleton 느낌인) applicationContext 가 적절할 것 같네요.

  2. 네 koin, dagger 와 같은 di 라이브러리에서 해주는 일을 직접 코드로 작성한 셈이죠.

추가로, 이번 과제에서는 persist 하게 유지해야하는 정보가 user token (더 커봤자 user model) 정도로 꼭 room db 를 사용할 필요까지는 없다고 느껴집니다. 따라서 sharedPreference 를 활용해 좀 더 가벼운 코드로 persistance 를 유지시켜도 좋은 방향일 것 같습니다.

@sanggggg
아 2번 질문은 1번 질문에 연결되어 질문드린건데요, 2번의 코드 부분에서 application의 context를 이용해야 한다는 것을 인지하였기 때문에 1번 질문에서 application context를 받아올 수 있다면 2번 질문과 같이 수정해서 사용하면 되는 것인가에 대한 질문이었습니다! 아마 답변해주신 내용을 보니 가능한 방식이라는 생각은 드네요