TIL - React Navigation(update ver.)

김수지·2021년 12월 13일
0

TILs

목록 보기
36/39
post-thumbnail
post-custom-banner

Today What I Learned

매일 배운 것을 이해한만큼 정리해봅니다.


작년에 React Native(RN)으로 모바일 어플리케이션 개발을 해본 적이 있는데 그 때 한 번 다뤘던 React Navigation(ver 4.x)이라는 주제를 다시 한 번 다뤄보려고 한다. 예전에 작성했던 repo와 비교해보니 대부분 패키지가 react native community 쪽으로 옮겨 가서 관리되는 것도 있는 것 같고 해서 이번에는 리액트 네이티브를 다루는 기술 책을 읽고서 정리한 내용이다(책의 내용은 ver 5.x 정도의 내용인 것 같다).

1. RN에서 사용할 수 있는 내비게이션 방법

  • React Navigation
    • 리액트 네이티브 커뮤니티에서 관리
    • 가장 많이 사용하는 라이브러리이고, 리액트 공식 매뉴얼에서도 이 라이브러리를 이용한 화면 전환 방법을 소개함
    • 내비게이션 기능이 자바스크립트로 구현되어 있음
    • 패키지: @react-navigation/native
    • 의존성을 가지는 패키지: react-native-screens, react-native-safe-area-context
  • React Native Navigation
    • 홈페이지 제작 서비스 Wix에서 관리
    • 이미 만들어진 네이티브 앱에 RN을 적용할 때 적합
    • 내비게이션 기능이 각 플랫폼의 네이티브 코드로 구현되어 있음 -> 더 native 답다!
  • 아래 내용에서는 React Navigation을 다루겠다.

2. React Navigation

  • React Navagiation에서 화면을 전환하는 구조는 Stack을 기반한다. 웹에서 History와 비슷하다고 생각하면 되고 Native Stack Navigator를 가장 흔하게 사용한다. push/pop 등으로 관리하고, navigate이라는 메소드를 이용해서 최초 페이지로 이동하거나 연이은 push/pop 없이도 원하는 화면 전환이 가능하다(location replace와 비슷한 느낌).
  • 이동한 화면마다 헤더가 노출되는데 options를 통해서 노출 유무를 정할 수 있다.
  • 기본 사용 방법: App.js 에서 화면 전환이 적용될 수 있도록 NavigationContainer를 감싼다. Container 내부에서 사용하고자 하는 Navigator에서 create 관련 함수를 import하여 스택 구조를 만들고 해당 Navigator와 Screen으로 컴포넌트를 렌더한다.
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigation } from "@react-navigation/native-stack";
 // ... 스크린에 담을 컴포넌트 불러온 뒤
