React Native 전환 로드맵 6. React Navigation 설계
React Navigation을 앱 아키텍처 요소로 보고 스택/탭 구조와 상태 연계를 설계하는 방법
Posted
By okorion
React Native 전환 로드맵 6. React Navigation 설계
내비게이션은 “화면 이동 라이브러리”가 아니다.
React Native에서 내비게이션은 앱 전체 구조를 고정시키는 아키텍처 요소다.
이 파트를 대충 넘기면 반드시 다음 문제가 발생한다.
- 화면이 늘어날수록 이동 로직이 꼬인다
- 상태 관리와 내비게이션이 서로 침범한다
- “이 화면은 어디서 오는가?”를 설명 못 한다
목표는 명확하다.
확장해도 무너지지 않는 화면 구조를 처음부터 잡는 것
내비게이션을 아키텍처로 보는 이유
웹에서의 내비게이션은 보통 URL 중심이다.
React Native는 다르다.
웹 (React Router 기준)
- URL = 상태
- 새로고침 가능
- 브라우저 히스토리 기반
React Native
- URL 없음
- 화면 스택 = 상태
- 앱 생명주기와 강하게 결합
즉, RN에서 내비게이션은 단순 이동이 아니라
“현재 앱이 어떤 상태에 있는가”를 나타내는 구조다.
그래서 내비게이션은:
- 전역 상태와 맞닿아 있고
- 인증 여부와 연결되며
- UX 흐름 전체를 결정한다
👉 설계 없이 추가하면 반드시 망가진다.
Stack / Tab / Drawer 선택 기준
Stack Navigator
적합한 UX
- 화면 → 상세 → 서브 화면
- 순차적 흐름
- 뒤로 가기 개념이 명확한 경우
특징
- 화면이 쌓인다 (LIFO)
- 대부분의 앱에서 기본 뼈대
대표 사용처
- 인증 플로우
- 상세 화면 진입
Tab Navigator
적합한 UX
- 주요 기능 간 빠른 전환
- 화면 간 위계 없음
특징
- 항상 보이는 글로벌 이동 수단
- 상태 유지에 유리
대표 사용처
- 홈 / 검색 / 프로필
- 메인 기능 전환
Drawer Navigator
적합한 UX
- 보조 기능 모음
- 설정, 히스토리 등
특징
- 발견성 낮음
- 주요 흐름에는 부적합
대표 사용처
- 설정
- 계정 관리
- 로그아웃
현실적인 조합 패턴
- Root: Stack
- Auth / Main 분기
- Main: Tab
- 주요 기능
- 부가 기능: Drawer 또는 내부 Stack
이 패턴을 벗어나면 설계 이유를 명확히 설명할 수 있어야 한다.
중첩 내비게이션 설계 규칙 (지옥 방지)
중첩은 피할 수 없다.
문제는 기준 없이 중첩할 때다.
규칙 1. 역할이 다른 Navigator만 중첩
- Stack 안에 Stack ❌
- Tab 안에 Tab ❌
- Stack + Tab ⭕
- Stack + Drawer ⭕
규칙 2. “최상위 목적”은 하나만
- Root Navigator는 앱의 상태를 표현
- 로그인됨 / 안 됨
- 하위 Navigator는 UX 흐름만 표현
규칙 3. 화면은 Navigator 구조를 몰라야 한다
1
navigation.navigate('Detail');
- 상위 구조를 가정하는 코드는 설계 실패
- 화면은 “목적지 이름”만 알아야 한다
흔한 실패 패턴
- 화면마다 다른 navigate 경로
- params 전달이 중첩 깊이에 의존
- header 옵션이 여기저기 흩어짐
👉 중첩이 복잡해질수록 구조를 단순화해야 한다
데이터 전달 (route params) 패턴
기본 패턴
1
2
3
navigation.navigate('Detail', {
itemId: id,
});
1
const { itemId } = route.params;
실무 원칙
params는 식별자만
- 전체 객체 전달 ❌
- 화면 진입 후 데이터 로딩
- params는 “주소”, 데이터는 “내용”
useNavigation 사용 기준
1
const navigation = useNavigation();
사용해도 되는 경우
- 버튼, 카드 같은 UI 컴포넌트
- Screen 외부 컴포넌트
주의
- Screen 컴포넌트에서는 props 우선
- 남용하면 구조 파악 어려움
헤더 / 옵션 동적 구성
헤더는 단순 UI가 아니다. 현재 화면의 맥락을 사용자에게 설명하는 요소다.
정적 설정
1
2
3
4
5
6
7
<Stack.Screen
name="Detail"
component={DetailScreen}
options={{
title: '상세',
}}
/>
동적 설정 (데이터 기반)
1
2
3
4
5
useLayoutEffect(() => {
navigation.setOptions({
title: item.title,
});
}, [item]);
헤더 버튼 추가
1
2
3
4
5
options={{
headerRight: () => (
<IconButton onPress={save} />
),
}}
원칙
- 헤더 로직은 Screen 단위
- 전역 설정 남용 금지
- 상태에 따라 바뀌는 경우만 동적 처리
이 파트의 결론
- 내비게이션은 “이동”이 아니라 구조
- Stack / Tab / Drawer는 역할이 다르다
- 중첩은 규칙 없으면 재앙
- params는 주소, 데이터는 상태
이 구조를 먼저 고정하면 이후 상태 관리, 인증, 네이티브 기능이 자연스럽게 얹힌다.
다음 단계에서는 이 내비게이션 구조 위에 반응형 UI와 플랫폼 대응을 추가한다.
This post is licensed under CC BY 4.0 by the author.
