Compose) Jetpack Compose Navigation 설정하기

2ast·2025년 3월 11일

Dependency 설치

Compose에서 Navigation을 구성하기 위해서는 가장 먼저 navigation-compose를 설치해주어야 한다. app/build.gradle.kts 경로에 아래 종속성을 넣어준다.

plugins {
    // Kotlin serialization plugin for type safe routes and navigation arguments
    kotlin("plugin.serialization") version "2.0.21"
}

dependencies {
    val nav_version = "2.8.9"

    implementation("androidx.navigation:navigation-compose:$nav_version")
    
     // JSON serialization library, works with the Kotlin serialization plugin.
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
}

위 코드를 보면 슬쩍 serialization관련 종속성도 함께 설치해주고 있는데, 추후 navigation 이동시 screen parameters를 정의해줄 때 필요하기 때문에 미리 설치해주었다.

Navigation을 적용할 Screen 정의

NavGraph에 정의할 스크린을 만들어준다.

// screens/WelcomeScreen.kt

@Composable
fun WelcomeScreen(
    navController: NavController,
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("Welcome to Compose")
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = {
                /*TODO*/
            }
        ) {
            Text("Go to Profile")
        }
    }
}
// screens/ProfileScreen.kt

@Composable
fun ProfileScreen(
    navController: NavController,
    name: String
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("My Name is ${name}")
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = {
                /*TODO*/
            }
        ) {
            Text("Go to Welcome")
        }
    }
}

onClick에 해당하는 부분은 아직 NavHost 작성 전이기 때문에 우선 TODO로 비워두었다.

NavHost 정의하기

NavHost는 navigation을 실제로 관리하는 주체가 되는 객체다. navController와 NavGraph를 비롯한 options를 인자로 받는다. 나는 NavHost를 정의하기 위해 별도로 MainNavigation.kt라는 파일을 만들어 주었다.

@Serializable
object Welcome

@Serializable
data class Profile(val name: String?)


@Composable
fun MainNavigation() {
    val navController = rememberNavController()
    NavHost(
        navController = navController,
        startDestination = Welcome,
        ) {
        
        composable<Welcome> {
          WelcomeScreen(
              navController = navController
          )
        }
        
        composable<Profile> { backStackEntry ->
            val profile: Profile = backStackEntry.toRoute() // screen params
            
            ProfileScreen(
                navController = navController,
                name = profile.name
            )
        }
    }
}

먼저 각 스크린의 타입을@serializable annotation으로 정의해준다. screen params가 있다면 위에 Profile을 정의해준 것처럼 data class로 선언해주어야 한다. 그리고 그렇게 전달받은 params는 backStackEntry.toRoute()로 접근할 수 있다.

참고로 위 코드에서 NavHost의 content 영역에 정의된 코드는 NavGraphBuilder라고 해서 NavGraph를 정의한 부분이다.

composable<Welcome> {
  WelcomeScreen(
    navController = navController
  )
}
        
composable<Profile> { backStackEntry ->
  val profile: Profile = backStackEntry.toRoute() // screen params
            
  ProfileScreen(
    navController = navController,
    name = profile.name
  )
}

NavGraph는 Navigation의 각 스크린들을 정의해놓은 부분으로, 원래는 navController.createGraph를 호출해 NavHost에 넘겨주어야 하는 것을 NavHost의 content로 구조를 넘기면 은닉해서 처리해준다.

//출처: https://developer.android.com/guide/navigation/design?hl=ko#understand-lambda

val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

Navigate

이제 다시 Screen으로 돌아와서 TODO로 남겨두었던 navigate 함수를 정의해보자.

@Composable
fun WelcomeScreen(
    navController: NavController,
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("Welcome to Compose")
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = {
                navController.navigate(route = Profile(name = "Lim")
          )
            }
        ) {
            Text("Go to Profile")
        }
    }
}
@Composable
fun ProfileScreen(
    navController: NavController,
    name: String
) {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("My Name is ${name}")
        Button(
            modifier = Modifier.padding(vertical = 24.dp),
            onClick = {
                navController.navigate(route = Welcome)
            }
        ) {
            Text("Go to Welcome")
        }
    }
}

Transition Animation 커스텀

이렇게해서 Welcome과 Profile로 구성된 compose navigation 구현이 마무리되었다. 하지만 나는 기본적으로 적용된 Fade Transition Animation이 마음에 들지 않았기 때문에 Transition Animation을 제거하기로 했다. animation 설정은 NavHost에 인자를 넘겨 커스텀할 수 있다.

NavHost(
  ...
  enterTransition = {
    EnterTransition.None
  },
  exitTransition = {
    ExitTransition.None
  },
) {
  ...
}

물론 enterTransition, exitTransition을 사용하면 애니메이션을 끄는 것 외에도 fade, slide같이 다양하게 커스텀할 수 있다.

Ref

https://developer.android.com/develop/ui/compose/navigation?hl=ko#kts

profile
React-Native 개발블로그

0개의 댓글