const App = () => {
  const Stack = createNativeStackNavigation();
  
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="My" component={MyPageScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
  • 이렇게 렌더된 컴포넌트는 navigation을 props로 받고 있는데 이를 이용해서 화면 이동이 가능하다. 함께 전달하기 원하는 정보가 있다면 두번째 전달인자로 객체 형태 전달이 가능하다.
// HomeScreen.js
import React from "react";
import { View, Button } from "react-native";

const HomeScreen = ({ navigation, router }) => {
  return (
    <View>
      <Button title="MyPage로 이동" onPress={() => navigation.navigate("My", {id: 1})} />
    </View>
  );
}
  • navigation을 이용해서 이동한 화면에서는 route를 props로 받아서 route.params를 이용해 이동 전에 전달했던 정보를 활용할 수 있다. (ex: 위의 예에서는 route.params.id가 1)

3. Navigator 종류들

  • 위에서 다룬 Native Stack 외에도 몇가지 Navigator가 있다. 각 네비게이터를 create함수로 생성한 후 해당 네비게이터의 Navigator와 Screen을 사용해 배치하여 사용하는 구조는 대부분 비슷하다.

    1. Drawer Navigator

    • 좌측 혹은 우측에 햄버거 버튼을 누르면 등장하는 네비게이터 구조이다.
    • 패키지: @react-navigation/drawer
    • 의존성 패키지: react-native-gesture-handler(드로어에서 사용자 제스처를 인식하기 위한 라이브러리), react-native-reanimated(RN에 내장된 애니메이션 효과보다 개선된 성능으로 애니메이션 효과를 구현하는 라이브러리)
    • 드로어 네비게이터에서 사용하는 props
      • initialRouteName: 가장 처음 보여질, 기본 화면
      • drawerPosition: "left", "right"
      • backBehavior: 뒤로가기 시 설정
        • order: 스크린 컴포넌트를 사용한 순서에 따라 현재 화면의 이전 화면으로 이동
        • history: 화면을 열기 직전에 봤던 화면으로 이동
        • none: 뒤로가기를 수행하지 않음
    • 드로어 스크린에서 사용하는 Screen options Props
      • drawerActiveTintColor
      • drawerActiveBackgroundColor
      • drawerInactiveTintColor
      • drawerInactiveBackgroundColor
      • drawerItemStyle
      • drawerLabelStyle
      • drawerContentContainerStyle
      • drawerStyle
    • IOS의 경우에는 드로어가 StatusBar 영역과 겹칠 수 있으므로 SafeAreaView를 꼭 감싸줘야 한다.

    2. Bottom Tab Navigator

    • 화면과 고정 구조로 노출되는 하단 탭 구조
    • 패키지: @react-navigation/bottom-tabs
    • 추가로 필요한 패키지: react-native-vector-icons(각 탭에 노출될 이미지 관리), 아이콘 사용을 위해서 ios 폴더 내 Info.plist 최하단과 android 폴더 내 build.gradle에 코드를 추가해야 한다.
  // Info.plist
    <key>UIViewControllerBasedStatusBarAppearance</key>
      <flase/>
      <key>UIAppFonts</key>
      <array>
        <string>MaterialIcons.ttf</string>
      </array>
        
  // build.gradle
    project.ext.vectoricons= [
      iconFontNames: ["MaterialIcons.ttf"]
    ]
    
    apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
  • 탭 관련 Options
    • tabBarActiveTintColor
    • tabBarActiveBackgroundColor
    • tabBarInactiveTintColor
    • tabBarInactiveBackgroundColor
    • tabBarShowLabel: 항목에서 텍스트의 가시성 설정(default: true)
    • tabBarShowIcon: 항목에서 아이콘의 가시성 설정(default: false)
    • tabBarStyle
    • tabBarLabelStyle
    • tabBarItemStyle
    • tabBarLabelPosition: 텍스트 위치 "beside-icon"(아이콘 우측), "below-icon"(아이콘 하단)
    • tabBarAllowFontScaling: 시스템 폰트 크기에 따라 폰트 크기를 키울지 결정(default: true)
    • tabBarSafeAreaInset: SafeAreaView의 forceInset을 덮어쓰는 객체(default: {bottom: "always", top:"never"})
    • tabBarKeyboardHIdesTabBar: 키보드가 나타날 때 하단 탭을 가릴지 결정(default: false)
  • 참고) React Navigation v6에서는 tabBarOptionsscreenOptions라는 이름으로 변경되었다.

    3. Material Tab Navigator

    • Material Tab Navigator은 위에서 다룬 하단 탭 네비게이터과 유사하나 안드로이드 5.0 이상에서 ripple 효과를 줄 수 있고 스와이프 형태로 우측/좌측 탭 전환이 가능하다. (예전에 모바일 어플리케이션 만들 때는 그냥 react-native에서 Tab을 불러와 화면 내 상단 탭을 구현했었는데 그 방법보다 더 수월하게 처리가 가능해보인다.)
    • 상단 탭
      • 구현을 위해 필요한 패키지: @react-navigation/material-top-tabs react-native-tab-view(RN에서 탭 구현을 위한 라이브러리) react-native-pager-view
      • Navigator 주요 props
        • initialRouteName
        • scrrenOptions
          • swipeEnabled: 화면을 좌우로 스와이프하여 전환할 수 있게 함(default: true)
          • lazy: 특정 탭으로 이동해야만 해당 탭을 렌더링((default: true)
          • lazyPreloadDistance: lazy 속성이 활성화된 상태에서 몇 칸 뒤 화면을 미리 불러올지 설정(default:0)
          • lazyPlaceholder: lazy 속성이 활성화된 상태에서 아직 보이지 않는 화면에서 보여줄 대체 컴포넌트
          • tabBarIndicator: 활성화된 탭을 표시하는 컴포넌트
          • tabBarIndicatorStyle: 활성화된 탭을 표시하는 컴포넌트의 스타일
          • backBehavior
          • tabBarPosition: top, bottom
          • keyboardDismissMode: 키도르를 숨길 것인지 설정 (auto: 화면이 바뀔 때 숨김, on-drag 화면을 드래그할 때 숨김, none: 안 숨김)
          • sceneContianerStyle
          • style
          • tabBar: 탭 바를 대체할 수 있는 컴포넌트
      • Screen props
        • tabBarIcon: 아이콘을 보여주는 함수, { focused: boolean, color: string } 타입의 파라미터를 받음
        • tabBarLabel
    • 하단 탭
      • 구현을 위해 필요한 패키지: @react-navigation/material-bottom-tabs react-native-pager(RN에서 material 디자인을 사용하게 하는 라이브러리)
      • Navigator 주요 Props
        • initialRouteName
        • screenOptions
        • backBehavior
        • shifting: 탭의 개수가 3개 이상인 경우 default로true, true인 경우에는 탭이 변경될 때마다 배경색을 변경하고 활성화된 탭만 탭의 이름을 보여줌. false인 경우에는 탭마다 배경색을 따로 따로 지정할 수 없어서 모든 탭에 이름이 보임.
        • labeld: 탭 아이콘 하단에 이름을 나타낼지 정하는 값(default: true)
        • activeColor
        • inactiveColor
        • barStyle
      • Screen 주요 Props
        • tabBarIcon
        • tabBarLabel
        • tabBarBadge: 탭 아이콘에 뱃지, true인 경우 아이콘 우측 상단에 빨간색 점 노출. 문자나 숫자를 입력하면 빨간 뱃지 안에 해당 데이터가 노출

3. Navigation Hooks

  • stack 구조에서 쌓여 있으나 화면에 노출되지 않는 컴포넌트에서의 navigation이나 route 처리가 필요할 때가 있다.
  • 앞서 다룬 것처럼 컴포넌트마다 props에서 navigation이나 route를 꺼내서 처리할 수도 있으나 hook 형태를 사용할 수도 있다.

    1. useNavigation

    • 현재 화면으로 사용하고 있지 않은 컴포넌트에서도 navigation 객체 사용 가능
    • const navigation = useNavigation(); 형태로 컴포넌트 내에서 사용한다.

    2. useRoute

    • useNavigation과 같은 식으로 컴포넌트 내에서 사용한다. 리액트에서 많이 써서 별로 어려워 보이지 않을 것이다.
    • const router = useRouter(); 형태

    3. useFocusEffect

    • 화면에 포커스가 잡혔을 때 특정 작업을 할 수 있게 하는 hook
// HomeScreen.js
import React, { useCallback } from "react";
import { useFocusEffect } from "@react-navitation/native";
// ...
const HomeScreen = () => {
  useFocusEffect(
    useCallback(() => {
      console.log("screen mouted");
      // 포커스가 잡혔을 때 처리 추가
      return () => {
        console.log("screen unmounted");
        // 포커스가 벗어날 때 처리 추가
      };
    }, []);
}
// ... 컴포넌트 렌더

오랜만에 보니까 새롭긴 한데 크게 달라진 건 없는 것 같다. 이번에는 책을 읽고 주요 내용을 정리해봤는데 이번 여름에 v6가 나와서 가장 업데이트 된 내용은 공식 문서를 보는게 제일 좋을 것 같다.
ReactNavigation은 실제로 만들고자 하는 것이 있을 때 더 습득하기 좋을 듯... 끝.

profile
선한 변화와 사회적 가치를 만들고 싶은 체인지 메이커+개발자입니다.
post-custom-banner

0개의 댓글