본문 바로가기
차근차근

React Router로 웹페이지 이동 흐름 완전 정복|SPA 라우팅 구현 모든 방법

by 아빠고미 2025. 5. 4.
반응형

🚀 React Router로 웹페이지 이동 흐름 완전 정복|SPA에서 라우팅을 구현하는 모든 방법

안녕하세요, 퍼블리셔 노미입니다!
지금까지 우리는 HTML, CSS, JavaScript, API, 인증, 상태관리, 모달까지 프론트엔드 개발의 핵심 흐름을 따라왔습니다.

하지만 여기서 한 가지 빠질 수 없는 주제가 있어요.
바로 **“라우팅(Routing)”** 입니다.
SPA(Single Page Application)에서는 화면 이동을 어떻게 구현할까요?
새로고침 없이 자연스럽게 페이지를 이동하려면 어떤 기술이 필요할까요?

React Router로 웹페이지 이동 흐름 완전 정복|SPA 라우팅 구현 모든 방법


이 글에서는 프론트 개발자가 꼭 알아야 할 SPA와 라우팅 개념부터 React Router 사용법, 실전 코드 구성까지 자세하게 풀어서 정리해드릴게요.


📌 라우팅(Routing)이란?

라우팅이란 사용자가 웹사이트에서 특정 URL로 이동할 때 알맞은 페이지(컴포넌트)를 보여주는 과정을 말합니다.

  • 일반 웹사이트: 페이지 이동 시 새로고침 발생
  • SPA(Single Page Application): 페이지 새로고침 없이 URL만 변경되고 화면만 전환

→ SPA에서는 라우터(Router)라는 도구가 필요합니다.


🧩 SPA와 라우팅의 차이

구분 전통적 웹사이트 SPA
페이지 이동 서버로 새 요청 → 새 HTML 문서 반환 JS로 URL 변경 → 컴포넌트만 교체
새로고침 필수 불필요
속도 느림 빠름
UX 끊김 발생 자연스러움

🛠 React Router란?

React Router는 SPA에서 URL에 따라 특정 컴포넌트를 렌더링하도록 도와주는 라이브러리입니다.
프론트엔드 프로젝트에서 가장 많이 사용되는 라우팅 솔루션 중 하나예요.

  • 경로에 따라 다른 컴포넌트 보여주기
  • 중첩 라우트, 동적 라우트 지원
  • 네비게이션, 리다이렉트, protected route 처리

📦 설치 방법

npm install react-router-dom

React 프로젝트에 설치 후 바로 사용할 수 있어요.


🚏 기본 사용법 정리

1. BrowserRouter로 감싸기


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

function App() {
  return (
    <BrowserRouter>
      <Routes>
        {/* 라우트 작성 */}
      </Routes>
    </BrowserRouter>
  );
}

2. Routes & Route 설정


import { Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}
  • path는 URL 경로
  • element는 보여줄 컴포넌트

🧭 Link 컴포넌트로 페이지 이동


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

function Navbar() {
  return (
    <nav>
      <Link to="/">홈</Link>
      <Link to="/about">소개</Link>
    </nav>
  );
}

→ a 태그 대신 Link 컴포넌트를 사용해야 새로고침 없이 이동합니다!


🔗 useNavigate로 코드에서 이동


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

function LoginButton() {
  const navigate = useNavigate();

  const handleLogin = () => {
    // 로그인 성공 후 이동
    navigate("/dashboard");
  };

  return <button onClick={handleLogin}>로그인</button>;
}

→ 버튼 클릭 등 이벤트 안에서 프로그래밍적으로 경로 변경할 수 있어요.


🧩 중첩 라우트(Nested Routes)


function Dashboard() {
  return (
    <>
      <h1>대시보드</h1>
      <Outlet />
    </>
  );
}

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />}>
          <Route path="profile" element={<Profile />} />
          <Route path="settings" element={<Settings />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}
  • Outlet은 하위 Route를 렌더링하는 자리
  • 중첩 URL: `/dashboard/profile`, `/dashboard/settings`

