NavHost — Jetpack Compose에서 내비게이션 그래프 및 경로 구축하기

저자: IT Sectr 게시일: 2026-06-30 읽는 시간: 7 분

NavHost는 Jetpack Compose에서 내비게이션 그래프의 진입점 역할을 하는 composable 컨테이너입니다. NavController를 경로 집합에 연결하고 백 스택 상태에 따라 현재 화면을 렌더링합니다. Android Developers(2025)에 따르면 NavHost는 내비게이션이 있는 모든 Compose 앱에 필수 구성 요소입니다. NavHost 내부에는 선택적 인수, 딥 링크 및 애니메이션과 함께 composable 경로가 등록됩니다. 각 경로는 전환 데이터와 함께 NavBackStackEntry를 수신하는 일반 composable 함수입니다. NavHost는 뒤로 가기, 상태 저장 및 재구성 시 복원을 자동으로 처리합니다.

주요 내용

  • NavHost — NavController를 경로 그래프에 연결하고 현재 화면을 렌더링하는 composable 컨테이너
  • composable() — 경로, 인수, 딥 링크 및 전환 애니메이션으로 경로를 등록하는 함수
  • startDestination — NavHost 생성 시 열리는 초기 경로
  • 인수는 화면 간 유형화된 데이터 전송을 위해 navArgument 및 NavType을 통해 정의됩니다
  • 애니메이션은 enterTransition, exitTransition 매개변수를 통해 전역 또는 개별적으로 구성됩니다

Jetpack Compose에서 NavHost란?

NavHost는 현재 내비게이션 화면을 표시하기 위한 컨테이너를 제공하는 composable 함수입니다. NavHost는 NavController, startDestination 및 Kotlin DSL로 구축된 경로 그래프를 사용합니다. 현재 경로가 변경되면 NavHost는 지정된 애니메이션으로 표시된 composable을 전환합니다.

NavHost는 화면 전환기로 작동합니다. NavController에서 현재 NavBackStackEntry를 추적하고 해당 composable 블록을 렌더링합니다. 각 화면은 독립적인 composable 함수이며 경로 인수와 함께 NavBackStackEntry를 수신합니다. 모든 화면은 단일 컴포지션 트리에 존재하지만 NavHost는 한 번에 하나만 표시하고 나머지는 애니메이션을 통해 숨깁니다.

FragmentManager와 달리 NavHost는 각 화면에 대해 Fragment를 만들지 않습니다. 전체 수명 주기는 CompositionLifecycle을 통해 관리됩니다. composable 함수에는 onStart/onResume이 없으므로 부작용을 위해 LaunchedEffect 및 DisposableEffect가 사용됩니다. NavHost는 자동으로 NavController를 구독하고 경로가 변경되면 UI를 재구성합니다.

Google에 따르면 NavHost는 Navigation 2.4.0부터 안정적인 API입니다. 2.8.0부터 NavHost는 Kotlin Serialization을 통한 유형 안전 내비게이션을 지원하여 문자열 경로를 데이터 클래스로 대체합니다. NavHost는 중첩된 그래프도 지원하므로 모듈 기반 내비게이션 구성이 가능합니다.

NavHost는 두 개의 필수 매개변수로 생성됩니다: navController(NavHostController 인스턴스) 및 startDestination(첫 번째 화면의 경로 문자열). 세 번째 매개변수는 composable(), navigation() 및 dialog()를 통해 모든 경로가 등록되는 빌더 블록입니다.

kotlin
@Composable
fun AppNavHost(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = "home"
    ) {
        composable("home") { HomeScreen(navController) }
        composable("settings") { SettingsScreen(navController) }
    }
}

startDestination은 NavHost가 처음 시작될 때 열리는 경로입니다. 백 스택이 비어 있으면 NavHost가 자동으로 startDestination을 스택에 추가합니다. 재구성(화면 회전) 시 NavHost는 savedState에서 마지막 경로를 복원하며 startDestination을 복원하지 않습니다.

BottomNavigation의 경우 startDestination은 하단 패널 경로 중 하나입니다. 나머지 패널 경로는 별도의 composable 항목으로 추가됩니다. NavHost는 Scaffold.content 내부에 배치해야 합니다. 여기에 기본 앱 콘텐츠가 표시됩니다. NavHost는 TopAppBar 및 BottomNavigation을 제외한 사용 가능한 모든 높이를 차지합니다.

composable을 통한 경로 등록

composable(route, arguments, deepLinks, enterTransition, exitTransition, content) 함수는 NavHost 그래프에 경로를 등록합니다. route 매개변수는 {paramName} 형식의 선택적 자리 표시자가 있는 경로를 설명하는 문자열입니다. 내비게이션 중에 자리 표시자는 실제 값으로 대체됩니다.

