[React] React Router 중첩 라우트에서 index 대신 Navigate를 선택한 이유

2026. 1. 19. 04:25·💻 개발/🦕 React
728x90
반응형

| 서론

안녕하세요, 팡일입니다.

 

React Router v6에서 중첩 라우트(nested routes)를 사용하다 보면 index 라우트를 자연스럽게 사용하게 됩니다. 저 역시 메시지 기능을 구현하면서 /message 아래에 여러 하위 페이지를 두는 구조를 만들게 되었는데요?

 

구조는 다음과 같았습니다.

  • /message
  • /message/send
  • /message/history
  • /message/template

의도는 단순했습니다. /message로 접근했을 때, 가장 기본적인 화면인 ‘문자 보내기’ 페이지를 보여주고 싶었습니다. 그래서 처음에는 index 라우트를 사용해 구현했지만, 포스팅 제목처럼 URL이 그대로인 점으로 인해서 애매한 상황에 놓여 있었습니다. 오늘은 현재 겪은 상황을 공유하고, 어떤 식으로 해결했는지 기록해보려고 합니다.

 

 

 

 

| 처음 구현: index 라우트를 사용한 기본 페이지 처리

초기 라우터 구조는 아래와 같았습니다.

<Route path="/message">
  <Route index element={<MessageSendPage />} />
  <Route path="send" element={<MessageSendPage />} />
  <Route path="history" element={<MessageHistoryPage />} />
  <Route path="template" element={<MessageTemplatePage />} />
</Route>

 

이렇게 설정하면 /message로 접근했을 때 MessageSendPage가 정상적으로 렌더링됩니다. 기능적으로는 전혀 문제가 없어 보였고, 실제 화면도 의도한 대로 잘 나왔습니다.

 

하지만 실제로 사용해보면서 한 가지 점이 계속 마음에 걸렸습니다.

 

 

 

 

| 문제 인식: 화면은 맞는데 URL이 애매하다

'메세지' 버튼을 눌렀지만, 주소창은 여전히 '/message'인 상태.
'문자 보내기' 하위 메뉴를 클릭해야 변경되는 모습.

 

위의 사진처럼, /message에 접근했을 때 화면은 분명 ‘문자 보내기’ 페이지인데, 주소창의 URL은 여전히 /message였습니다.

 

처음에는 “이 정도는 괜찮지 않나?”라고 생각했지만, 조금 더 사용해보니 몇 가지 불편함이 느껴졌습니다.

  • 주소를 복사하거나 북마크를 하면 /message/send가 아니라 /message가 남음
  • 새로고침했을 때 “어디에 있는 페이지인지” URL만 보고 바로 알기 어려움
  • 사이드바에서 활성 메뉴를 판단할 때 기준이 애매해짐
  • 무엇보다 보여지는 화면과 URL이 일치하지 않는 느낌이 계속 남음

즉, 기능은 맞지만 UX와 구조 측면에서는 찝찝한 상태였습니다.

 

 

 

 

| 관점 전환:  /message는 페이지가 아니라 진입점이다

이 문제를 해결하기 위해 /message의 역할을 다시 생각해보게 되었습니다.

 

/message는 실제로 보여줄 독립적인 페이지라기보다는, 메시지 기능으로 들어오는 진입점에 더 가깝다고 느껴졌습니다.

 

그렇다면 /message에 접근했을 때 특정 페이지를 렌더링하는 것이 아니라, 의도한 기본 경로(/message/send)로 이동시키는 것이 더 자연스럽지 않을까라는 생각이 들었습니다.

 

 

 

 

| 해결 방법: index 라우트에서  Navigate 로 redirect 처리 

React Router에서는 이런 경우를 위해 Navigate 컴포넌트를 제공하고 있습니다.

 

index 라우트에서 페이지를 렌더링하는 대신, redirect만 담당하도록 변경했습니다.

import { Navigate } from "react-router-dom";

<Route path="/message">
  <Route index element={<Navigate to="send" replace />} />
  <Route path="send" element={<MessageSendPage />} />
  <Route path="history" element={<MessageHistoryPage />} />
  <Route path="template" element={<MessageTemplatePage />} />
</Route>

 

이제 동작은 다음과 같습니다.

  • /message 접근
  • 즉시 /message/send로 이동
  • URL과 화면이 정확히 일치

이 방식으로 변경하니, 처음에 느꼈던 어색함이 깔끔하게 해결되었습니다.

 

 

 

 

| 이 방식이 좋다고 느낀 이유

이 변경이 좋았던 이유는 단순히 URL이 예뻐져서만은 아니었습니다.

 

첫째, URL과 화면의 역할이 명확해졌습니다.

: 사용자는 주소만 보고도 지금 어떤 화면에 있는지 바로 알 수 있고, 북마크나 공유 시에도 의도가 분명해졌습니다.

 

둘째, 라우팅 책임이 라우터에만 남아 있게 되었습니다.

