2025. 2. 7. 14:39ㆍKotlin Project/Chosung Market
https://github.com/KwonGeneral/chosungmarket.git
GitHub - KwonGeneral/chosungmarket: 초성마켓
초성마켓. Contribute to KwonGeneral/chosungmarket development by creating an account on GitHub.
github.com
안녕하세요~!
이번 포스트는 DI 관련된 내용입니다.
제가 Kotlin으로 클린 아키텍처를 적용하기 위해서 라이브러리를 살펴봤는데요, 검색 과정에서 제가 모르던 단어도 알게됬습니다. 저는 의존성 역전, 의존성 주입이라는 키워드로 검색을 했는데, 이걸 줄여서 DI(Dependency Injection)이라고 부르더라고요.
여러 라이브러리가 존재하는데 저는 Koin을 채택했습니다. 저번 포스트에 말씀드렸던 것 처럼, 런타임 방식이라서 소규모 프로젝트에 적합할 것 같아서 채택했습니다.
Dagger2는 빌드 방식이고, Koin은 런타임 방식인데, Hilt는 좀 어중간한 포지션이더라구요. (제가 Android DI 관련 라이브러리 지식이 없어서 가볍게 언급하는겁니다~)
아무튼! Koin을 적용해보도록 하겠습니다!
먼저, dependencies에 추가해줍시다!

그 다음에, libs.versions.toml에 버전을 명시해줍시다! 저는 가장 최신 버전을 사용해보겠습니다~

그리고나서, 새로운 패키지로 di를 만들어줍시다!

그런 다음에, dataModule은 data 레이어를 엮어주고, domainModule은 domain 레이어를 엮어주면 되겠습니다~!


사실, 클린 아키텍처를 적용하면 이미 의존성 관련된 부분은 대부분 해결이 된 상황이고, 라이브러리를 통해 더 깔끔하게 코드를 작성할 수 있습니다.
koin 사용 예시를 보고 한번 시도해봤는데요, 대충 아래처럼 사용하면 됩니다.
sealed class QuizState {
object Loading : QuizState()
data class Success(val quizGroups: List<QuizGroupData>) : QuizState()
data class Error(val message: String) : QuizState()
object QuizSubmitted : QuizState()
}
# 1. ViewModel 주입받기
@Composable
fun QuizScreen(
viewModel: QuizViewModel = koinViewModel()
) {
// ViewModel 사용
val quizState by viewModel.quizState.collectAsStateWithLifecycle()
}
# 2. Dependency 직접 주입받기
@Composable
fun UserProfileScreen() {
// Repository 직접 주입
val userRepository: UserRepositoryImpl = get()
// UseCase 직접 주입
val updateProfileUseCase: UpdateProfileUseCase = get()
}
# 3. ViewModel 예제
class QuizViewModel(
private val quizRepository: QuizRepositoryImpl,
private val sessionRepository: SessionRepositoryImpl,
private val processQuizResultUseCase: ProcessQuizResultUseCase
) : ViewModel() {
private val _quizState = MutableStateFlow<QuizState>(QuizState.Loading)
val quizState = _quizState.asStateFlow()
init {
viewModelScope.launch {
// Repository 사용
quizRepository.observeQuizGroups()
.collect { quizGroups ->
_quizState.value = QuizState.Success(quizGroups)
}
}
}
fun submitQuiz(quizGroupId: String, answers: List<String>) {
viewModelScope.launch {
try {
processQuizResultUseCase.invoke(quizGroupId, answers)
.onSuccess {
_quizState.value = QuizState.QuizSubmitted
}
.onFailure { error ->
_quizState.value = QuizState.Error(error.message ?: "알 수 없는 오류가 발생했습니다.")
}
} catch (e: Exception) {
_quizState.value = QuizState.Error(e.message ?: "알 수 없는 오류가 발생했습니다.")
}
}
}
}
# 4. ViewModel 모듈 설정
val viewModelModule = module {
viewModel { QuizViewModel(get(), get(), get()) }
viewModel { UserProfileViewModel(get(), get()) }
viewModel { HomeViewModel(get(), get(), get()) }
}
클린 아키텍처를 적용하기 위해서는 오늘 포스트보다는 이전의 포스트들이 더 중요합니다.
드디어.. 어느정도 구조는 잡은 것 같습니다. 짧은 시간동안 집중력있게 했더니 너무 지치네요..
color, textstyles, theme, router도 어느정도 만들어 뒀으니 이제 화면을 밀고 나가면 될 것 같습니다.
사실 저한테는 지금부터가 더 고비에요.
저는 정말 디자인에 소질이 없어서.. 핀터레스트를 많이 참고해야할 것 같습니다.
다음 포스트부터는 화면에 대한 글을 작성하겠습니다~!
'Kotlin Project > Chosung Market' 카테고리의 다른 글
[Kotlin Project] 초성마켓 - 홈, 퀴즈 페이지 개발 (0) | 2025.02.10 |
---|---|
[Kotlin Project] 초성마켓 - 로그인 페이지 개발 (0) | 2025.02.07 |
[Kotlin Project] 초성마켓 - 클린 아키텍처 적용: Data 레이어 개발 (0) | 2025.02.07 |
[Kotlin Project] 초성마켓 - 카카오 로그인 환경 구성 (0) | 2025.02.07 |
[Kotlin Project] 초성마켓 - 파이어베이스 환경 구성 및 DB 구현 (1) | 2025.02.07 |