composable의 content 블록은 인수가 추출되는 NavBackStackEntry를 수신합니다. 화면 composable 함수는 현재 NavController 경로가 경로와 일치하는 경우에만 렌더링됩니다. 일치하지 않으면 composable이 컴포지션에서 제거되지만 rememberSaveable 또는 SavedStateHandle이 있는 ViewModel을 통해 상태를 보존할 수 있습니다.

kotlin
composable(
    route = "article/{articleId}",
    arguments = listOf(navArgument("articleId") {
        type = NavType.IntType
        defaultValue = 0
    }),
    deepLinks = listOf(navDeepLink { uriPattern = "https://app.example/article/{articleId}" })
) { backStackEntry ->
    val articleId = backStackEntry.arguments?.getInt("articleId") ?: 0
    ArticleScreen(articleId = articleId)
}

NavHost 내의 composable 항목 수는 몇 개에서 수백 개까지 다양합니다. 대규모 애플리케이션의 경우 경로가 모듈 간에 분할되고 중첩된 그래프를 통해 연결됩니다. 각 composable은 고유한 애니메이션 설정, 딥 링크 및 인수를 가질 수 있습니다.

인수 및 유형화된 경로 매개변수

경로 인수는 composable()의 arguments: List<NamedNavArgument> 매개변수를 통해 정의됩니다. 각 인수는 navArgument(name) { type; defaultValue }를 통해 정의됩니다. NavType은 인수 유형을 결정합니다: StringType, IntType, LongType, FloatType, BoolType, ParcelableType 및 ReferenceType.

경로 매개변수경로 예시NavType
경로(path)"user/{id}"NavType.IntType
쿼리(query)"search?q={query}"NavType.StringType
선택적"details/{id}?tab={tab}"StringType + defaultValue=""
Parcelable"checkout/{order}"NavType.ParcelableType

인수는 arguments?.getInt("id")를 통해 NavBackStackEntry에서 추출됩니다. 필수 인수의 경우 defaultValue를 생략할 수 있습니다. NavType은 null을 사용합니다. 선택적 인수의 경우 defaultValue를 설정해야 하며, 그렇지 않으면 매개변수가 누락된 경우 내비게이션에서 예외가 발생합니다.

Navigation 2.8.0부터 유형 안전 내비게이션이 권장됩니다. Kotlin Serialization을 사용하여 경로에 대한 sealed class 또는 data class를 정의합니다. 문자열 경로 대신 composable<RouteType> { backStackEntry -> }를 사용합니다. 이렇게 하면 경로의 오타가 제거되고 인수에 대한 NavType이 자동으로 생성됩니다. 마이그레이션하려면 navigation-compose-typesafe 종속성과 Kotlin Serialization 플러그인을 추가하세요.

중첩된 내비게이션 그래프

nested graphsnavigation(route, startDestination) 함수를 사용하여 NavHost 내에서 경로를 그룹화하는 메커니즘입니다. 중첩된 그래프에는 자체 경로 접두사와 startDestination이 있으며 모든 경로는 접두사를 통해 액세스할 수 있습니다. 중첩된 그래프는 각 기능 모듈이 자체 하위 그래프를 등록하는 모듈식 아키텍처에 사용됩니다.

중첩된 그래프의 이점: 모듈 내 경로 격리, 화면 그룹에 대한 통합 백 스택, 내부 구조를 노출하지 않고 접두사로 탐색할 수 있는 기능. 예를 들어 "auth" 그래프에는 "auth/login" 및 "auth/register"가 포함됩니다. 전체 경로를 통해 또는 startDestination으로 리디렉션되는 접두사를 통해 탐색할 수 있습니다.

kotlin
NavHost(navController = navController, startDestination = "main") {
    composable("main") { MainScreen(navController) }
    navigation(
        route = "auth",
        startDestination = "auth/login"
    ) {
        composable("auth/login") { LoginScreen(navController) }
        composable("auth/register") { RegisterScreen(navController) }
    }
}

중첩된 그래프는 그래프 수준에서 인수 전달을 지원합니다. 그래프 경로에 선언된 매개변수는 모든 내부 경로로 전달됩니다. 중첩된 그래프를 지우려면 popBackStack(route)를 사용하면 모든 내부 항목이 제거됩니다. 중첩된 그래프에는 깊이 제한이 없지만 가독성을 위해 3단계를 초과하지 않는 것이 좋습니다.

애니메이션 및 전환 사용자 지정

NavHost는 enterTransition, exitTransition, popEnterTransitionpopExitTransition 매개변수를 통해 composable 경로 간 전환 애니메이션을 지원합니다. 애니메이션은 NavHost에 대해 한 번 설정되며 모든 경로에 적용되거나 각 composable에 개별적으로 적용됩니다. 기본적으로 애니메이션은 비활성화됩니다.