: 컴포넌트 내부에서 useEffect로 강제로 이동시키지 않아도 되었고, 페이지는 오로지 “화면을 그리는 역할”에만 집중할 수 있었습니다.

 

셋째, 중첩 라우트 구조를 그대로 유지할 수 있었습니다.

: 앞으로 메시지 관련 기능이 더 추가되더라도 /message 하위 구조를 자연스럽게 확장할 수 있는 상태가 되었습니다.

 

 

 

| 결론

이번 경험을 통해 정리하게 된 생각은 다음과 같습니다.

 

중첩 라우트에서 index는 “기본으로 보여줄 화면”이라기보다는 “기본으로 이동시킬 경로”로 생각하는 편이 더 자연스럽다.

 

작은 차이처럼 보이지만, URL 설계는 결국 사용자 경험과 구조의 명확성으로 이어진다는 것을 다시 한 번 느끼게 되었습니다.

 

React Router를 사용하면서 단순히 “동작하게 만드는 것”을 넘어서 “의도가 드러나는 구조를 만드는 것”에 대해 한 단계 더 고민해볼 수 있었던 경험이었습니다.

 

728x90
반응형

'💻 개발 > 🦕 React' 카테고리의 다른 글

[React] React + Vite + TS + Firebase Hosting + Github Action 구축하기  (0) 2026.01.18
[React] TanStack Query(React Query) 활용하기 - useMutation으로 데이터 생성·수정·삭제 마스터하기  (0) 2026.01.15
[React] TanStack Query(React Query) 깊게 파고들기 : useQuery와 캐시 생명주기의 모든 것  (0) 2026.01.15
[React] 코드 스플리팅을 적용했을 뿐인데, 초기 로딩이 줄어들었습니다  (0) 2025.12.27
[React] public 이미지에서 import 구조로 (이미지 최적화 개선기)  (1) 2025.12.27
'💻 개발/🦕 React' 카테고리의 다른 글
  • [React] React + Vite + TS + Firebase Hosting + Github Action 구축하기
  • [React] TanStack Query(React Query) 활용하기 - useMutation으로 데이터 생성·수정·삭제 마스터하기
  • [React] TanStack Query(React Query) 깊게 파고들기 : useQuery와 캐시 생명주기의 모든 것
  • [React] 코드 스플리팅을 적용했을 뿐인데, 초기 로딩이 줄어들었습니다
pangil_kim
pangil_kim
기록을 통해 지속적인 성장을 추구합니다.
  • pangil_kim
    멈추지 않는 기록
    pangil_kim
  • 전체
    오늘
    어제
  • 📝 글쓰기
      ⚙️ 관리

    • 분류 전체보기 (405) N
      • 💻 개발 (176) N
        • ※ 참고 지식 (9)
        • 🦕 React (13)
        • 🎩 Next.js (25)
        • 📘 TypeScript (4)
        • 📒 JavaScript (8)
        • 🟩 Node.js (7)
        • 📀 MySQL (24)
        • 🌸 Spring Boot (5)
        • 👷 SveleteKit (24)
        • 🩵 Flutter (11)
        • 🌀 Dart (2)
        • 🌈 CSS (5)
        • 🔸Git (1)
        • 🔥 Firebase (4)
        • 🧑🏻‍💻 코테 (29) N
        • 🕸️ 알고리즘 (4)
        • 🌤️ AWS (1) N
      • 📋 프로젝트 (4) N
        • ☄️ 트러블 슈팅 (2) N
        • 🧑🏻‍💻 서비스 소개 (2)
      • ✍🏻 회고 (52) N
        • ☀️ 취준일지 (6) N
        • 🍀 우테코 (32)
        • 👋 주간회고 (1) N
      • 📰 정보 공유 (12)
      • 🧑🏻‍💻 개발자라면? (1)
      • 🏫 한동대학교 (153)
        • Database (15)
        • Software Engineering (18)
        • EAP (22)
        • 일반화학 (26)
        • 25-1 수업 정리 (19)
        • Computer Networking (36)
        • OPIc (2)
        • 미술의 이해 (15)
  • 최근 글

  • 인기 글

  • 태그

    데이터베이스
    GLS
    한동대학교
    CCM
    부트캠프
    컴네
    묵상
    QT
    네트워킹
    computer networks and the internet
    우아한테크코스
    전산전자공학부
    웹개발
    글로벌리더십학부
    고윤민교수님
    csee
    주일
    설교
    찬양
    우테코
    어노인팅
    우테코 8기
    프론트엔드
    예배
    FE
    날마다 솟는 샘물
    날솟샘
    typeScript
    프리코스
    웹 프론트엔드 8기
  • 최근 댓글

  • 250x250
  • hELLO· Designed By정상우.v4.10.4
pangil_kim
[React] React Router 중첩 라우트에서 index 대신 Navigate를 선택한 이유
상단으로

티스토리툴바