Computer >> 컴퓨터 >  >> 시스템 >> Android

React Native에서 React Navigation 5로 네비게이션 처리하는 방법

React Native에서 네비게이션을 이야기할 때 가장 먼저 떠오르는 라이브러리가 바로 react-navigation입니다.

저는 이 라이브러리의 열렬한 팬으로, React Native 프로젝트에서 네비게이션을 처리할 때 항상 가장 먼저 선택하는 솔루션입니다. 그 이유는 훌륭하고 사용하기 쉬운 API를 제공하면서도 매우 유연하게 커스터마이징할 수 있기 때문입니다.

이 글을 작성하게 된 이유는 react-navigation 버전 5가 드디어 베타 단계를 거쳐 안정화(stable) 버전으로 출시되었기 때문입니다. 새 버전에는 여러 기능 변화가 있었고, 특히 기존과는 전혀 다른 방식으로 라우트를 선언할 수 있는 새로운 API 디자인이 도입되었습니다.

이번 글에서는 새롭게 바뀐 API들을 하나씩 살펴보고, 실제 애플리케이션에서 어떻게 활용할 수 있는지 알아보겠습니다.

원문은 saidhayani.com에 게시되었습니다.

설치하기

react-navigation 5의 설치 방법은 이전 버전(4.x 이하)과 비교해 조금 달라졌습니다.

// 4.x 이전 버전
yarn add react-navigation

react-navigation 5를 설치하는 방법은 다음과 같습니다.

// yarn
yarn add @react-navigation/native
// npm
npm install @react-navigation/native

최신 버전의 react-navigation은 애니메이션과 화면 전환 처리를 위해 react-native-gesture-handler 같은 서드파티 라이브러리들을 많이 활용합니다. 따라서 아래 라이브러리들도 반드시 함께 설치해야 합니다.

// yarn
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
// npm
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

동적 화면(Dynamic Screens)

새로운 API는 라우트 초기화 방식에 동적인 요소를 도입했습니다. 이전에는 설정 파일에 라우트를 정적으로 정의해야 했습니다.

// @flow
import React from "react";

import { createAppContainer, createSwitchNavigator } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";

/** ---------Screens----------- */
import HomeScreen from "../Containers/HomeScreen";
import ProfileScreen from "../Containers/ProfileScreen";
import LoginScreen from "../Containers/LoginScreen";

const StackNavigator = createStackNavigator(
  {
    initialRouteName: "Home"
  },
  {
    Home: {
      screen: HomeScreen
    },
    Login: {
      screen: LoginScreen,
      headerMode: "none",
    },
    Profile: {
      screen: ProfileScreen
    }
);

export default createAppContainer(StackNavigator);

새로운 API는 동적 컴포넌트 방식을 채택하여 네비게이션을 훨씬 더 유연하게 만들어 주었습니다. 라우트를 선언하는 새로운 방식은 아래와 같습니다.

import React from "react"
import { SafeAreaView, StyleSheet, View, Text, StatusBar } from "react-native"

import { NavigationContainer } from "@react-navigation/native"
import { createStackNavigator } from "@react-navigation/stack"

const App: () => React$Node = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView style={styles.containerStyle}>
        <AppNavigation />
      </SafeAreaView>
    </>
  )
}
const Stack = createStackNavigator()
const AppNavigation = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="home">
        <Stack.Screen name="home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  )
}
const HomeScreen = () => {
  return (
    <View style={styles.containerStyle}>
      <Text style={styles.title}>Home Screen</Text>
    </View>
  )
}

이 새로운 방식은 동적이고 사용법이 훨씬 간단하며, 어딘가 익숙한 느낌이라면 그 이유는 react-router의 API와 상당히 유사하기 때문입니다.

동적 옵션(Dynamic Options)

이 기능은 커뮤니티에서 오랫동안 가장 많이 요청했던 부분입니다. 저 역시 기존의 정적(static) 방식 때문에 여러 번 문제를 겪었고, 네비게이션 동작을 동적으로 변경하는 일이 정말 어려웠습니다.

기존 방식 (4.x 이하)