일반적인 구성: enterTransition = slideInHorizontally(initialOffsetX = { it }) — 화면이 오른쪽에서 슬라이드 들어옵니다; exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — 화면이 왼쪽으로 슬라이드 나갑니다. 팝 애니메이션의 경우 방향이 반전됩니다: 화면이 왼쪽에서 슬라이드 들어오고 오른쪽으로 슬라이드 나갑니다. BottomNavigation의 경우 슬라이드 없이 fadeIn/fadeOut이 사용됩니다.

kotlin
NavHost(
    navController = navController,
    startDestination = "home",
    enterTransition = { slideInHorizontally(initialOffsetX = { it }) + fadeIn() },
    exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) + fadeOut() },
    popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) + fadeIn() },
    popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) + fadeOut() }
) { /* composable routes */ }

사용자 지정 애니메이션은 Compose Animation API를 사용하여 생성됩니다. AnimatedContentTransitionScope는 컨테이너 치수, 애니메이션 진행률 및 방향에 대한 액세스를 제공합니다. 공유 요소 전환(한 요소가 다른 화면으로 부드럽게 이동)의 경우 Accompanist Navigation Animation 라이브러리 또는 sharedElement Modifier를 통한 사용자 지정 구현이 필요합니다. Android Developers(2025)에 따르면 기본 슬라이드 애니메이션(오른쪽에서 들어와 왼쪽으로 나감)은 내비게이션이 있는 Android 앱의 80%에서 사용됩니다.

자주 묻는 질문

하나의 Activity에서 여러 NavHost를 사용할 수 있나요?

기술적으로는 가능하지만 권장되지 않습니다. 각 NavHost는 독립적인 백 스택을 생성하여 통합된 내비게이션을 깨뜨립니다. 예외는 기본 콘텐츠용 NavHost와 자체 내비게이션이 있는 BottomSheet용 NavHost와 같이 분리된 영역입니다.

Compose에서 NavHost와 Scaffold의 차이점은 무엇인가요?

NavHost는 화면을 전환하는 내비게이션 컨테이너입니다. Scaffold는 전체 페이지의 레이아웃입니다(TopAppBar, BottomNavigation, FloatingActionButton). 일반적으로 NavHost는 Scaffold.content 내부에 배치됩니다. Scaffold는 내비게이션을 관리하지 않으며 UI 구성 요소에 대한 슬롯만 제공합니다.

NavHost를 통해 화면 간에 ViewModel을 공유하려면 어떻게 해야 하나요?

ViewModel은 NavBackStackEntry 내에서 viewModel()을 통해 생성됩니다. 화면 간에 ViewModel을 공유하려면 parentNavController를 사용하여 공유 ViewModel을 상위 항목에 바인딩합니다. 대안은 NavGraph 범위가 있는 DI(Hilt/Koin)입니다.

NavHost가 내비게이션할 때마다 composable을 다시 생성하는 이유는 무엇인가요?

이것은 정상적인 동작입니다. 경로를 떠날 때 NavHost가 composable을 컴포지션에서 제거합니다. 상태를 보존하려면 UI 상태에는 rememberSaveable을, 비즈니스 로직에는 SavedStateHandle이 있는 ViewModel을 사용하세요.

NavHost에서 404(알 수 없는 경로) 처리를 추가하려면 어떻게 해야 하나요?

마지막 경로 composable("404")를 추가하고 알 수 없는 딥 링크를 수신하면 해당 경로로 이동합니다. NavHost에는 catch-all 경로가 없습니다. navigate() 전에 딥 링크 인텐트 핸들러에서 경로를 확인하세요. 경로를 찾을 수 없으면 404로 이동합니다.

요약

  • NavHost — NavController를 경로 그래프에 연결하고 현재 화면을 렌더링하는 Navigation Compose composable 컨테이너
  • composable()은 경로, 인수(NavType), 딥 링크 및 애니메이션으로 경로를 등록합니다
  • startDestination — NavHost가 처음 시작될 때 열리는 초기 경로
  • 인수는 유형화를 위한 NavType 및 선택적 매개변수를 위한 defaultValue와 함께 {param} 자리 표시자를 통해 전달됩니다
  • 중첩된 그래프는 navigation()을 통해 격리된 백 스택으로 모듈별로 경로를 그룹화할 수 있습니다
  • 전환 애니메이션은 Compose Animation API를 사용하여 enterTransition/exitTransition을 통해 구성됩니다
  • NavHost는 추가 코드 없이 뒤로 가기, 상태 저장 및 딥 링크를 자동으로 처리합니다

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기