Navigation Component — 개념, NavHost 및 Navigation Graph

저자: IT Sectr 게시일: 2026-02-22 읽는 시간: 7 분

Navigation Component는 앱 화면 간 탐색을 구현하기 위한 Android Jetpack 라이브러리입니다. 이 컴포넌트는 프래그먼트 스택, 딥 링크 및 인수 전달 관리를 중앙화합니다. 2018년부터 Jetpack의 일부였으며 Google은 모든 새 프로젝트에 이를 권장합니다. 자세한 내용은 Google 공식 가이드를 참조하세요.

주요 사항

  • Navigation Component — Android 화면 간 중앙집중식 탐색을 위한 Jetpack 라이브러리
  • NavGraph — 모든 화면과 그 사이의 연결을 설명하는 XML 리소스
  • NavHostFragment — Activity 레이아웃의 컨테이너로 현재 탐색 화면을 표시
  • NavController — 탐색 제어 객체: navigate, popBackStack, navigateUp
  • Safe Args — 화면 간 타입 안전 인수 전달을 위한 Gradle 플러그인

Navigation Component란?

Navigation Component는 탐색을 위한 통합 API를 제공하는 Android Jetpack 라이브러리(androidx.navigation)입니다. 세 가지 핵심 요소로 구성됩니다: Navigation Graph(내비게이션 그래프), NavHostFragment(화면 컨테이너), NavController(전환 컨트롤러). 이 컴포넌트는 백 스택을 자동으로 관리하고 딥 링크를 지원합니다.

Navigation Component 이전에는 개발자가 FragmentManager를 통해 수동으로 프래그먼트를 관리했습니다. 이로 인해 코드가 파편화되었습니다: 각 화면마다 탐색 규칙이 달랐고, 백 스택 상태가 다양했으며, 딥 링크에는 별도의 구현이 필요했습니다. Navigation Component는 이러한 시나리오를 통합했습니다. Google(2026년)에 따르면, 이 라이브러리는 새로운 Android 프로젝트의 90%에 설치되어 있습니다.

Navigation Component는 다른 Jetpack 라이브러리(LiveData, ViewModel, Material Design)와 통합됩니다. XML 프래그먼트와 Jetpack Compose를 모두 navigation-compose 확장을 통해 지원합니다. 안정적인 릴리스 — 2.8.x (2025), 최소 Android 버전 — API 14.

NavGraph는 앱의 모든 화면과 그 사이의 연결을 정의하는 XML 리소스(res/navigation/nav_graph.xml)입니다. 각 화면은 목적지(destination)이며 Fragment, Activity 또는 Composable이 될 수 있습니다. 목적지 간 연결은 전환 방향을 정의하는 작업(action)입니다.

xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    app:startDestination="@+id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name=".HomeFragment"
        android:label="홈"
        tools:layout="@layout/fragment_home">
        <action
            android:id="@+id/action_home_to_detail"
            app:destination="@+id/detailFragment"
            app:enterAnim="@anim/slide_in_right"
            app:exitAnim="@anim/slide_out_left"
            app:popEnterAnim="@anim/slide_in_left"
            app:popExitAnim="@anim/slide_out_right" />
    </fragment>

    <fragment
        android:id="@+id/detailFragment"
        android:name=".DetailFragment"
        android:label="세부정보"
        tools:layout="@layout/fragment_detail">
        <argument android:name="itemId"
            app:argType="integer"
            android:defaultValue="0" />
    </fragment>
</navigation>

startDestination 속성은 시작 시 처음 표시되는 화면을 설정합니다. 작업은 대상 목적지와 선택적 애니메이션을 정의합니다. 인수는 화면에 전달되는 매개변수(타입 및 기본값)를 설명합니다.

NavHostFragment는 Activity 레이아웃에 배치되는 컨테이너로 현재 탐색 화면을 표시합니다. NavController.navigate()가 호출되면 NavHostFragment가 자동으로 프래그먼트를 전환합니다. NavController는 탐색을 관리하는 객체입니다: 전환, 뒤로 가기, 현재 경로 확인.

kotlin
// Layout Activity: activity_main.xml
// <androidx.fragment.app.FragmentContainerView
//     android:id="@+id/nav_host_fragment"
//     android:name="androidx.navigation.fragment.NavHostFragment"
//     app:navGraph="@navigation/nav_graph"
//     app:defaultNavHost="true" />

class MainActivity : AppCompatActivity() {