이전 버전의 react-navigation에서는 정적 옵션만 정의할 수 있었고, 이를 동적으로 변경할 방법이 없었습니다.

  static navigationOptions = {
    title: "Sign In",
    header: null,
    mode: "modal",
    headerMode: "none"
  };

새로운 방식 (버전 5)

react-navigation 5는 훨씬 간단한 동적 방식을 제공합니다. 이제 props만으로 어떤 화면에든 옵션을 설정할 수 있습니다.

const AppNavigation = ({}) => {
  let auth = {
    authenticated: true,
    user: {
      email: "user@mail.com",
      username: "John",
    },
  }
  let ProfileScreenTitle = auth.authenticated ? auth.user.username : "Profile"
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen
          name="Profile"
          component={ProfileScreen}
          options={{
            title: ProfileScreenTitle,
            headerTintColor: "#4aa3ba",
            headerStyle: {
              backgroundColor: darkModeOn ? "#000" : "#fff",
            },
          }}
        />
        <Stack.Screen name="About" component={AboutScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  )
}

동적 옵션을 활용하면 인증 상태에 따라 타이틀을 변경할 수 있습니다. 예를 들어 사용자가 로그인된 경우 화면 제목을 해당 사용자의 이름으로 설정하거나, 헤더의 배경색을 자유롭게 바꿀 수 있습니다.

이 기능은 특히 동적 테마를 적용하거나 다크 모드(dark mode)를 구현하려는 경우에 큰 도움이 됩니다.

훅(Hooks)

지금까지 소개한 기능 중에서 개인적으로 가장 마음에 드는 것은 바로 Hooks입니다. 개발 시간을 크게 절약해 주기 때문입니다. 새로운 API는 특정 작업을 수행할 수 있는 커스텀 훅들을 제공합니다.

이전 버전에서는 예를 들어 현재 활성화된 화면의 routeName을 가져오려면 아래와 같은 헬퍼 함수를 직접 만들어야 했습니다.

export function getCurrentRouteName(): string | null {
  const tag = "[getCurrentRouteNameSync] "
  const navState = getStore().getState().nav
  const currentRoute = getActiveRouteState(navState)
  console.log(tag + " currentRoute > ", currentRoute)
  return currentRoute && currentRoute.routeName ? currentRoute.routeName : null
}

Hooks API 덕분에 이런 복잡한 과정 없이도, 단 한 줄의 훅 호출로 Navigation API에 접근할 수 있게 되었습니다.

이제 useRoute 훅을 사용하면 RouteName을 간단히 가져올 수 있습니다.

import { useRoute } from "@react-navigation/native"
const AboutScreen = ({ navigation }) => {
  const route = useRoute()
  return (
    <View
      style={{
        justifyContent: "space-around",
        flex: 1,
        alignItems: "center",
      }}
    >
      {/*    Display the RouteName here */}
      <Text style={styles.title}>{route.name}</Text>
    </View>
  )
}

useNavigationState 훅으로도 동일한 작업이 가능합니다. 이 훅은 네비게이션 상태(navigation state)에 직접 접근할 수 있게 해줍니다.

const navigationState = useNavigationState(state => state)
let index = navigationState.index
let routes = navigationState.routes.length
console.log(index)
console.log(routes)

react-navigation은 이 외에도 다양한 훅을 제공합니다.

  • useFocusEffect: 화면이 로드될 때 포커스된 화면을 반환하는 사이드 이펙트(side effect) 훅
  • useLinking: 딥 링크(deep linking)를 처리하는 훅

두 훅 모두 꼭 확인해서 활용해 보시길 강력히 추천합니다.

마무리

새로운 react-navigation API는 확실히 정적(static)에서 동적(dynamic)으로 패러다임을 전환했습니다. React Native에서 네비게이션을 다루는 방식을 완전히 바꿔놓을 훌륭한 변화입니다. 동적 라우트는 react-navigation 사용자들이 오랫동안 요청해 온 핵심 기능이었으며, 이 새로운 방식을 통해 더 나은 사용자 네비게이션 경험을 만들 수 있을 것입니다.

읽어주셔서 감사합니다.

프로젝트를 위한 React Native 개발자를 찾고 계신가요? 언제든지 연락해 주세요!