🧳 URL 파라미터와 useParams 사용법

SPA에서는 URL의 일부를 변수처럼 사용할 수 있습니다.
예를 들어, 게시글 상세 페이지를 구현할 때 이런 식으로 사용해요.

라우트 설정


<Route path="/post/:id" element={<PostDetail />} />

useParams로 URL 값 읽기


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

function PostDetail() {
  const { id } = useParams();
  return <h2>게시글 번호: {id}</h2>;
}
  • :id처럼 경로에 변수를 걸고
  • useParams()로 값을 가져올 수 있어요!

🛣️ 쿼리스트링(Query String) 처리하기

URL에 ?키=값 형태로 데이터가 붙는 걸 **쿼리스트링**이라고 합니다.
React Router에서는 useSearchParams를 사용해서 읽고 쓸 수 있어요.

예시

http://localhost:3000/search?keyword=노미

useSearchParams 사용


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

function SearchPage() {
  const [searchParams, setSearchParams] = useSearchParams();
  const keyword = searchParams.get("keyword");

  return <h2>검색어: {keyword}</h2>;
}

🏃 리다이렉트(redirect) 처리

로그인 상태에 따라 강제로 다른 페이지로 보내야 할 때가 있어요.
그럴 때 useNavigate()로 리다이렉트를 처리합니다.


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

function LoginPage() {
  const navigate = useNavigate();

  const handleSubmit = () => {
    // 로그인 완료 후 메인 페이지로 이동
    navigate("/");
  };

  return <button onClick={handleSubmit}>로그인</button>;
}

🛡️ 인증이 필요한 라우트 보호 (Protected Route)

로그인한 사용자만 접근 가능한 페이지를 만들려면 Route Guard를 구현해야 합니다.

ProtectedRoute 컴포넌트 만들기


function ProtectedRoute({ children }) {
  const isLogin = !!localStorage.getItem("token");
  
  if (!isLogin) {
    return <Navigate to="/login" />;
  }
  
  return children;
}

적용 예시


<Route path="/dashboard" element={
  <ProtectedRoute>
    <Dashboard />
  </ProtectedRoute>
} />

→ 로그인 안 한 사용자는 자동으로 /login으로 이동!


📜 Route 구성 깔끔하게 관리하는 법

페이지가 많아질수록 Routes를 깔끔하게 관리하는 게 중요해요.

routes 배열로 관리


const routes = [
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
  { path: "/login", element: <Login /> },
  { path: "/dashboard", element: <ProtectedRoute><Dashboard /></ProtectedRoute> }
];

map으로 Routes 렌더링


<Routes>
  {routes.map(({ path, element }) => (
    <Route key={path} path={path} element={element} />
  ))}
</Routes>

→ 관리 편하고, 추후 수정할 때도 깔끔!


🧭 라우팅 설계할 때 고려해야 할 점

  • 중첩 구조를 잘 설계하기
  • 권한에 따라 접근 제어
  • 404 Not Found 페이지 설정
  • SEO 최적화 고려 (meta태그 변경 필요)
  • URL 규칙 일관성 유지

404 페이지 처리


<Route path="*" element={<NotFound />} />

→ 모든 경로를 커버하는 “catch-all” 패턴


⚡ 프로그램적 네비게이션 고급 테크닉

앞서 useNavigate()를 배웠지만, 실제 서비스에서는 더 다양한 이동 제어가 필요해요.
특히, replace 옵션을 주면 **히스토리 스택을 새로 덮어쓰기** 때문에 “뒤로 가기” 방지가 가능합니다.

예시: 로그인 후 replace 이동


const navigate = useNavigate();

function afterLogin() {
  navigate("/dashboard", { replace: true });
}

→ 사용자가 로그인 후 뒤로 가기를 눌러도 로그인 페이지로 돌아가지 않게 만듭니다.


🪄 Lazy Loading으로 라우트 최적화

페이지 수가 많아지면 번들 파일이 커져서 로딩이 느려질 수 있어요.
이때 Lazy Loading으로 각 페이지를 나눠서 로드하면 성능이 개선됩니다.

