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로 받고 있는데 이를 이용해서 화면 이동이 가능하다. 함께 전달하기 원하는 정보가 있다면 두번째 전달인자로 객체 형태 전달이 가능하다.
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 종류들
// 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에서는
tabBarOptions
가 screenOptions
라는 이름으로 변경되었다. 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
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은 실제로 만들고자 하는 것이 있을 때 더 습득하기 좋을 듯... 끝.