본문 바로가기
안드로이드/코틀린

AAC Navigation의 특징

by 나이아카 2023. 6. 2.

 오늘은 안드로이드의 Navigation에 대한 내용입니다. 머테리얼 디자인의 바텀 내비게이션과 같은 그런 것을 이야기하는 것은 아닙니다. 안드로이드 Jetpack 라이브러리에 동봉되어 있는 프래그먼트의 흐름의 가시성을 높여준다고 하는 navigation 그래프에 관한 내용입니다.


 AAC Navigtaion이란?

 제가 설명할 내비게이션은 Jetpack 라이브러리 내에 속해있는 요소입니다. 기존 프래그먼트의 경우, FragmentManager를 통해(childFragmentManager든, parentFragmentManager든) 프래그먼트를 add 하거나 replace하는 등의 효과를 통해 프래그먼트를 변경해주는 작업을 진행했습니다. 이는 딱히 큰 문제가 되지는 않았지만 각 프래그먼트의 다음 프래그먼트가 무엇인지, 그리고 각 프래그먼트들의 흐름을 한 눈에 파악하기가 어려웠습니다. 더욱이 라우터와 같은 형태의 패턴을 사용하게 되면 프래그먼트의 변경점과 이동내역을 파악하는 것은 더더욱 쉽지 않은 일이었습니다.

 그래서 Jetpack에서는 버튼의 상호작용에 의한 화면의 이동부터 뒤로가기 등(또는 앱바와 같은 추가적인 기능)의 작업까지 모두 navigation 패키지 내의 그래프에서 처리 가능하도록 기능을 추가했습니다. 하나의 플로우는 하나의 그래프로 관리되며 이 그래프는 NavHost가 가지게 되며, 이를 NavController를 통해 관리할 수 있습니다. 이 그래프는 iOS의 스토리보드와 유사한 역할을 하고 있습니다.

 

사용법

 가장 중요한 점은 Android Studio 3.3 이상 버전과 Java 8.0 이상 버전에서 navigation이 지원됩니다.

 모든 라이브러리가 기본적으로 해줘야 하는 세팅인, 앱의 build.gradle 파일에 아래와 같은 코드를 삽입합니다. 아래 코드는 공식문서에서 가져온 코드이며, 기본적으로 navigation-fragment와 navigation-ui가 있으면 최소한의 준비는 완료됩니다.(언어에 따라 -ktx 여부를 파악해야 합니다.) 이때 Compose 라이브러리를 사용한다면, navigation-compose를 설치하셔야 합니다. 또한, 테스트 및 추가 기능에 대한 라이브러리는 자신이 내비게이션을 사용할 때 요구하는 기능들이 들어있는 경우 설치해서 확인할 수 있습니다.

dependencies {
  val nav_version = "2.5.3"

  // Java language implementation
  implementation("androidx.navigation:navigation-fragment:$nav_version")
  implementation("androidx.navigation:navigation-ui:$nav_version")

  // Kotlin
  implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
  implementation("androidx.navigation:navigation-ui-ktx:$nav_version")

  // Feature module Support
  implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")

  // Testing Navigation
  androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")

  // Jetpack Compose Integration
  implementation("androidx.navigation:navigation-compose:$nav_version")
}

 navigation 라이브러리 설치가 완료 되었다면 res 폴더 아래에 navigation 폴더를 생성한 후(이미 생성되어 있는 경우 생략합니다.), navigation 폴더 우측버튼 클릭 후 New -> navigation resource file을 클릭합니다. 이름을 설정하면 그래프를 하나 생성하게 됩니다.

 또한, safeArgs 기능을 사용하기 위해서는 프로젝트의 build.gradle에 아래와 같은 코드를 삽입해야 합니다. 아래 코드 역시 공식문서에서 제공하고 있습니다.

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.5.3"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}

 모든 준비가 끝나고 나면, 내비게이션 이미지 중, 왼쪽 상단의 + 버튼을 클릭해서 Fragment를 추가할 수 있습니다.(물론 XML에서 직접 fragment 코드를 작성하셔도 추가 가능합니다.)

 