React.lazy 사용법


import { lazy, Suspense } from "react";

const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>로딩 중...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

→ 컴포넌트가 필요한 시점에만 네트워크로 불러와서 성능 최적화!


🎯 Suspense로 로딩 상태 관리하기

Lazy Loading과 함께 Suspense를 사용하면 네트워크 지연 시간 동안 사용자에게 로딩 화면을 보여줄 수 있어요.

커스텀 로딩 컴포넌트


function Loading() {
  return <div>잠시만 기다려주세요...</div>;
}

Suspense 적용


<Suspense fallback={<Loading />}>
  <Routes>...</Routes>
</Suspense>

→ UX가 부드러워지고, 페이지 전환이 자연스러워집니다!


🗺️ 다중 레이아웃(Multiple Layouts) 처리하기

사이트에 따라 홈 레이아웃, 관리자 레이아웃 등 다양한 레이아웃이 필요한 경우가 많아요.
이럴 때 중첩 라우트 + Outlet을 조합하면 깔끔하게 구성할 수 있습니다.

예시 구조


function MainLayout() {
  return (
    <div>
      <Header />
      <Outlet />
      <Footer />
    </div>
  );
}

function AdminLayout() {
  return (
    <div>
      <AdminSidebar />
      <Outlet />
    </div>
  );
}

라우트 설정


<Route path="/" element={<MainLayout />}>
  <Route index element={<Home />} />
  <Route path="about" element={<About />} />
</Route>

<Route path="/admin" element={<AdminLayout />}>
  <Route path="dashboard" element={<Dashboard />} />
</Route>

→ 레이아웃별 구조가 명확하고 관리가 쉬워집니다.


🔀 리다이렉트 전략 실전편

사용자가 특정 조건을 만족하지 않으면 자동으로 다른 페이지로 보내야 할 때도 있습니다.

Navigate 사용


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

function MyPage() {
  const isLogin = false; // 예시
  
  if (!isLogin) {
    return <Navigate to="/login" replace />;
  }

  return <div>마이페이지 콘텐츠</div>;
}
  • replace를 쓰면 브라우저 히스토리에 기록되지 않습니다.

🌐 URL 관리 전략 정리

  • 대문자 대신 소문자 사용
  • 단수형/복수형 규칙 통일 (/user vs /users)
  • 동사 대신 명사 사용 (/create 대신 /new)
  • SEO를 고려해 간결한 URL 사용

→ URL 자체가 설계 철학을 드러냅니다!


🚥 React Router v6 주요 변화 정리

React Router는 v6에서 많은 변화가 있었어요.

주요 변경 사항

  • Switch → Routes로 변경
  • Route element 속성 사용 (children이 아님)
  • useRoutes 훅 추가로 배열 기반 라우팅 가능
  • 중첩 라우트 공식 지원 강화

예시: useRoutes 사용


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

function App() {
  const routing = useRoutes([
    { path: "/", element: <Home /> },
    { path: "/about", element: <About /> }
  ]);

  return routing;
}

→ 컴포넌트 안에서 간결하게 라우트 구성 가능!


📚 마무리하며

React 프로젝트를 만드는 과정에서 **라우팅 시스템을 잘 설계**하는 것은 매우 중요합니다.
단순히 페이지를 이동시키는 것을 넘어서,

  • URL 체계 설계
  • Protected Route로 접근 제어
  • 중첩/동적 라우팅
  • Lazy Loading & Suspense 최적화

까지 고려하면, 훨씬 탄탄하고 유지보수하기 쉬운 웹 애플리케이션을 만들 수 있어요.

이제 여러분도 직접 React Router를 활용해서 SPA를 제대로 구축할 수 있을 거예요! 다음 글에서는 React Router + 인증 상태 + 권한에 따라 메뉴 동적 변경 고급편으로 이어갈게요. 🚀


#ReactRouter #SPA개발 #라우팅구현 #중첩라우트 #ProtectedRoute #LazyLoading #ReactSuspense #리액트실전가이드 #퍼블리셔노미

반응형