Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/navigation/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
alias(libs.plugins.twix.android.library)
alias(libs.plugins.twix.android.compose)
alias(libs.plugins.twix.koin)
}

android {
Expand Down
60 changes: 60 additions & 0 deletions core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.twix.navigation

import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.twix.navigation.base.NavGraphContributor
import org.koin.compose.getKoin

@Composable
fun AppNavHost() {
val navController = rememberNavController()
val koin = getKoin()
val contributors = remember {
koin.getAll<NavGraphContributor>().sortedBy { it.priority }
}
Comment on lines +20 to +22
Copy link

@coderabbitai coderabbitai bot Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# AppNavHost.kt 파일 찾기 및 내용 확인
find . -type f -name "AppNavHost.kt" | head -5

Repository: YAPP-Github/Twix-Android

Length of output: 133


🏁 Script executed:

# NavGraphContributor 인터페이스 정의 찾기
rg -n --type=kotlin "interface NavGraphContributor|class NavGraphContributor"

Repository: YAPP-Github/Twix-Android

Length of output: 180


🏁 Script executed:

# NavGraphContributor 구현 클래스 검색
rg -n --type=kotlin ":\s*NavGraphContributor" | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

cat -n ./core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt | head -35

Repository: YAPP-Github/Twix-Android

Length of output: 1595


🏁 Script executed:

cat -n ./core/navigation/src/main/java/com/twix/navigation/base/NavGraphContributor.kt

Repository: YAPP-Github/Twix-Android

Length of output: 678


🏁 Script executed:

# 다른 패턴으로 NavGraphContributor 구현체 검색
rg -n --type=kotlin "NavGraphContributor" -A 1 -B 1 | grep -E "(class|object)" | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# 모든 코틀린 파일에서 NavGraphContributor 참조 및 구현 찾기
rg -n --type=kotlin "NavGraphContributor" -B 2 -A 5 | grep -A 7 "^[0-9]*.*class\|^[0-9]*.*object"

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# 다른 방식으로: object나 class 정의 후 : NavGraphContributor 찾기
ast-grep --pattern 'class $_ : $$$NavGraphContributor$$$'

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# Koin 모듈 파일에서 NavGraphContributor 등록 확인
rg -n --type=kotlin "NavGraphContributor" -B 3 -A 3 | head -50

Repository: YAPP-Github/Twix-Android

Length of output: 2335


🏁 Script executed:

# 프로젝트 구조 확인
ls -la | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 1224


🏁 Script executed:

# 모듈 목록 확인
find . -maxdepth 2 -type d -name "feature*" -o -name "*Graph*" 2>/dev/null | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 77


🏁 Script executed:

# 더 광범위한 NavGraphContributor 구현 검색
find . -type f -name "*.kt" -exec grep -l "NavGraphContributor" {} \; | head -30

Repository: YAPP-Github/Twix-Android

Length of output: 213


🏁 Script executed:

# feature 모듈 내부 구조 확인
find ./feature -type f -name "*.kt" | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 129


🏁 Script executed:

# Koin 모듈 설정 파일 찾기
rg -n --type=kotlin "module\s*{|NavGraphContributor" -B 2 -A 5

Repository: YAPP-Github/Twix-Android

Length of output: 190


🏁 Script executed:

# 프로젝트 전체에서 "koin.getAll" 또는 "single<NavGraphContributor>" 검색
rg -n --type=kotlin "(getAll|single).*NavGraphContributor|factory.*NavGraphContributor"

Repository: YAPP-Github/Twix-Android

Length of output: 202


🏁 Script executed:

# Koin 관련 설정 파일 모두 찾기
find . -type f -name "*Koin*.kt" -o -name "*Module*.kt" -o -name "*Di*.kt" 2>/dev/null | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 152


🏁 Script executed:

# app 모듈의 구조 확인
find ./app -type f -name "*.kt" | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 120


🏁 Script executed:

# 모든 코틀린 파일에서 "module {" 패턴 찾기
rg -n --type=kotlin "^\s*module\s*\{" -A 10 | head -50

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

cat -n ./app/src/main/java/com/yapp/twix/TwixApplication.kt

Repository: YAPP-Github/Twix-Android

Length of output: 526


🏁 Script executed:

cat -n ./build-logic/convention/src/main/kotlin/com/twix/convention/KoinConventionPlugin.kt | head -50

Repository: YAPP-Github/Twix-Android

Length of output: 444


🏁 Script executed:

# 전체 코드베이스에서 NavGraphContributor를 구현한 클래스 또는 object 찾기
rg -n --type=kotlin "class\s+\w+.*:\s*.*NavGraphContributor|object\s+\w+.*:\s*.*NavGraphContributor"

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# modules() 함수 정의 찾기
rg -n --type=kotlin "fun\s+modules\s*\(" -A 20

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# 혹은 modules 변수 정의
rg -n --type=kotlin "val\s+modules.*=|object.*modules"

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# TwixApplication.kt 파일의 import 문을 포함한 전체 내용
cat -n ./app/src/main/java/com/yapp/twix/TwixApplication.kt

Repository: YAPP-Github/Twix-Android

Length of output: 526


🏁 Script executed:

# app 모듈 전체 파일 목록
find ./app -type f -name "*.kt" -o -name "*.xml"

Repository: YAPP-Github/Twix-Android

Length of output: 570


🏁 Script executed:

# modules 함수 또는 변수 전역 검색 (확장함수 포함)
rg -n "modules" --type=kotlin | grep -E "(fun|val|object|package|import)" | head -30

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# startKoin 호출 주변의 모든 코드 확인
rg -n --type=kotlin "startKoin" -B 5 -A 10

Repository: YAPP-Github/Twix-Android

Length of output: 1269


🏁 Script executed:

# app 모듈의 build.gradle.kts 확인
find ./app -name "build.gradle.kts" -exec cat -n {} \;

Repository: YAPP-Github/Twix-Android

Length of output: 1152


🏁 Script executed:

# 전체 코드베이스에서 "modules()" 함수 정의 찾기
rg -n --type=kotlin "fun.*modules\s*\(" -A 3

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# Koin 설정 관련 파일 모두 찾기
find . -path ./build-logic -prune -o -type f -name "*.kt" -exec grep -l "module\s*{" {} \; 2>/dev/null | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# twix.koin 플러그인 찾기
find ./build-logic -name "*koin*" -o -name "*Koin*" | grep -i kotlin

Repository: YAPP-Github/Twix-Android

Length of output: 152


🏁 Script executed:

# feature/login 모듈 구조
find ./feature/login -type f -name "*.kt" | head -20

Repository: YAPP-Github/Twix-Android

Length of output: 129


🏁 Script executed:

# feature/login 모듈에서 NavGraphContributor 관련 검색
rg -n --type=kotlin "NavGraphContributor" ./feature/login -A 5 -B 5

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# 직접 전체 feature/login 디렉토리 구조 확인
find ./feature/login -type f

Repository: YAPP-Github/Twix-Android

Length of output: 322


🏁 Script executed:

# LoginActivity.kt 내용 확인
cat -n ./feature/login/src/main/java/com/twix/login/LoginActivity.kt

Repository: YAPP-Github/Twix-Android

Length of output: 382


🏁 Script executed:

# 전체 코드베이스에서 실제로 NavGraphContributor를 상속받는 구현 검색
rg -n "NavGraphContributor" --type=kotlin -c

Repository: YAPP-Github/Twix-Android

Length of output: 213


NavGraphContributor 구현체가 없어 현재 코드가 실행되지 않는 상태입니다.

코드베이스 전체를 검색한 결과, NavGraphContributor 인터페이스는 정의되어 있으나 이를 구현한 클래스가 존재하지 않습니다. 따라서 koin.getAll<NavGraphContributor>()는 항상 빈 리스트를 반환하며, 결과적으로 23-26줄의 error("해당 Graph를 찾을 수 없습니다.")가 필연적으로 실행됩니다.

이를 해결하기 위해서는:

  1. feature 모듈들에서 NavGraphContributor 구현체 작성 - 각 feature(예: login, home 등)마다 해당 그래프를 등록하는 구현체 필요
  2. Koin 모듈 설정 완성 - TwixApplication에서 호출하는 modules() 함수 정의 및 각 feature의 Koin 모듈 연결
  3. 에러 메시지 개선 (필요시) - 현재 에러 메시지도 명확하지만, 구현체 등록 후 다음과 같이 개선 가능:
    val start = contributors
        .firstOrNull { it.graphRoute == NavRoutes.LoginGraph }
        ?.graphRoute
        ?: error("LoginGraph를 찾을 수 없습니다. 등록된 그래프: ${contributors.map { it.graphRoute }}")
🤖 Prompt for AI Agents
core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt lines 20-22:
koin.getAll<NavGraphContributor>()가 빈 리스트를 반환하여 error(...)가 실행되는 문제를 고치려면 각
feature 모듈(login, home 등)에 NavGraphContributor 인터페이스 구현체를 추가하고 해당 구현체들을 포함한 Koin
모듈을 작성하여 TwixApplication의 modules() 호출에 등록하세요; 또한 Koin 설정이 누락됐는지 확인하고 통합 테스트로
koin.getAll이 기대하는 구현체들을 반환하는지 검증하며(선택 사항) 런타임에 바로 크래시 대신 등록된 그래프 목록을 출력하도록 error
메시지를 더 구체화해 주세요.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이후에 :feature:*에서 구현할 예정

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dogmania, 네, feature 모듈에서 구현 예정이시군요! 이해했습니다.

추후 디버깅을 쉽게 하기 위해 다음과 같은 개선을 고려해보시면 좋을 것 같습니다 (선택 사항):

val contributors = remember {
    koin.getAll<NavGraphContributor>().sortedBy { it.priority }
}

// TODO: feature 모듈에서 NavGraphContributor 구현체 추가 필요
val start = contributors
    .firstOrNull { it.graphRoute == NavRoutes.LoginGraph }
    ?.graphRoute
    ?: error(
        "LoginGraph를 찾을 수 없습니다. " +
        "등록된 그래프 수: ${contributors.size}, " +
        "그래프 목록: ${contributors.map { it.graphRoute }}"
    )

이렇게 하면:

  • TODO 주석으로 구현이 필요한 부분을 명시
  • 에러 발생 시 등록된 그래프 정보를 출력하여 누락된 구현체를 쉽게 파악 가능

하지만 현재 구조도 충분히 명확하므로, 선호하시는 방식으로 진행하셔도 됩니다! 👍

val start = contributors
.firstOrNull { it.graphRoute == NavRoutes.LoginGraph }
?.graphRoute
?: error("해당 Graph를 찾을 수 없습니다.")
val duration = 300

NavHost(
navController = navController,
startDestination = start.route,
enterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
)
},
exitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
)
},
popEnterTransition = {
slideInHorizontally(
initialOffsetX = { fullWidth -> -fullWidth },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
)
},
popExitTransition = {
slideOutHorizontally(
targetOffsetX = { fullWidth -> fullWidth },
animationSpec = tween(duration, easing = FastOutSlowInEasing)
)
},
modifier = Modifier.fillMaxSize()
) {
contributors.forEach { with(it) { registerGraph(navController) } }
}
}
20 changes: 20 additions & 0 deletions core/navigation/src/main/java/com/twix/navigation/NavRoutes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.twix.navigation