특징

  • 가시성있는 프래그먼트 처리
    • 프래그먼트 및 다이얼로그를 위의 이미지와 같이 가시성 있게 볼 수 있도록 도와줍니다.
    • 각 프래그먼트의 다음 이동이 어떤 방향으로 이동하는지에 대해서 알려줍니다.
    • 한 프래그먼트에서 너무 다양한 화면으로 이동하는 경우, 복잡도가 올라가 가시성이 떨어질 수 있습니다.
  • SafeArgs로 안전한 데이터 이동
    • 기존 bundle의 경우, key 값을 통해 value를 전달하지만 value 값의 type 및 값의 유무를 보장할 수 없지만, Args의 경우 navigation 내부에서 type 및 nullable 여부를 컴파일 타임에 미리 파악해서 에러를 줄여줍니다.
  • 전환 애니메이션 적용 간편화
    • enterAnim: A -> B로 Action할 때 들어오는 UI 대상의 Animation(B의 Animation)
    • exitAnim: A -> B로 Action할 때 나가는 UI 대상의 Animation(A의 Animation)
    • popEnterAnim: B -> A로 Pop할 때 들어오는 UI 대상의 Animation(A의 Animation)
    • popExitAnim: B -> A로 Pop할 때 나가는 UI 대상의 Animation(B의 Animation)
    • 위 네 개를 이용하면 기존 fragmentManager를 사용하여 애니메이션을 지정하는 것 보다 더 간편하게 애니메이션을 설정할 수 있습니다.
  •  딥링크로 인한 화면 처리
    • 프래그먼트 화면으로의 전환을 딥링크로서 처리가 가능합니다.
  • 모든 화면 처리는 replace 방식
    • 프래그먼트의 전환에는 크게 add 방식과 replace 방식이 존재하는데 navigation의 전환을 사용하는 경우 프래그먼트 위에 프래그먼트를 얹는 개념인 add를 따로 설정할 수 없으며 기본적으로 replace 방식으로 전환이 이루어집니다.
  • NavigationDirections로 확정된 이동 가능
    • NavigationDirections를 통해 현재 프래그먼트에서 사용가능한 action을 class 형태로 작성해서 SafeArgs처럼 안전하게 사용할 수 있도록 도와줍니다.
    • actionId가 동일하고, graph가 다른 경우에 FragmentA의 Directions를 사용하게 되면 현재 FragmentA가 어떤 그래프 상에 있는지에 따라 그 그래프에 맞는 action을 실행하게 됩니다. 만약 moveToB라는 FragmentA의 actionId가 graphA, graphB에 모두 존재하고 있다면 FragmentA의 코드에서는 항상 moveToB를 호출하게 되면 graphA를 가진 화면이든, graphB를 가진 화면이든 동일하게 이동하게 됩니다. 아래 코드에서 actionId의 중복이 어떤 의미인지 코드로 확인할 수 있습니다.
    • https://github.com/whwogjs96/android_navigation_action_duplication_test
  • Nested Navigation Graph를 통한 내비게이션 모듈화
    • 여러 내비게이션 file을 생성한 후, include를 통해 다른 내비게이션 file의 시작지점으로 전환 가능
    • by navGraphViewModels를 통해 프래그먼트가 속한 내비게이션을 영역으로 한 viewModel 작성 가능

 

결론

 기존에 불편하다고 생각했던 가시성을 대폭 향상시켜 준 부분인 것 같습니다. 하지만 거기다 많은 기능들을 내장해준 덕분에 내비게이션을 제대로 다루기 위해 또 다른 아키텍쳐나 패턴등을 활용해야 할 수 있고 추가적인 이해가 필요합니다. 하지만 이를 잘 활용하면(물론 코드가 더 많은 곳에 분산되긴 하겠지만) 오히려 더 깔끔한 코드를 작성할 수 있을 것 같습니다.

 

참조: https://developer.android.com/guide/navigation/navigation-getting-started?hl=ko


 더 많은, 더 중요한 부분들이 있을지도 모르겠습니다. 공부하는 입장에서 자주 사용하는 부분들을 최대한 키워드로 설명하려고 했는데 제대로 모든 게 설명이 됐는지 모르겠어요. 이번 글의 경우 내비게이션의 예제와 상세 화면들을 보여주면서 처리하려는 것이 목적이 아니었고, 여기서 설명된 키워드를 통해 필요한 부분들을 검색해서 처리해나갈 수 있도록 정리해놓은 부분입니다.

 옛날부터 예제까지 만들어놨던 코드들도 시간이 지나면서 자연스럽게 잊혀지게 되더라구요. 아무래도 똑똑하지 못해서 많은 것들을 저장하지 못하게 된 탓이겠지만, 그로 인해 습관적으로 키워드들을 정리해두는 습관이 생긴 것 같습니다. 마치 주소값만 저장해두는 인스턴스 같은 느낌이네요.

'안드로이드 > 코틀린' 카테고리의 다른 글

Android - 시스템 앱 알림 상태 확인  (0) 2023.10.25
(Kotlin) Flow - 1  (0) 2023.08.10
JvmStatic 어노테이션  (0) 2023.03.16
Kotlin - Object 키워드(with SingleTon)  (1) 2023.02.17
Coroutine 관련 설명 글 링크  (0) 2022.06.30

댓글