    private val navController by lazy {
        (findViewById<NavHostFragment>(R.id.nav_host_fragment))
            .navController
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // NavigationUI가 NavController를 AppBar에 연결
        setupActionBarWithNavController(navController)
    }

    // 세부정보 화면으로 이동
    fun openDetail(itemId: Long) {
        val bundle = Bundle().apply {
            putLong("itemId", itemId)
        }
        navController.navigate(R.id.action_home_to_detail, bundle)
    }

    override fun onSupportNavigateUp() = 
        navController.navigateUp() || super.onSupportNavigateUp()
}

app:defaultNavHost="true"는 중요한 속성입니다: 시스템 뒤로 가기 버튼을 가로채서 NavController에 제어를 전달합니다. NavigationUI는 NavController를 AppBar, BottomNavigationView, NavigationDrawer에 연결하는 유틸리티입니다. setupActionBarWithNavController는 중첩된 화면에서 뒤로 가기 화살표를 활성화합니다.

Navigation Component는 작업 내에서 또는 프로그래밍 방식으로 설정되는 사용자 정의 전환 애니메이션을 지원합니다. 애니메이션은 네 가지 속성으로 정의됩니다: enterAnim(새 화면 나타남), exitAnim(현재 화면 사라짐), popEnterAnim(돌아갈 때 나타남), popExitAnim(돌아갈 때 사라짐).

xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%"
        android:duration="300" />
</set>

// 애니메이션이 포함된 프로그래밍 방식 전환
val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_left)
    .setPopEnterAnim(R.anim.slide_in_left)
    .setPopExitAnim(R.anim.slide_out_right)
    .build()

navController.navigate(R.id.detailFragment, args, navOptions)

애니메이션은 FragmentTransaction 수준에서 Fragment와 함께 작동합니다. Jetpack Compose의 경우 NavOptionsCompat을 통해 Compose Animation을 사용하여 애니메이션을 설정합니다. Navigation Component는 애니메이션 유형에 제한을 두지 않습니다 — translate, scale, alpha 및 그 조합이 지원됩니다.

Safe Args: 타입 안전 인수

Safe Args는 화면 간 타입 안전 데이터 전송을 위한 Gradle 플러그인입니다. 플러그인은 NavGraph를 분석하고 특정 필드 타입으로 Directions 및 Args 클래스를 생성합니다. 타입 일치는 컴파일 타임에 확인되며 MissingArgumentException은 앱 실행 전에 감지됩니다.

kotlin
// build.gradle (module)
plugins {
    id 'androidx.navigation.safeargs.kotlin'
}

// Safe Args 생성: DetailFragmentArgs, HomeFragmentDirections
// HomeFragment에서 사용:
val action = HomeFragmentDirections
    .actionHomeToDetail(itemId = 42L)
findNavController().navigate(action)

// DetailFragment에서 사용:
private val args: DetailFragmentArgs by navArgs()
// args.itemId는 Long 타입이며 null을 전달할 수 없습니다

override fun onViewCreated(...) {
    super.onViewCreated(...)
    loadItem(args.itemId)
}

navArgs()는 Fragment 또는 Activity에서 인수를 검색하기 위한 Kotlin 위임자입니다. 플러그인은 프리미티브, 문자열, Parcelable, Serializable, Enum 및 배열을 지원합니다. 복잡한 객체의 경우 ID를 전달하고 ViewModel 또는 데이터베이스에서 로드합니다.

Deep Link는 앱의 특정 화면을 여는 외부 링크입니다. Navigation Component는 NavGraph의 app:deepLink 속성을 통해 딥 링크를 처리합니다. 시스템은 PendingIntent를 생성하여 탐색 스택을 대상 화면까지 복원하거나, 앱이 실행 중이 아닌 경우 새 스택을 생성합니다.

xml

<fragment android:id="@+id/profileFragment"
    android:name=".ProfileFragment">
    <deepLink
        app:uri="https://example.com/profile/{userId}" />
    <argument
        android:name="userId"
        app:argType="string" />
</fragment>

// Deep Link 프로그래밍 방식 생성
val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.profileFragment)
    .setArguments(Bundle().apply {
        putString("userId", "user_123")
    })
    .createPendingIntent()

딥 링크는 경로 및 쿼리 매개변수가 있는 URI 패턴, intent action 및 mime type을 지원합니다. 플레이스홀더({userId})는 자동으로 대상 인수에 매핑됩니다. Navigation Component는 AndroidManifest를 통한 암시적 딥 링크도 처리합니다 — NavHostFragment가 있는 Activity에 intent-filter를 추가하기만 하면 됩니다.

