TIL - React Navigation

김수지·2020년 3월 5일
1

TILs

목록 보기
28/39

Today What I Learned

Javascript를 배우고 있습니다. 매일 배운 것을 이해한만큼 정리해봅니다.


1달 간 React Native를 이용해서 모바일 어플리케이션을 만들었고, 이 때 어플리케이션 내 이동 구조 설계에 React Navigation을 사용했다. 프로젝트는 마쳤지만 Stack 개념을 사용해서 navigation이 움직인다는 흥미로운 사실을 잊고 싶지 않아 TIL로 정리해본다.

1. Stack navigation

  • React가 react router dom을 이용해서 SPA(single page application)을 구축해놓고 link에 따라 필요한 내용을 page가 바뀌는 것처럼 웹 상에서 보여주는 것처럼 React native에서는 page 대신 screen라는 개념이 존재한다. 말 그대로 사용자가 마주하는 하나 하나의 화면이고, 이 또한 react navigation의 도움을 받아서 이리 저리 이동이 가능하다.
  • stack navigation을 사용하면 screen 이동 시 screen 하나씩을 stack에 넣고 빼는 구조로 구현할 수 있다.
  • Stack 자료 구조는 하나의 컨테이너에 노드를 순서대로 넣고 노드를 제거할 때는 가장 마지막에 들어간 노드를 꺼내는 후입선출구조이다.
  • 이 자료 구조를 유념하면서 네비게이션 구조를 구현한다면 이렇게 구현이 가능하다.
    • 스택마다 넣고 뺄 수 있는 스크린이 정의된다.
    • 최초 스크린이 가장 먼저 스택에 쌓이고 사용자 화면에 보인다.
    • 다음 화면으로 이동한다면 화면 상으로는 이전 화면이 사라지고 새로운 화면이 보이지만, 구조적으로는 컨테이너에 최초 스크린이 push 되고 다음 화면이 push 되어서 컨테이너에 2개의 노드가 쌓인 격이다.
    • 사용자가 이전 화면으로 돌아가는 행동을 취한다면 컨테이너에서 마지막 화면이 pop 되면서 남아있는 최초 스크린이 화면에 보이는 식으로 '돌아가기'를 완성한다.
  • 실제로 프로젝트에서 구현했던 스택 중 하나를 예시로 보면 아래와 같다.
const AppStack = createStackNavigator(
  {
    Home: {
      // initial screen
      screen: HomeTabs,
      navigationOptions: {
        headerShown: false,
      },
    },
    AddCatModal: {
      // Home에서 이동해 AddCatModal으로 이동하면 스택에 2개 노드가 쌓인 것
      screen: AddCatModal,
      navigationOptions: {
        headerTitle: false,
        headerStyle: {
          elevation: 0,
          shadowOpacity: 0,
        },
      },
    },
  },
  {
    initialRouteName: 'Home',
    modal: 'modal',
  },
);

2. Switch navigation

  • stack navigator로 구성한 navigation 구조는 1개 이상일 수 있다. 따라서 스택 내에서 화면을 이동하는 것 뿐만 아니라 A stack navigator에서 B stack navigator로 이동해야 하는 상황이 발생한다.
  • 대부분은 회원가입/로그인과 관련된 화면 이동 vs 정상 로그인 이후의 화면 이동을 구분해 놓고 네비게이터를 넘어가야 할 때 사용한다.
  • 공식 문서 예시를 보면 로그인 전과 후로 2개의 스택 네비게이터를 구성할 수 있다.
const AppNavigator = createStackNavigator({
  Home: HomeScreen,
  Settings: SettingsScreen,
});

const RootNavigator = createSwitchNavigator({
  Login: LoginScreen,
  App: AppNavigator,
});
  • 그런 다음 로그인 유무를 따져서 사용자에게 어떤 stack navigator에 속한 화면을 보여줄지 가를 수 있다.
export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        {isLoggedIn ? (
          <> //로그인을 한 상태
            <Stack.Screen name="Home" component={HomeScreen} />
            <Stack.Screen name="Settings" component={SettingsScreen} />
          </>
        ) : ( // 로그인을 하지 않은 상태
          <Stack.Screen name="SignIn" component={SignInScreen} />
        )}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

3. Tab navigation

  • 대부분 모바일 어플리케이션을 살펴보면 화면 하단에 2~6개 사이의 즐겨찾기와 같은 버튼들이 나열되어 있고 이를 눌렀을 때 해당 페이지로 이동하는 것을 발견할 수 있다. (아래 빨간 박스처럼)
  • 이런 화면 구조는 링크 같아 보이지만 사실상 '병렬 구조'로 구성된 navigator이다.
  • 말 그대로 항상 화면 하단에 tab으로 navigator가 노출되어 있어서 tab을 누를 경우 해당 tab이 가지고 있는 stack의 기본 화면이 열리는 꼴이다.
  • 만약 사용자가 A tab의 2번째 페이지까지 진입한 상태인데 하단의 B tab을 누른다면 다시 B tab이 가진 stack의 기본 화면으로 이동하게 된다.
  • react navigation의 예제 코드는 아래와 같다.
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function HomeScreen() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Home!</Text>
    </View>
  );
}

function SettingsScreen() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Settings!</Text>
    </View>
  );
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}
  • stack navigtor와 tab navigator의 성격을 살려 지난 프로젝트에서는 아래와 같이 스택 구조를 구축할 수 있었다.
    • Home Tabs는 Add Cat Tab, Main Stack, My Page Stack을 병렬적으로 가지고 있는 tab navigator의 모습이다.
    • Navigator 안에 직렬적으로 또 다른 Navigator를 쌓을 수도 있고, 병렬적으로 Navigator를 배치할 수도 있다.

4. Drawer navigation

  • 이 밖에도 모바일 어플에서 좌/우 상단쯤 위치한 햄버거 버튼을 누를 때 좌/우측에서 쓱하고 나타나는 Drawer 또한 하단 Tab navigation처럼 병렬적인 navigator의 역할을 한다.
  • Tab 구조로 화면 상/하단에 위치하느냐 or Drawer의 구조로 화면 좌/우측에 위치하느냐의 차이가 있고, 작동 방식은 Tab navigation과 같다.

5. 스크린 이동: withNavigation과 navigation

  • 위에서 언급한 것과 같이 stack navigation으로 구성된 화면 컴포넌트는 navigation이라는 값을 자동으로 props로 받게 된다. 따라서 스택에 pop, push에 의한 이동 외에도 props로 전달된 navigation을 꺼내서 navigation.navigate('특정 화면')처럼 임의로 이동을 시킬 수도 있다.
  • stack navigator에 등록된 화면에 nested Component가 존재한다면 nested Component에서도 navigation을 props로 받을 수 있다. 단, screen 안에 nested된 component의 경우에는 withNavigation이라는 값을 react Navigation에서 import해와서 사용해야 한다.
  • nested Component에서 navigation 사용을 위해 withNavigation import 하는 예

6. navigation options

  • 이 외에도 navigation을 정의하면서 다양한 options을 정의할 수 있다.
    • header(button, title 등)에 있는 style
    • modal screen 유무
    • navigation 시 특정 함수 추가
profile
선한 변화와 사회적 가치를 만들고 싶은 체인지 메이커+개발자입니다.

2개의 댓글

comment-user-thumbnail
2020년 3월 6일

좋은 포스팅 감사합니다 :-D
이번에 RN에 관심을 갖고 공부하다 Navigation을 알게되어 인스타그램처럼 바텀 / 헤더 네비게이션 해볼려고 하는데
좋은 참고자료인거 같습니다.

1개의 답글