개요
이제 본격적으로 React Native 학습한 내용을 정리할 계획이다. 먼저 첫 번째로는 Expo Router에 대한 내용이다.
1. Expo Router란?
안써봐서 잘 모르지만 기존 React Navigation을 사용할 때 스택, 탭, 드로어의 여러 종류의 내비게이터를 조합해서 사용한다. 그래서 내비게이터의 구조라던지 코드로 직접 작성해줘야 하기 때문에 코드 양이 많아지고, 편의성에서도 Expo Router에 비해 떨어진다.
그럼 Expo Router는 어떻게 작동하길래?
일단 Expo Router는 React Navigation 위에 구축되어서 편의성을 더욱 극대화한 라이브러리로
Expo Router는 파일 기반 라우팅이다.
app이라는 디렉토리 안에 파일을 생성하면, Expo에서 자동으로 해당 파일 자체를 화면으로 인식해서 내비게이션 설정을 구성해준다.
파일 기반 라우팅이라는게 이런 느낌이다.
app
├── index.js -> '/'
├── home.js -> '/home'
├── settings.js -> '/settings'
└ user
└──profile.js -> '/user/profile'
app/index.js
-> 앱의 메인 화면 (경로 : / )
app/home.js
-> /home 경로의 화면
app/settings.js
-> /settings 경로의 화면
app/user/profile.js
-> /user/profile 경로의 화면
간단하게 복잡한 라우팅에 대한 세팅이나 코드 없이, app 디렉토리 안에다가 필요한 화면을 만들기만 하면 쉽게 이동이 가능하다!
1-1. 특징
1) 파일 시스템 기반 라우팅
위에서 본 것 처럼 파일을 생성해주면,그에 맞춰서 라우팅을 진행할 수 있다. 이건 Next.js에서도 사용하는 방식인데 나중에 Next.js도 학습해볼 계획이다
2) 레이아웃
_layout.tsx라는 특수한 파일을 사용해서 여러 화면에 사용되는 공통적인 UI나 내비게이션 설정을 관리할 수 있다. 예를 들면, 앱을 만들 때 반복적으로 사용되는 부분들!
-> 화면 상단에 보이는 헤더
-> 화면 하단에 있는 탭 바들
-> 뒤로 가기 버튼 또는 특정 메뉴가 있는 상단 내비게이션 바
이런 애들을 모든 화면의 파일들마다 넣는다면 비효율적이기도 하고, 유지보수에 있어서도 적절하지 않겠지?!
그래서 레이아웃이라는 하나의 '템플릿'을 사용해서 관리하는 것이다.
app/
├── _layout.tsx // 이 폴더의 모든 화면을 Stack으로 관리
├── index.tsx // (홈 화면)
└── about.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="index" options={{ title: '홈' }} />
<Stack.Screen name="about" options={{ title: '소개' }} />
</Stack>
);
}
-> 이 코드는 앱 전체에 스택 내비게이션이라는 것을 적용하는 것
-> _layout.tsx 파일이 하나의 틀 역할을 하고 여기에다가 다른 화면들을 쌓는 것이다.
또 특정 그룹으로 나누는 것도 가능한데
app/
├── (tabs)/ // URL에 영향을 주지 않는 'tabs' 그룹
│ ├── _layout.tsx // 현재 그룹에만 적용
│ ├── home.tsx // (탭1: 홈)
│ └── settings.tsx // (탭2: 설정)
│
├── _layout.tsx // 앱 전체의 최상위(보통 여기에 Stack을 둠)
└── index.tsx
import { Tabs } from 'expo-router';
import FontAwesome from '@expo/vector-icons/FontAwesome';
// 이 컴포넌트는 (tabs) 폴더 안의 화면들을 위한 틀
export default function TabLayout() {
return (
<Tabs>
<Tabs.Screen
name="home"
options={{
title: '홈',
tabBarIcon: ({ color }) => <FontAwesome size={28} name="home" color={color} />,
}}
/>
<Tabs.Screen
name="settings"
options={{
title: '설정',
tabBarIcon: ({ color }) => <FontAwesome size={28} name="cog" color={color} />,
}}
/>
</Tabs>
);
}
-> 폴더 이름을 () 괄호로 감싸게 되면 URL 경로에는 영향을 주지 않고 화면을 묶을 수 있다.
-> 여기서 index.tsx 같이 (tabs) 폴더 바깥에 있는 화면은 이 탭 레이아웃 자체에 영향을 받지 않는다.
3) 동적 라우팅
파일이나 폴더 이름에 [] 대괄호를 사용해서 동적 경로 세그먼트를 만들 수 있다.
예를 들면,
app/post/[id].ts
-> /post/1, /post/2 와 같이 경로에 id 값을 컴포넌트 내에서 파라미터로 받아서 동적으로 처리할 수 있게 한다.
app/user/[...slug].ts
-> 이거는 여러 세그먼트들을 한 번에 처리할 수 있도록 하는 'catch-all' 라우트라는 것이다.
-> /user/a/b/c라는 경로에 모두 대응하는 것.
4) 유니버셜 링크 및 딥 링크 자동 지원
이거 좋은 것 같다. 안드로이드 네이티브 할 때 딥 링크 처리에 있어서 과정이 복잡했었는데, Expo Router로 생성된 모든 경로는 자동으로 딥 링크를 지원한다.
1-2. 화면간 이동
이제 어느 정도 Expo Router에 대한 특징들을 학습했으니까, 화면간 이동하는 방법에 대해서 정리해보자.
화면 사이를 이동할 때는 Link라는 컴포넌트를 사용하는데 웹에서의 <a> 태그와 유사하게 동작한다.
// app/index.js
import { Link } from 'expo-router';
import { View, Text } from 'react-native';
export default function HomeScreen() {
return (
<View>
<Text>홈 화면</Text>
<Link href="/about">
<Text>소개 페이지로 이동</Text>
</Link>
<Link href="/post/123">
<Text>123번 게시글 보기</Text>
</Link>
</View>
);
}
또는 이제 우리가 React에서 사용했던 useRouter 훅을 통해 router 객체를 가져와 사용할 수도 있다.
import { useRouter } from 'expo-router';
import { Button, View } from 'react-native';
export default function LoginScreen() {
// useRouter 훅을 호출하여 router 객체를 가져옵니다.
const router = useRouter();
const handleLogin = async () => {
const loginSuccess = await api.login('user', 'password');
if (loginSuccess) {
// 로그인 성공 시, 메인 화면으로 이동
router.push('/home');
} else {
alert('로그인 실패!');
}
};
return (
<View>
<Button title="로그인" onPress={handleLogin} />
</View>
);
}
이때 이동에는 여러 가지 방식이 있는데
router.push('/path')
-> 새로운 화면을 현재 화면 위에 쌓는 스택의 방식
router.replace('/path')
-> 현재 화면을 새로운 화면으로 교체하는 것
-> 뒤로가기 기록이 남지 않겠지
router.back()
-> 이전 화면으로 돌아간다.
'Web&Hybrid > React Native' 카테고리의 다른 글
| [RN] Mirage JS로 API 서버 mocking (0) | 2025.10.20 |
|---|---|
| [RN] Axios 활용한 HTTP 통신 (0) | 2025.10.19 |
| [RN] Reanimated 사용해보기 (0) | 2025.09.28 |
| [RN] React Native 작동 방식 - 구 아키텍처 (1) | 2025.09.18 |
| [RN] Expo란 (0) | 2025.09.05 |