
โ React Navigation

React Navigation์ React Native์์ ํ๋ฉด ์ด๋(๋ค๋น๊ฒ์ด์ )์ ๋ง๋๋ ๊ฐ์ฅ ๋ํ์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ฑ์ “ํ๋ฉด ์คํ”, “ํญ”, “์๋ ๋ฉ๋ด”, “๋ฅ๋งํฌ”, “์ ํ ์ ๋๋ฉ์ด์ ” ๊ฐ์ ๊ฑธ ํ์ค์ ์ผ๋ก ๊ตฌ์ฑํ ์ ์๋ค.
React Navigation์ด ํด์ฃผ๋ ๊ฒ
- Stack Navigation: A → B → C์ฒ๋ผ ํ๋ฉด์ ์์๊ฐ๋ฉฐ ์ด๋ (๋ค๋ก๊ฐ๊ธฐ ํฌํจ)
- Tab Navigation: ํ๋จ ํญ(ํ/๊ฒ์/๋ง์ดํ์ด์ง ๊ฐ์)
- Drawer Navigation: ์์์ ๋์ค๋ ์ฌ์ด๋ ๋ฉ๋ด
- Nested Navigation: ํญ ์์ ์คํ, ์คํ ์์ ํญ ๊ฐ์ ์กฐํฉ
- Params ์ ๋ฌ: navigate("Detail", { id }) ์ฒ๋ผ ํ๋ฉด ๊ฐ ๋ฐ์ดํฐ ์ ๋ฌ
- Deep Linking: myapp://detail/123 ๊ฐ์ ๋งํฌ๋ก ํน์ ํ๋ฉด ์ด๊ธฐ
โ Bottom Tabs Navigator
https://reactnavigation.org/docs/bottom-tab-navigator?config=dynamic
Bottom Tabs Navigator | React Navigation
A simple tab bar on the bottom of the screen that lets you switch between different routes. Routes are lazily initialized -- their screen components are not mounted until they are first focused.
reactnavigation.org
Navigator(stack or tab)๋ฅผ ๋ ๋๋งํ๋ ค๋ฉด NavigationContainer๋ฅผ ๋จผ์ ๋ ๋๋ง ํด์ผ ํ๋ค.
(appํด๋ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ Expo Router๋ฉด ํ์์๋ค.)
Tab.Navigator prop
screenOptions: ๋ค์ํ ์ต์
๋ค ์ค์ ๊ฐ๋ฅ
(๋ชจ๋ Screen์ ๊ฐ์ ์ค์ ์ ํ๊ณ ์ถ๋ค๋ฉด)
export default function Tabs() {
return (
<Tab.Navigator
initialRouteName="Movies"
screenOptions={{
tabBarLabelStyle: {
backgroundColor: "red",
},
}}
>
<Tab.Screen name="Movies" component={Movies}></Tab.Screen>
<Tab.Screen name="Tv" component={Tv}></Tab.Screen>
<Tab.Screen name="Search" component={Search}></Tab.Screen>
</Tab.Navigator>
);
}
๊ฐ Screen์ ์ค์ ์ ๋ฐ๋ก ์ฃผ๊ณ ์ถ๋ค๋ฉด ๊ฐ Screen์ options prop์ ์ฌ์ฉ.
<Tab.Screen
name="Tv"
component={Tv}
options={{
tabBarLabelStyle: {
backgroundColor: "purple",
},
}}
></Tab.Screen>
tabBarIcon
Function that given { focused: boolean, color: string, size: number } returns a React.Node, to display in the tab bar.
<Tab.Screen
name="Movies"
component={Movies}
options={{
tabBarIcon: ({focused, color, size }) => (
<Ionicons name="film-outline" color={color} size={size} />
),
}}
/>
https://reactnavigation.org/docs/bottom-tab-navigator#options
Bottom Tabs Navigator | React Navigation
A simple tab bar on the bottom of the screen that lets you switch between different routes. Routes are lazily initialized -- their screen components are not mounted until they are first focused.
reactnavigation.org
โ Stack Navigator
Stack vs Native Stack
Stack Navigator๋ React Navigation์ ์๋ ๊ฒ์ด๊ณ , javascript๋ก ๊ตฌํ๋ ๊ฒ.
(๊ฐ Platform์ navigation์ ์ฌ์ฉํ์ง ์๋๋ค. Native๋ก ๊ตฌํ๋ navigation๋ณด๋ค ์ฑ๋ฅ์ด ์ ์ข์ ์ ์์)
Native Stack Navigator๋ Native API๋ฅผ ์ด์ฉํด ๊ตฌํ๋ ๊ฒ.
createNativeStackNavigator๋ฅผ ์ฌ์ฉํ์ฌ navigator๋ฅผ ๋ง๋ค๋ฉด native๋ก ๋ง๋ ์ผ๋ฐ ์ดํ๋ฆฌ์ผ์ด์ ๊ณผ ์์ ํ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์๋ํ๊ณ , ํผํฌ๋จผ์ค๋ ๋๊ฐ๋ค.
(๋์ ์ปค์คํ ํ ์ ์๋ ์์ญ์ด ์กฐ๊ธ ์ค์ด๋ ๋ค.)
(๊ณต์๋ฌธ์์์๋ Native๋ฅผ ์ถ์ฒ)
npm install @react-navigation/native-stack
or
npx expo install @react-navigation/native-stack
๐ expo install์ ์ฐ๋ ์ด์
ํ์ฌ Expo SDK ๋ฒ์ ์ ๋ง๋ ๋ฒ์ ์๋ ์ ํ
iOS/Android ๋ค์ดํฐ๋ธ ์์กด์ฑ ํธํ ๋ณด์ฅ
Usage
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { Text, View } from "react-native";
const NativeStack = createNativeStackNavigator();
const ScreenOne = () => (
<View>
<Text>One</Text>
</View>
);
const ScreenTwo = () => (
<View>
<Text>Two</Text>
</View>
);
const ScreenThree = () => (
<View>
<Text>Three</Text>
</View>
);
export default function Stack() {
return (
<NativeStack.Navigator>
<NativeStack.Screen name="One" component={ScreenOne} />
<NativeStack.Screen name="Two" component={ScreenTwo} />
<NativeStack.Screen name="Three" component={ScreenThree} />
</NativeStack.Navigator>
);
}
Navigation prop reference
navigate
const ScreenOne = ({ navigation: { navigate } }: any) => (
<TouchableOpacity onPress={() => navigate("Two")}>
<Text>Go to Two</Text>
</TouchableOpacity>
);
const ScreenTwo = ({ navigation: { navigate } }: any) => (
<TouchableOpacity onPress={() => navigate("Three")}>
<Text>Go to Three</Text>
</TouchableOpacity>
);
const ScreenThree = ({ navigation: { goBack } }: any) => (
<TouchableOpacity onPress={() => goBack()}>
<Text>Go Back</Text>
</TouchableOpacity>
);
Stack.Navigator props
animation
ํ๋ซํผ์ animation ๊ธฐ๋ณธ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค. iOS์์๋ flip๋ ์ฌ์ฉ ๊ฐ๋ฅ.
headerBackTitleVisible: false -> headerBackButtonDisplayMode: "minimal"
๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ ์ ๋ชฉ์ ์์ ๋ ์์ฑ ์ด๋ฆ์ด ๋ฐ๋(iOS only)
โ Stack navigator์ Tab navigator ๊ฐ์ด ์ฌ์ฉํ๊ธฐ
๋จผ์ Root Stack navigator๋ฅผ ๋ง๋ค๊ณ Tabs์ Stack์ Screen์ผ๋ก ๋ ๋๋ง ํ๋ค.
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import Stack from "./Stack";
import Tabs from "./Tabs";
const Nav = createNativeStackNavigator();
export default function Root() {
return (
<Nav.Navigator screenOptions={{ headerShown: false }}>
<Nav.Screen name="Tabs" component={Tabs} />
<Nav.Screen name="Stack" component={Stack} />
</Nav.Navigator>
);
}
๊ทธ๋ฆฌ๊ณ Tabs ๋ด์ Movies component์์ props๋ก navigation๋ด์ navigate์ TouchableOpacity๋ฅผ ์ฌ์ฉํด ์คํฌ๋ฆฐ์ด ๋๋ ธ์ ๋, Stack ์ปดํฌ๋ํธ ๋ด์ Three Screen์ผ๋ก ์ด๋ํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ ์ฝ๋๋ฅผ ์ฌ์ฉ.
import { Text, TouchableOpacity } from "react-native";
export default function Movies({ navigation: { navigate } }: any) {
return (
<TouchableOpacity
onPress={() => navigate("Three")}
style={{ flex: 1, alignItems: "center", justifyContent: "center" }}
>
<Text>Movies</Text>
</TouchableOpacity>
);
}
๋ค์๊ณผ ๊ฐ์ ์๋ฌ ๋ฐ์ The action 'NAVIGATE' with payload {"name":"Three"} was not handled by any navigator.
์๋ก ๋ค๋ฅธ Navigator(Stack๊ณผ Tab) ์ฌ์ด๋ฅผ ์ด๋ํ๋ ค๋ฉด ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด์ผ ํ๋ค.
๋จผ์ Stack navigator์ ๊ฐ์ ๊ทธ ๋ค์ Three Screen์ผ๋ก ์ด๋ํ๊ณ ์ถ๋ค๊ณ ์ ์ด์ค์ผ ํจ.
import { Text, TouchableOpacity } from "react-native";
export default function Movies({ navigation: { navigate } }: any) {
return (
<TouchableOpacity
onPress={() => navigate("Stack", { screen: "Three" })}
style={{ flex: 1, alignItems: "center", justifyContent: "center" }}
>
<Text>Movies</Text>
</TouchableOpacity>
);
}
ํน์ ํ๋ฉด์ ๋ค์ด๊ฐ์ Stack navigator๋ฅผ ์ฌ์ฉํ ๋, Tab navigator๊ฐ ๋ณด์ด์ง ์์์ผ๋ฉด ํ ๋ ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค.
(๋ณดํต ์ด๋ ๊ฒ ๋ง์ด ์ฌ์ฉ)
Stack์์๋ง modal์ ์ฌ์ฉํ๊ณ Search screen์ผ๋ก ๋์๊ฐ ๋๋ modal๋ก ์ด๋ฆฐ stack์ ๋ซ๊ณ ๋์๊ฐ๋ ๋ฐฉ๋ฒ
<Root.tsx>
export default function Root() {
return (
<Nav.Navigator screenOptions={{ headerShown: false }}>
<Nav.Screen name="Tabs" component={Tabs} />
<Nav.Screen
name="Stack"
component={Stack}
options={{ presentation: "modal" }}
/>
</Nav.Navigator>
);
}
<Stack.tsx>
const ScreenThree = ({ navigation }: any) => (
<TouchableOpacity
onPress={() => {
const parent = navigation.getParent();
parent.goBack();
requestAnimationFrame(() => {
parent.navigate("Tabs", { screen: "Search" });
});
}}
>
<Text>Go to Search</Text>
</TouchableOpacity>
);
navigation.goBack()์ “ํ์ฌ Stack ์์์๋ง ๋ค๋ก ๊ฐ๋ ๊ฒ”์ด๊ณ
navigation.getParent().goBack()์ “modal๋ก ์ด๋ฆฐ Stack ์์ฒด๋ฅผ ๋ซ๋ ๊ฒ”์ด๋ค.
์ง๊ธ ๊ตฌ์กฐ์์๋ ๋ฐ๋์ parent๋ฅผ ์จ์ผ ํ๋ค.
requestAnimationFrame์ด ํ์ํ ์ด์
• v7์์๋ modal dismiss ์ ๋๋ฉ์ด์
์ด ์์๋๊ธฐ ์ ์ navigateํ๋ฉด
• ์ฌ์ ํ “modal ์ปจํ
์คํธ”๋ก ์ฒ๋ฆฌ๋๋ ๊ฒฝ์ฐ๊ฐ ์์
• ํ ํ๋ ์ ๋ฆ์ถ๋ฉด ์์ ์ ์ผ๋ก ๋ถ๋ฆฌ๋จ
'๐ธ React Native' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| React Native - Dark Mode (0) | 2026.01.26 |
|---|---|
| React Native - npx expo prebuild, ๊ธฐ๊ธฐ ๋ฌด์ ์ฐ๊ฒฐ ๋ชจ๋ํฐ๋ง (0) | 2026.01.21 |
| React Native - 26.01.20 ๊ธฐ์ค ์ต์ Components, API (0) | 2026.01.20 |
| React Native - Android Studio & Xcode ํ๊ฒฝ ์ธํ (m2 macOS) (0) | 2026.01.20 |
| React Native - ๋ฐฐํฌํ๊ธฐ (0) | 2026.01.19 |