직딩 개발기-React Navigation
직딩에는 여러 화면이 있는데 이 화면간 전환을 위해 React Navigation을 사용했어요.
공식 홈페이지에서 Read Docs를 선택하면 설명서가 나타납니다.
여기서 최신(당시에) 버전 6을 선택했어요. 버전 6을 사용하기 위한 최소 사양은 아래와 같답니다.
직딩의 package.json를 보면 다행히 최소 사양을 충족하네요.
설치
navigation을 사용하기 위해 아래와 같이 패키지들을 설치해줬어요
yarn add @react-navigation/native
yarn add react-native-screens react-native-safe-area-context
yarn add @react-navigation/native-stack
iOS도 지원하기 때문에 Pods을 설치해야하고
cd ios
pod install
android도 android 폴더아래에 있는 MainActivity.java를 열고
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
}
를 추가하는 작업을 해줘야 했어요.
구현
본격적으로 구현하지 전에 기본으로 만들어지는 Template 화면을 navigation에 넣어보는 시험삼아 넣어봤어요.
먼저 기존 src 폴더 아래에 screens/welcome 폴더를 만들고 최상위에 있는 App.tsx를 아래와 같이 index.tsx로 복사해온 후
복사된 welcome/index.tsx를 열고 App component의 이름을 WelcomeScreen로 바꾸고 export 해줬어요.
export const WelcomeScreen;
다음은 기존 App.tsx의 App 선언 내부를 모두 삭제하고 아래와 같이 대체해서 Navigation 사용 준비했습니다.
const App = () => {
return <NavigationContainer>
</NavigationContainer>
};
Navigation에는 여러 Navigator가 있는데 직딩은 Stack을 사용할거라 App위에서 StackNavigator를 생성해서
const Stack = createNativeStackNavigator()
아래와 같이 NavigationContainer에 넣어줬어요. (참고로 Stack은 여러 화면을 Push형태로 중첩 시키거나 Pop으로 빼내는 형태를 말해요)
<Stack.Navigator>
<Stack.Screen name='welcome' component={WelcomeScreen} />
</Stack.Navigator>
그럼 이제 실행해보면?
구조만 달라진거라 눈으로 보기에 처음과 달라진 것은 없어요.
첫 화면
Navigation 기반으로 직딩의 첫 화면을 만들었어요. 아직 구현한게 없어서 추가 앱을 실행하면 로고가 나오는 스플래쉬 화면을 만들었습니다.
먼저 screens 폴더에 splash/index.tsx를 추가하고
직딩이라는 글자가 나오게 구성했어요.
import React from 'react';
import { Text, View } from "react-native"
export const SplashScreen = () => {
return <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text style={{ fontSize: 50 }}>{'직딩'}</Text></View>
}
이렇게 만들어진 화면을 보려면 WelcomeScreen 처럼 Stack.Navigator아래에 추가해줘야 합니다.
<Stack.Screen name=’splash’ component={SplashScreen} options={{ headerShown: false }} />
이제 앱을 실행해서 아래와 같이 직딩이 써있는 화면이 나오는 것을 확인할 수 있었어요.
하지만 이 상태에서는 처음에 추가한 Welcome 화면을 볼 수가 없었죠…
화면 전환
SplashScreen에서 WelcomeScreen으로 넘기려면 Navigation에서 제공하는 함수를 사용해야 합니다.
먼저 SplashScreen 소스를 열고 수정했어요.
export const SplashScreen = ({ navigation }) => {
하지만 직딩 프로젝트는 typescript를 사용하고 있어 navigation에 밑줄이 생겼습니다 ㅠㅠ
Typescript에 대응하기 위해 screens/splash 아래에 types.ts 추가하고 화면에 넘길 Parameter 모음을 선언하고
export type SplashScreenParams = {
//
}
screens/welcome 아래에도 types.ts 추가해줬어요. (Parameter가 필요없는 화면도 일단은 같은 구조를 가지게 하기 위해 빈 Params를 선언했습니다)
export type WelcomeScreenParams = {
//
}
다음은 screens 아래에 types.ts 추가하고 두 화면의 Params를 묶은 후
NativeStackScreenProps에 각 화면 이름과 Params의 모음을 넣어 Screen의 기본이 되는 Type을 만들어줬습니다.
import { NativeStackScreenProps } from "@react-navigation/native-stack";
import { ReactNode } from "react";
import { SplashScreenParams } from "./splash/types"
import { WelcomeScreenParams } from "./welcome/types"
export type ScreenParamList = {
splash: SplashScreenParams,
welcome: WelcomeScreenParams
}
export type ScreenName = keyof ScreenParamList
type ScreenProps<K extends ScreenName> = NativeStackScreenProps<ScreenParamList, K>;
export type IScreen<K extends ScreenName> = FunctionComponent<ScreenProps<K>>
이렇게 만들어진 type에 splash를 지정해서 screens/splash/types.ts에 추가한후
export type ISplashScreen = IScreen<'splash'>
SplashScreen에 수정 방금 선언한 type 적용해서
export const SplashScreen: ISplashScreen = ({ navigation }) => {
화면내부에서 navigate 함수를 호출할 수 있게되었어요. 상호작용할 수 있는 UI가 없기 때문에 마운트 된 후 Timer를 추가해서 자동으로 welcome 화면으로 넘어가게 했어요. 위에 선언한 Type에 의해서 navigate 함수 사용시 화면 이름을 자동완성할 수 있게 되었습니다.
useEffect(() => {
setTimeout(() => {
navigation.navigate('welcome')
}, 2000)
}, [])
이렇게 작성한 후 실행했더니..
다시 Welcome 화면을 볼 수 있게 되었습니다!
문제해결
requireNativeComponent: “RNSScreenStackHeaderConfig” was not found in UIManager
android/gradlew clean