/**
* 앱 전반에서 사용하는 Navigation Route를 여기에서 정의합니다.
*
* · 문자열 route를 직접 사용하지 않고 타입 안정성을 위해 sealed class를 활용합니다.
* · navigation argument가 필요한 경우 createRoute()를 통해 route를 생성합니다.
* · Graph의 경우 _graph로 네이밍하고 Screen의 경우에는 Composable명에서 Screen을 제외한 앞부분을 활용합니다. ex) HomeScreen -> home
* */
sealed class NavRoutes(val route: String) {
object LoginGraph: NavRoutes("login_graph")
object Login: NavRoutes("login")

object HomeGraph: NavRoutes("home_graph")
object Home: NavRoutes("home")

object HomeDetail: NavRoutes("home_detail/{id}") {
fun createRoute(id: String) = "home_detail/$id"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.twix.navigation.base

import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import com.twix.navigation.NavRoutes

/**
* priority는 우선적으로 등록해야 하는 Graph에서 값을 낮춰 사용하면 됩니다.
* ex) SplashGraph는 앱 내에서 가장 먼저 실행되어야 하는 그래프이므로 priority를 낮춰주면 됩니다.
**/
interface NavGraphContributor {
val graphRoute: NavRoutes
val startDestination: String
val priority: Int get() = 100

fun NavGraphBuilder.registerGraph(navController: NavHostController)
}
Comment on lines +11 to +17
Copy link

@coderabbitai coderabbitai bot Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -n --type=kotlin -C 3 'startDestination'

Repository: YAPP-Github/Twix-Android

Length of output: 1528


🏁 Script executed:

# AppNavHost.kt 상세 확인
cat -n core/navigation/src/main/java/com/twix/navigation/AppNavHost.kt | sed -n '15,45p'

Repository: YAPP-Github/Twix-Android

Length of output: 1281


🏁 Script executed:

# NavGraphContributor의 구현체 찾기
rg -n --type=kotlin 'class.*:.*NavGraphContributor'

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# startDestination 프로퍼티 직접 사용처 검색 (contributor.startDestination 패턴)
rg -n --type=kotlin '\.startDestination'

Repository: YAPP-Github/Twix-Android

Length of output: 50


🏁 Script executed:

# NavGraphContributor를 구현하는 모든 파일 찾기
rg -n --type=kotlin 'NavGraphContributor' -A 10 | head -50

Repository: YAPP-Github/Twix-Android

Length of output: 2681


🏁 Script executed:

# startDestination에 대한 모든 언급 찾기 (주석 포함)
rg -n --type=kotlin --type-add='kt:include:*.kt' 'startDestination' -B 2 -A 2

Repository: YAPP-Github/Twix-Android

Length of output: 127


🏁 Script executed:

# 간단하게 startDestination 모든 언급 찾기
grep -rn "startDestination" --include="*.kt" core/

Repository: YAPP-Github/Twix-Android

Length of output: 288


startDestination 프로퍼티는 현재 사용되지 않고 있습니다. 제거하거나 명확히 문서화해야 합니다.

NavGraphContributor 인터페이스의 전반적인 설계는 우수합니다:

장점:

