탐색은 사용자가 앱 내에서 이동하는 방식을 나타냅니다. 사용자는 일반적으로 탭하거나 클릭하여 UI 요소와 상호작용하며 앱은 새 콘텐츠를 표시하여 응답합니다. 사용자가 이전 콘텐츠로 돌아가려는 경우에는 뒤로 동작을 사용하거나 뒤로 버튼을 탭합니다.
탐색 상태 모델링
이 동작을 모델링하는 편리한 방법은 콘텐츠 스택을 사용하는 것입니다. 사용자가 새 콘텐츠로 앞으로 이동하면 스택 상단에 푸시됩니다. 해당 콘텐츠에서 뒤로 이동하면 스택에서 팝되고 이전 콘텐츠가 표시됩니다. 탐색 용어로 이 스택은 사용자가 돌아갈 수 있는 콘텐츠를 나타내므로 일반적으로 뒤로 스택이라고 합니다.
그림 1. 사용자 탐색 이벤트에 따라 백 스택이 어떻게 변경되는지 보여주는 다이어그램
뒤로 스택 만들기
탐색 3에서 백 스택에는 실제로 콘텐츠가 포함되지 않습니다. 대신 키라고 하는 콘텐츠 참조가 포함됩니다. 키는 모든 유형이 될 수 있지만 일반적으로 간단한 직렬화 가능한 데이터 클래스입니다. 콘텐츠 대신 참조를 사용하면 다음과 같은 이점이 있습니다.
키를 백 스택으로 푸시하여 간단하게 탐색할 수 있습니다.
키가 직렬화 가능하면 백 스택을 영구 저장소에 저장하여 구성 변경과 프로세스 종료를 견딜 수 있습니다. 사용자는 앱을 나갔다가 나중에 다시 돌아와서 중단한 지점부터 동일한 콘텐츠가 표시되기를 기대하므로 이 점이 중요합니다. 자세한 내용은 뒤로 스택 저장을 참고하세요.
Navigation 3 API의 핵심 개념은 개발자가 백 스택을 소유한다는 것입니다. 라이브러리는 다음을 충족해야 합니다.
백 스택이 스냅샷 상태 지원 List<T>일 것으로 예상합니다. 여기서 T은 백 스택 keys의 유형입니다. Any을 사용하거나 더 강력한 유형의 키를 직접 제공할 수 있습니다. '푸시' 또는 '팝'이라는 용어가 표시되면 기본 구현은 목록의 끝에서 항목을 추가하거나 삭제하는 것입니다.
다음 예에서는 키와 뒤로 스택을 만들고 사용자 탐색 이벤트에 따라 뒤로 스택을 수정하는 방법을 보여줍니다.
// Define keys that will identify contentdataobjectProductListdataclassProductDetail(valid:String)@ComposablefunMyApp(){// Create a back stack, specifying the key the app should start withvalbackStack=remember{mutableStateListOf<Any>(ProductList)}// Supply your back stack to a NavDisplay so it can reflect changes in the UI// ...more on this below...// Push a key onto the back stack (navigate forward), the navigation library will reflect the change in statebackStack.add(ProductDetail(id="ABC"))// Pop a key off the back stack (navigate back), the navigation library will reflect the change in statebackStack.removeLastOrNull()}
콘텐츠는 컴포저블 함수가 포함된 클래스인 NavEntry을 사용하여 Navigation 3에서 모델링됩니다. 대상을 나타냅니다. 사용자가 앞으로 이동하고 뒤로 이동할 수 있는 단일 콘텐츠입니다.
NavEntry에는 콘텐츠에 관한 정보인 메타데이터도 포함될 수 있습니다. 이 메타데이터는 NavDisplay와 같은 컨테이너 객체가 NavEntry의 콘텐츠를 표시하는 방법을 결정하는 데 도움이 되도록 읽을 수 있습니다. 예를 들어 메타데이터를 사용하여 특정 NavEntry의 기본 애니메이션을 재정의할 수 있습니다. NavEntry
metadata는 String 키를 Any 값에 매핑하는 맵으로, 다용도 데이터 저장소를 제공합니다.
key를 NavEntry로 변환하려면 항목 제공자를 만드세요. key를 허용하고 해당 key의 NavEntry을 반환하는 함수입니다. NavDisplay를 만들 때 람다 매개변수로 정의되는 경우가 많습니다.
항목 제공자를 만드는 방법에는 두 가지가 있습니다. 람다 함수를 직접 만들거나 entryProvider DSL을 사용하는 것입니다.
entryProvider DSL을 사용하면 각 키 유형에 대해 테스트하고 각 키 유형에 대해 NavEntry을 구성할 필요가 없으므로 람다 함수를 간소화할 수 있습니다.
이를 위해 entryProvider 빌더 함수를 사용합니다. 키를 찾을 수 없는 경우 오류를 발생시키는 기본 대체 동작도 포함됩니다.
entry는 NavEntry.metadata를 설정하기 위해 metadata 매개변수를 허용합니다.
백 스택 표시
백 스택은 앱의 탐색 상태를 나타냅니다. 백 스택이 변경될 때마다 앱 UI는 새로운 백 스택 상태를 반영해야 합니다. 탐색 3에서 NavDisplay는 백 스택을 관찰하고 그에 따라 UI를 업데이트합니다. 다음 매개변수를 사용하여 생성합니다.
뒤로 스택 - T이 뒤로 스택 키의 유형인 SnapshotStateList<T> 유형이어야 합니다. 변경될 때 NavDisplay의 리컴포지션을 트리거할 수 있도록 관찰 가능한 List입니다.
뒤로 스택의 키를 NavEntry 객체로 변환하는 entryProvider
원하는 경우 onBack 매개변수에 람다를 제공합니다. 사용자가 뒤로 이벤트를 트리거할 때 호출됩니다.
다음 예는 NavDisplay를 만드는 방법을 보여줍니다.
dataobjectHomedataclassProduct(valid:String)@ComposablefunNavExample(){valbackStack=remember{mutableStateListOf<Any>(Home)}NavDisplay(backStack=backStack,onBack={backStack.removeLastOrNull()},entryProvider={key->
when(key){isHome->NavEntry(key){ContentGreen("Welcome to Nav3"){Button(onClick={backStack.add(Product("123"))}){Text("Click to navigate")}}}isProduct->NavEntry(key){ContentBlue("Product ${key.id} ")}else->NavEntry(Unit){Text("Unknown route")}}})}
기본적으로 NavDisplay는 단일 창 레이아웃에서 백 스택의 최상위 NavEntry를 표시합니다. 다음 녹화 영상은 이 앱이 실행되는 모습을 보여줍니다.
그림 2.NavDisplay 기본 동작(대상 2개)
종합적으로 살펴보기
다음 다이어그램은 탐색 3의 다양한 객체 간에 데이터가 흐르는 방식을 보여줍니다.
그림 3. 탐색 3의 다양한 객체를 통해 데이터가 흐르는 방식을 보여주는 다이어그램
탐색 이벤트는 변경을 시작합니다. 사용자 상호작용에 따라 키가 백 스택에 추가되거나 삭제됩니다.
뒤로 스택 상태 변경으로 콘텐츠 가져오기 트리거NavDisplay(백 스택을 렌더링하는 컴포저블)는 백 스택을 관찰합니다. 기본 구성에서는 최상위 백 스택 항목을 단일 창 레이아웃에 표시합니다. 백 스택의 상단 키가 변경되면 NavDisplay는 이 키를 사용하여 항목 제공자로부터 해당 콘텐츠를 요청합니다.
항목 제공자가 콘텐츠를 제공합니다. 항목 제공자는 키를 NavEntry로 확인하는 함수입니다. NavDisplay에서 키를 수신하면 항목 제공자는 키와 콘텐츠를 모두 포함하는 연결된 NavEntry를 제공합니다.
콘텐츠가 표시됩니다. NavDisplay는 NavEntry를 수신하고 콘텐츠를 표시합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-09-10(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-09-10(UTC)"],[],[],null,["# Understand and implement the basics\n\nNavigation describes the way users move around your app. Users interact with UI\nelements, usually by tapping or clicking on them, and the app responds by\ndisplaying new content. If the user wants to go back to the previous content,\nthey use the back gesture or tap the back button.\n\nModeling navigation state\n-------------------------\n\nA convenient way of modeling this behavior is with a stack of content. As the\nuser navigates *forward* to new content, it is pushed on top of the stack. When\nthey go *back* from that content, it is popped off the stack and the previous\ncontent is displayed. In navigation terms, this stack is usually referred to as\nthe **back stack** because it represents the content that the user *can go back\nto*.\n**Figure 1.** Diagram showing how the back stack changes with user navigation events.\n\nCreate a back stack\n-------------------\n\nIn Navigation 3, the back stack does not actually contain content. Instead, it\ncontains *references to content* , known as **keys**. Keys can be any type but\nare usually simple, serializable data classes. Using references rather than\ncontent has the following benefits:\n\n- It is simple to navigate by pushing keys onto the back stack.\n- As long as the keys are serializable, the back stack can be saved to persistent storage, allowing it to survive configuration changes and process death. This is important because users expect to leave your app, come back to it later, and pick up where they left off with the same content being displayed. See [Save your back stack](/guide/navigation/navigation-3/save-state#save-back) for more information.\n\nA key concept in the Navigation 3 API is that you own the back stack. The\nlibrary:\n\n- Expects that your back stack will be a snapshot-state backed `List\u003cT\u003e`, where `T` is the type of your back stack `keys`. You can use `Any` or you can provide your own, more strongly-typed keys. When you see the terms \"push\" or \"pop\", the underlying implementation is to add or remove items from the end of a list.\n- Observes your back stack and reflects its state in the UI using a [`NavDisplay`](/reference/kotlin/androidx/navigation3/ui/package-summary#NavDisplay(kotlin.collections.List,androidx.compose.ui.Modifier,androidx.compose.ui.Alignment,kotlin.Function1,kotlin.collections.List,androidx.navigation3.ui.SceneStrategy,androidx.compose.animation.SizeTransform,kotlin.Function1,kotlin.Function1,kotlin.Function1,kotlin.Function1)).\n\nThe following example shows how to create keys and a back stack, and modify the\nback stack in response to user navigation events:\n\n\n```kotlin\n// Define keys that will identify content\ndata object ProductList\ndata class ProductDetail(val id: String)\n\n@Composable\nfun MyApp() {\n\n // Create a back stack, specifying the key the app should start with\n val backStack = remember { mutableStateListOf\u003cAny\u003e(ProductList) }\n\n // Supply your back stack to a NavDisplay so it can reflect changes in the UI\n // ...more on this below...\n\n // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state\n backStack.add(ProductDetail(id = \"ABC\"))\n\n // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state\n backStack.removeLastOrNull()\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L33-L51\n```\n\n\u003cbr /\u003e\n\nResolve keys to content\n-----------------------\n\nContent is modeled in Navigation 3 using [`NavEntry`](/reference/kotlin/androidx/navigation3/runtime/NavEntry), which is a class\ncontaining a composable function. It represents a *destination* - a single piece\nof content that the user can navigate *forward to* and *back from*.\n\nA `NavEntry` can also contain metadata - information about the content. This\nmetadata can be read by container objects, like `NavDisplay`, to help them\ndecide how to display the `NavEntry`'s content. For example, metadata can be\nused to override the default animations for a specific `NavEntry`. NavEntry\n`metadata` is a map of `String` keys to `Any` values, providing versatile data\nstorage.\n\nTo convert a `key` to a `NavEntry`, create an Entry Provider. This is a\nfunction that accepts a `key` and returns a `NavEntry` for that `key`. It is\nusually defined as a lambda parameter when creating a `NavDisplay`.\n\nThere are two ways to create an Entry Provider, either by creating a lambda\nfunction directly, or by using the [`entryProvider`](/reference/kotlin/androidx/navigation3/runtime/package-summary#entryProvider(kotlin.Function1,kotlin.Function1)) DSL.\n\n### Create an Entry Provider function directly\n\nYou typically create an Entry Provider function using a `when` statement, with\na branch for each of your keys.\n\n\n```kotlin\nentryProvider = { key -\u003e\n when (key) {\n is ProductList -\u003e NavEntry(key) { Text(\"Product List\") }\n is ProductDetail -\u003e NavEntry(\n key,\n metadata = mapOf(\"extraDataKey\" to \"extraDataValue\")\n ) { Text(\"Product ${key.id} \") }\n\n else -\u003e {\n NavEntry(Unit) { Text(text = \"Invalid Key: $it\") }\n }\n }\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L60-L72\n```\n\n\u003cbr /\u003e\n\n### Use the `entryProvider` DSL\n\nThe `entryProvider` DSL can simplify your lambda function by avoiding the need\nto test against each of your key types, and construct a `NavEntry` for each one.\nUse the `entryProvider` builder function for this. It also includes default\nfallback behavior (throwing an error) if the key isn't found.\n\n\n```kotlin\nentryProvider = entryProvider {\n entry\u003cProductList\u003e { Text(\"Product List\") }\n entry\u003cProductDetail\u003e(\n metadata = mapOf(\"extraDataKey\" to \"extraDataValue\")\n ) { key -\u003e Text(\"Product ${key.id} \") }\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L83-L88\n```\n\n\u003cbr /\u003e\n\nNote the following from the snippet:\n\n- `entry` is used to define a `NavEntry` with the given type and composable content\n- `entry` accepts a `metadata` parameter to set `NavEntry.metadata`\n\nDisplay the back stack\n----------------------\n\nThe back stack represents your app's navigation state. Whenever the back stack\nchanges, the app UI should reflect the new back stack state. In Navigation 3, a\n`NavDisplay` observes your back stack and updates its UI accordingly. Construct\nit with following parameters:\n\n- Your back stack - this should be of type `SnapshotStateList\u003cT\u003e`, where `T` is the type of your back stack keys. It is an observable `List` so that it triggers recomposition of `NavDisplay` when it changes.\n- An `entryProvider` to convert the keys in your back stack to `NavEntry`s.\n- Optionally, supply a lambda to the `onBack` parameter. This is called when the user triggers a back event.\n\nThe following example shows how to create a `NavDisplay`.\n\n\n```kotlin\ndata object Home\ndata class Product(val id: String)\n\n@Composable\nfun NavExample() {\n\n val backStack = remember { mutableStateListOf\u003cAny\u003e(Home) }\n\n NavDisplay(\n backStack = backStack,\n onBack = { backStack.removeLastOrNull() },\n entryProvider = { key -\u003e\n when (key) {\n is Home -\u003e NavEntry(key) {\n ContentGreen(\"Welcome to Nav3\") {\n Button(onClick = {\n backStack.add(Product(\"123\"))\n }) {\n Text(\"Click to navigate\")\n }\n }\n }\n\n is Product -\u003e NavEntry(key) {\n ContentBlue(\"Product ${key.id} \")\n }\n\n else -\u003e NavEntry(Unit) { Text(\"Unknown route\") }\n }\n }\n )\n}https://github.com/android/snippets/blob/26d364466ee1c03d658ba2f0905f7cc1a97afefa/compose/snippets/src/main/java/com/example/compose/snippets/navigation3/basic/BasicSnippets.kt#L94-L125\n```\n\n\u003cbr /\u003e\n\nBy default, the `NavDisplay` shows the topmost `NavEntry` on the back stack in a\nsingle pane layout. The following recording shows this app running:\n**Figure 2.** `NavDisplay` default behavior with two destinations.\n\nPutting it all together\n-----------------------\n\nThe following diagram shows how data flows between the various objects in\nNavigation 3:\n**Figure 3.** Diagram showing how data flows through various objects in Navigation 3.\n\n1. **Navigation events initiate changes**. Keys are added or removed from the\n back stack in response to user interactions.\n\n2. **Change in back stack state triggers content retrieval** . The `NavDisplay`\n (a composable that renders a back stack) observes the back stack. In its\n default configuration, it displays the topmost back stack entry in a single\n pane layout. When the top key on the back stack changes, the `NavDisplay` uses\n this key to request the corresponding content from the entry provider.\n\n3. **Entry provider supplies content** . The entry provider is a function that\n resolves a key to a `NavEntry`. Upon receiving a key from the `NavDisplay`,\n the entry provider provides the associated `NavEntry`, which contains both the\n key and the content.\n\n4. **Content is displayed** . The `NavDisplay` receives the `NavEntry` and\n displays the content."]]