Navigation Compose(androidx.navigation:navigation-compose)는 Jetpack Compose를 위한 Navigation Component 확장입니다. API는 NavController 및 NavHost 개념을 유지하지만 화면은 Fragment 대신 Composable 함수입니다. NavHost는 각 경로에 대해 composable 람다를 허용합니다.

kotlin
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {
                val navController = rememberNavController()
                NavHost(
                    navController = navController,
                    startDestination = "home"
                ) {
                    composable("home") {
                        HomeScreen(
                            onItemClick = { id ->
                                navController.navigate("detail/$id")
                            }
                        )
                    }
                    composable(
                        route = "detail/{itemId}",
                        arguments = listOf(
                            navArgument("itemId") {
                                type = NavType.LongType
                            }
                        )
                    ) { backStackEntry ->
                        val itemId = backStackEntry
                            .arguments?.getLong("itemId") ?: 0L
                        DetailScreen(itemId = itemId)
                    }
                }
            }
        }
    }
}

Navigation Compose는 ID 대신 문자열 경로를 사용합니다. 매개변수는 경로 템플릿("detail/{itemId}")을 통해 전달되고 backStackEntry에서 추출됩니다. rememberNavController()는 재구성 간에 NavController를 유지합니다. Compose에서 타입 안전성을 위해 navigation-compose-type-safety 모듈(실험적)이 권장됩니다.

자주 묻는 질문

Navigation Component에서 NavHost란?

NavHost는 탐색 화면을 표시하기 위한 컨테이너입니다. XML 레이아웃에서 NavHostFragment를 통해 구현됩니다. NavHost는 NavGraph에서 현재 화면을 추적하고 전환을 관리합니다. 각 Activity에는 하나의 NavHostFragment가 포함됩니다.

Safe Args가 Bundle보다 나은 점은?

Safe Args는 타입 안전 인수 클래스를 생성하는 Gradle 플러그인입니다. Bundle은 키와 타입을 수동으로 지정해야 하므로 런타임 오류가 발생합니다. Safe Args는 컴파일 타임에 타입을 확인하고 데이터를 자동으로 직렬화합니다.

Navigation Component를 통해 복잡한 객체를 전달하는 방법은?

복잡한 객체는 ViewModel(화면 간 공유)을 통해 또는 ID를 전달하여 데이터베이스를 통해 전달됩니다. Safe Args는 프리미티브, 문자열 및 Parcelable만 지원합니다. Google은 탐색 인수를 통해 큰 객체를 전달하지 않도록 권장합니다.

Navigation Component에서 Deep Link는 어떻게 작동하나요?

Deep Link는 NavGraph에서 app:deepLink 속성을 통해 구성됩니다. Navigation Component는 들어오는 링크를 자동으로 처리하고, NavDeepLinkBuilder를 통해 PendingIntent를 생성하며, 탐색 스택을 대상 화면까지 복원합니다. URI, intent action 및 mime type을 지원합니다.

Navigation Component를 Jetpack Compose와 함께 사용할 수 있나요?

네. Navigation Compose(androidx.navigation:navigation-compose)는 Compose용 NavHost를 제공합니다. API는 XML 버전과 유사하지만 화면은 Composable 함수입니다. NavController는 두 버전에서 동일하게 사용됩니다. Google은 새로운 Compose 프로젝트에 Navigation Compose를 권장합니다.

요약

  • Navigation Component — NavController, NavHost 및 NavGraph를 통한 중앙집중식 탐색을 위한 Android Jetpack 라이브러리
  • NavGraph — 모든 화면(목적지)과 그 사이의 연결(작업)을 설명하는 XML 그래프
  • NavHostFragment — Activity 레이아웃의 컨테이너로 뒤로 가기 버튼용 defaultNavHost 속성 지원
  • Safe Args — 컴파일 타임 타입 검사로 타입 안전 인수 전달을 위한 Gradle 플러그인
  • 딥 링크 — URI, intent action 및 mime type 지원, 자동 탐색 스택 복원
  • Navigation Compose — 문자열 경로 및 composable 화면을 갖춘 Jetpack Compose 확장
  • Navigation Component는 새로운 Android 프로젝트에서 Google이 권장하는 유일한 탐색 방식입니다

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

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

프로젝트 논의

더 읽어보기