  • NavRoutes 타입으로 타입 안전성 확보
  • priority 기본값 제공으로 대부분의 경우 간편하게 사용 가능
  • extension function 패턴으로 Compose Navigation과 자연스럽게 통합

⚠️ 개선 필요:
startDestination 프로퍼티가 정의되어 있지만 코드 전체에서 실제로 사용되지 않습니다. 현재 AppNavHost에서는 graphRoute만 접근하여 시작 지점을 결정하고 있습니다.

개선 방안:

  • 단기: 현재 사용되지 않는 프로퍼티이므로 제거
  • 또는 중첩된 navigation graph의 시작점을 지정하기 위한 의도된 설계라면, registerGraph 구현에서 실제로 활용하고 주석으로 명확히 문서화
🤖 Prompt for AI Agents
In core/navigation/src/main/java/com/twix/navigation/base/NavGraphContributor.kt
around lines 11 to 17, the startDestination property is declared but never used;
either remove the unused property from the interface to avoid dead API surface,
or, if it was intended to mark nested graph entry points, update the interface
docs and the registerGraph implementations to consume startDestination (e.g.,
use it when building a nested NavGraph) and add a KDoc comment on
startDestination explaining its purpose and expected usage; choose one approach
and apply it consistently across all implementers and callers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:feature:*에서 NavGraphContributor 구현체를 만들 때 사용할 예정

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dogmania, 이해했습니다! 현재는 기본 인프라를 구축하는 단계이고, 실제 feature 모듈에서 NavGraphContributor를 구현할 때 startDestination이 활용될 예정이군요.

이러한 설계는 합리적입니다. 각 feature의 navigation graph는 여러 화면으로 구성될 수 있고, startDestination으로 해당 그래프 내의 시작 화면을 명시하는 것이 필요합니다.

다만 향후 유지보수를 위해 KDoc에 사용 예시를 추가하는 것을 고려해보세요:

/**
 * Navigation Graph 등록을 위한 기본 인터페이스
 * 
 * priority는 우선적으로 등록해야 하는 Graph에서 값을 낮춰 사용하면 됩니다.
 * ex) SplashGraph는 앱 내에서 가장 먼저 실행되어야 하는 그래프이므로 priority를 낮춰주면 됩니다.
 * 
 * @property graphRoute 전체 앱에서 해당 그래프를 식별하는 route
 * @property startDestination 해당 그래프 내에서 시작 화면의 route
 * @property priority 그래프 등록 우선순위 (낮을수록 먼저 등록)
 */