build logic을 적용한 후, 모듈간의 의존성이 의도한 것과 같이 참조되고 있는지 확인을 하기 위해 module dependency graph를 통해 의존성을 시각화해보았다.
의존성 시각화를 윟서는 이전에도 사용해본 플러그인을 활용해 의존성 그래프를 추출해보았다.
참고: module dependency graph를 뽑아내기 위해 다음의 플러그인을 사용하였다. 해당 플러그인을 활용할 경우, 명령어를 통해서 프로젝트에 대한 모듈 의존성 그래프를 자동으로 추출할 수 있다.
https://github.com/vanniktech/gradle-dependency-graph-generator-plugin
우리 프로젝트에서는 클린 아키텍처를 기반으로 모듈화를 진행하였다. 현재 main feature 모듈에서 login feature 모듈에 대한 참조를 가지고 있다. 그렇다면 이렇게 하나의 feature가 또 다른 feature에 대해 의존성을 가지고 있는 것이 올바른 의존성 방향일까?
우선 feature별로 모듈화를 한 이유에 대해 생각해보자. clean architecture에서 모듈을 나누는 이유는 관심사 분리를 위해서이다. 즉, 모든 feature를 하나의 모듈에서 관리하는 것보다 각각의 모듈로 구분해 로직을 분리함으로써 각 feautre 모듈은 해당 feature에 대해서만 고민하고 다루면 된다.
feature에 따라 관심사를 분리하고 로직을 관리하기 위해 feature별로 모듈을 구분하였기 때문에 위와 같이 하나의 feature에서 또 다른 feature에 의존하는 상황은 최대한 발생하지 않도록 하는 것이 더 맞다는 판단을 하게 되었다.
main 모듈에서 login 모듈에 의존할 수밖에 없는 이유는 login 모듈에서만 사용되는 UserUiModel
에 대한 참조를 main navigation logic이 가져야 하기 때문이다.
fun NavGraphBuilder.mainNavGraph(
onNavigationButtonClick: () -> Unit,
onNotificationButtonClick: () -> Unit,
onCreateStudyButtonClick: () -> Unit,
onEditStudyButtonClick: (String) -> Unit,
onStudyGroupClick: (String) -> Unit,
onEditUserClick: (UserUiModel?, String?) -> Unit,
onLoginOutClick: () -> Unit,
)
그렇다면 이를 어떻게 해결할 수 있을까?
mainNavGraph 로직을 Login으로 옮기는 방식
main에 대한 로직을 login이 가지고 있는 것은 옳지 않다.
UserUiModel
를 login / main 모두 접근할 수 있도록 상위 모듈로 뺀다.
실질적으로 UserUiModel
을 필요로 하는 모듈은 login 모듈만이다. 따라서 공통으로 빼 다른 모듈이 모두 접근이 가능하도록 하는 것은 옳지 않다.
navigationSignUp 오버로딩
fun NavController.navigationSignUp(
userUiModel: UserUiModel? = null,
userId: String? = null,
) {
navigate(SignUpRoute(userUiModel, userId))
}
fun NavController.navigationSignUp( // 오버로딩
userId: String? = null,
) {
navigate(SignUpRoute(userId = userId))
}
오버로딩 함수를 main 모듈에서 사용한다면 불필요하게 UserUiModel
을 알 필요가 없어진다.