본문 바로가기
React-Native

[React-Native] react-navigation 사용하여 화면 간 이동하기

by 방방방땡 2019. 10. 15.

왜 react-navigation인가?

react-native로 개발을 시작하는 데 있어서 가장 중요한 요소 중 하나는 화면 별 스택 구성과 화면 간 이동에 어떤 라이브러리를 쓸 것인가인 것 같습니다.

 

 

더 많은 라이브러리들이 있겠지만 화면을 이동할 때 많이 쓰는 라이브러리는 이정도가 있는 것 같습니다.

 

그중에 저는 react-navigation을 사용하여 개발을 시작하였습니다.

 

그 이유는 성능개선에 관한 update가 다른 라이브러리보다 훨씬 좋다고 판단이 되었기 때문입니다. react-navigation는 공식홈페이지가 따로 존재하고 현재 버전 4.0.10(글 작성 시)까지 나와있는 상태입니다. 현재 이 라이브러리는 페이스북에서 지원해주며 2.0이 2018년 4월 출시, 3.0이 2018년 11월 출시, 4.0이 2019년 9월에 출시를 하며 안정적인 라이브러리 개발에 힘쓰고 있는 모습을 보여주고 있습니다. 아직 리액트 네이티브가 안정성과 성능면에서 완전한 플랫폼이 아닌 만큼 화면 전환에 있어서도 문제점을 보여줄 때가 있고 그만큼 많은 라이브러리들이 나오고 있는데 그중 가장 열심히 문제점을 고치려 노력하는 것이 제가 본 react-navigation의 장점이었습니다.

 


react-navigation 사용법

화면전환에 대한 기본 사용법을 알 수 있는 기본적인 예제는 react-native tutorial 에서 확인할 수 있습니다.

 

기본적인 활용은 튜토리얼을 통해 진행하시고 저는 실제적으로 앱에 적용해 볼 수 있게끔 react-navigation을 모듈화 해서 사용해 보겠습니다.

 

1. 라이브러리 설치

yarn add react-navigation
# or with npm
# npm install react-navigation
yarn add react-native-gesture-handler react-native-reanimated
# or with npm
# npm install react-native-gesture-handler react-native-reanimated

 

RN >= 0.60의 경우

cd ios
pod install
cd ..

 

RN <= 0.59의 경우

react-native link react-native-reanimated
react-native link react-native-gesture-handler

 

2. src/common/NavigationService.js 생성

모듈화 시켜 사용하기 위해 common디렉토리 밑에 NavigationService.js을 생성해줍니다.

import { NavigationActions } from 'react-navigation';

let _navigator;

function setTopLevelNavigator(navigatorRef) {
    _navigator = navigatorRef;
}

function navigate(routeName, params) {
    _navigator.dispatch(
        NavigationActions.navigate({
            routeName,
            params,
        })
    )
    
}

function back() { 
    _navigator.dispatch(
        NavigationActions.back()
    );
}

// add other navigation functions that you need and export them

export default {
    navigate,
    setTopLevelNavigator,
    back,
};

 

navigate() 함수를 사용해 다른 스크린으로 이동할 수 있고 params값을 이용하여 데이터도 주고받을 수 있습니다.

back() 함수를 이용하면 이전 스크린으로 돌아갈 수 있습니다.

NavigationService.js를 사용하기 위해서 common 밑에 index.js 파일이 있어야 하고 밑에 코드를 넣어주어야 합니다.

import _NavigationService from './NavigationService';
export const NavigationService = _NavigationService;

 

3. 라우터 설정 및 화면 추가

App.js 수정

import React from 'react';
import RootRouter from './src/Router';

class App extends React.Component {

  render() {
    return (
      <RootRouter />
    );
  }

}

export default App;

 

src/Router.js 생성

import React, { Component } from 'react';
import Navigation from '../src/navigation';
import { NavigationService } from '../src/common';

class Router extends Component {

    constructor(props) {
        super(props);
    }

    render() {
        return (
            <Navigation
                ref={navigatorRef => {
                    NavigationService.setTopLevelNavigator(navigatorRef);
                }}
            />
        )
    }
}

export default Router;

 

src/navigation/index.js 생성

import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import LoginScreen from './LoginScreen';
import HomeScreen from './HomeScreen';

const AuthStack = createStackNavigator(
    {
        LoginScreen: {screen: LoginScreen},
        HomeScreen: {screen: HomeScreen}
    },
    {
        initialRouteName: 'LoginScreen'
    }
);

// 최상단 네비게이터
const AppNavigator = createSwitchNavigator(
    {
        Auth: AuthStack
    },
    {
        initialRouteName: 'Auth',
    }
);

export default createAppContainer(AppNavigator);

 

기본 세팅이 끝났고 LoginScreen화면과 HomeScreen화면 간 이동하는 예제를 작성해보겠습니다.

 

LoginScreen.js 생성

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
import { NavigationService } from '../../common';

class LoginScreen extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <View style={styles.container}>
                <StatusBar barStyle="dark-content" />
                <View>
                    <Text style={{fontSize:25}}>Login Screen</Text>
                </View>
                <TouchableOpacity
                        onPress={()=> NavigationService.navigate('HomeScreen', {
                            screen: 'HomeScreen',
                            info: 'information'
                        })}
                        style={{
                            justifyContent: 'flex-end',
                            backgroundColor: 'rgb(87,174,198)',
                            padding: 20,
                            marginTop: 20,
                            borderRadius: 30
                        }}>
                        <Text style={{fontSize: 20, textAlign: 'center', color: 'white'}}>다음</Text>
                    </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'white',
        justifyContent: 'center',
    }
})

export default LoginScreen;  

 

HomeScreen.js 생성

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
import {NavigationService} from '../../common';

class HomeScreen extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <View style={styles.container}>
                <StatusBar barStyle="dark-content" />
                <View>
                    <Text style={{fontSize:25}}>Home Screen</Text>
                </View>
                <TouchableOpacity
                        onPress={()=> NavigationService.back()}
                        style={{
                            justifyContent: 'flex-end',
                            backgroundColor: 'rgb(87,174,198)',
                            padding: 20,
                            marginTop: 20,
                            borderRadius: 30
                        }}>
                        <Text style={{fontSize: 20, textAlign: 'center', color: 'white'}}>뒤로</Text>
                    </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: 'white',
        justifyContent: 'center',
    }
})

export default HomeScreen;  

 

LoginScreen에서는 navigate() 함수를 사용하여 HomeScreen으로 넘어가고, HomeScreen에서 back() 함수를 사용하여 다시 LoginScreen으로 넘어가는 예제를 작성하였습니다.

 

4. 테스트

 

 

결론

정상적으로 두 화면이 전환되는 것을 확인할 수 있습니다. 이런 식으로 NavigationService.navigate를 사용해서 자유롭게 화면 전환을 할 수 있는 앱을 구현해 보았습니다. 앱을 만들어가면서 Screen화면이 추가될때마다 Navigation의 역할이 더욱 중요해 지는것 같습니다. 이런식으로 모듈화 해서 사용하면 필요할때마다 화면전환을 할 수 있고 개발 속도도 빨라질 것 같습니다. 또 params값을 잘 활용한다면 화면마다 데이터를 쉽게 주고받을 수도 있습니다. redux나 mobx 같은 상태 관리 라이브러리와도 연동해서 사용하면 더욱 좋은 앱을 만들 수 있을 것 같습니다.