본문 바로가기
코딩 정보/React

[React] 라우터의 개념과 활용 방법에 대해 알아보자

by 꽁이꽁설꽁돌 2024. 8. 16.
728x90
반응형

목차

     

    라우팅이란?

    라우팅은 기본적으로 네트워크에서 경로를 선택하는 프로세스를 의미한다.

    간단하게 요약하면 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이다.

     

    리액트 라우터의 사용 이유

    SPA 사용자 경험 향상의 목적으로 페이지 전체를 로딩하는 대신 라우팅을 통해 부드러운 화면전환을 목적으로 사용한다.

     

    간단한 사용 방법

    import { createBrowserRouter, RouterProvider } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    const router = createBrowserRouter([
      //경로
      { path: "/", element: <HomePage /> },
      {},
    ]);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    다른 방법

    아래와 같이 사용 가능하다.

    import {
      createBrowserRouter,
      createRoutesFromElements,
      RouterProvider,
      Route,
    } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    import ProductsPage from "./pages/Products";
    
    const routeDefinitions = createRoutesFromElements(
      <Route>
        <Route path="/" element={<HomePage />}></Route>
        <Route path="/products" element={<ProductsPage />}></Route>
      </Route>
    );
    
    const router = createBrowserRouter(routeDefinitions);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    링크로 페이지들 간의 이동 만들기

    아래와 같이 코드를 작성하면 잘 작동은 하지만 서버에 새로운 요청을 주어 모든 자바스크립트 코드를 다시 받아오게 된다,

    function HomePage() {
      return (
        <>
          <h1>My Home Page</h1>
          <p>
            Go to <a href="/products">the list of products</a>
          </p>
        </>
      );
    }
    
    export default HomePage;

     

    따라서 Router의 기능인 Link를 사용해 주면 된다.

    import {Link} from 'react-router-dom';
    function HomePage() {
      return (
        <>
          <h1>My Home Page</h1>
          <p>
            Go to <Link to="/products">the list of products</Link>
          </p>
        </>
      );
    }
    
    export default HomePage;

     

    +NavLink 사용하기

    NavLink를 사용하면 isActive를 제공 해주어 이동되어 있는 페이지의 활성화 여부를 전달 받아 활용할 수 있다.

    import { NavLink } from "react-router-dom";
    import styles from "./MainNavigation.module.css";
    function MainNavigation() {
      return (
        <header className={styles.header}>
          <nav>
            <ul className={styles.list}>
              <li>
                <NavLink
                  to="/"
                  className={({ isActive }) =>
                    isActive ? styles.active : undefined
                  }
                  end
                >
                  Home
                </NavLink>
              </li>
              <li>
                <NavLink
                  to="/products"
                  className={({ isActive }) =>
                    isActive ? styles.active : undefined
                  }
                >
                  Products
                </NavLink>
              </li>
            </ul>
          </nav>
        </header>
      );
    }
    export default MainNavigation;

     

    라우터 layout 만들기

    이런식으로 children속성을 지정해 주면 부모 컴포넌트는 띄어진 상태로 자식 컴포넌트로의 이동이 가능하다.

    import {
      createBrowserRouter,
      createRoutesFromElements,
      RouterProvider,
      Route,
    } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    import ProductsPage from "./pages/Products";
    import RootLayout from "./pages/Root";
    
    const router = createBrowserRouter([
      {
        path: "/",
        element: <RootLayout />,
        children: [
          { path: "/", element: <HomePage /> },
          { path: "/products", element: <ProductsPage /> },
        ],
      },
    ]);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    그리고 어디에 랜더링할지 부모 컴포넌트에서 Outlet으로 위치 지정만 해주면 된다.

    import { Outlet } from "react-router-dom";
    import MainNavigation from "../components/MainNavigation";
    //자녀 라우트 컴포넌트가 어디에 있는지 정의해 주어야 함
    function RootLayout() {
      return (
        <>
          <MainNavigation />
          {/* 여기 위치가 자녀 라우트를 랜더링하는 곳 */}
          <Outlet />
        </>
      );
    }
    export default RootLayout;

     

    에러 페이지 만들기

    아래 코드와 같이 errorElement를 만들어 주면 된다.

    import {
      createBrowserRouter,
      RouterProvider,
    } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    import ProductsPage from "./pages/Products";
    import RootLayout from "./pages/Root";
    import ErrorPage from "./pages/ErrorPage";
    
    const router = createBrowserRouter([
      {
        path: "/",
        element: <RootLayout />,
        //이런식으로 에러가 났을 경우 이 컴포넌트로 이동한다.
        errorElement: <ErrorPage />,
        children: [
          { path: "/", element: <HomePage /> },
          {
            path: "/products",
            element: <ProductsPage />,
          },
        ],
      },
    ]);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    함수를 이용해서 페이지 간의 이동 만들기

    useNavigte를 써주게 되면 함수를 통해 다양한 활용이 가능하다. (ex: setTimeout을 이용한 일정 시간후의 페이지 이동)

    import { Link, useNavigate } from "react-router-dom";
    
    function HomePage() {
      const navigate = useNavigate();
    
      function navigateHandler() {
        navigate('/products');
      }
    
      return (
        <>
          <h1>My Home Page</h1>
          <p>
            Go to <Link to="/products">the list of products</Link>
          </p>
          <p>
            <button onClick={navigateHandler}>Navigate</button>
          </p>
        </>
      );
    }
    
    export default HomePage;

     

    동적 라우팅을 이용하여 params 전달하기

     

    ProductsPage.jsx

    동적으로 페이지에 접근하는 링크를 만들어 준다.

    import { Link } from "react-router-dom";
    
    const PRODUCTS = [
      { id: "p1", title: "Product 1" },
      { id: "p2", title: "Product 2" },
      { id: "p3", title: "Product 3" },
    ];
    function ProductsPage() {
      return (
        <>
          <h1>The Products Page</h1>
          <ul>
            {PRODUCTS.map((prod) => (
              <li key={prod.id}>
                <Link to={`/products/${prod.id}`}>{prod.title}</Link>
              </li>
            ))}
          </ul>
        </>
      );
    }
    
    export default ProductsPage;

     

    productDetailPage.jsx

    useParams를 통해 전달 받은 productId를 사용한다.

    import { useParams } from "react-router-dom";
    function ProductDetailPage() {
      const params = useParams();
    
      return (
        <>
          <h1>Product Details!</h1>
          <p>{params.productId}</p>
        </>
      );
    }
    
    export default ProductDetailPage;

     

    Router.jsx

    /:productId로 params를 전달해 준다.

    import { createBrowserRouter, RouterProvider } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    import ProductsPage from "./pages/Products";
    import RootLayout from "./pages/Root";
    import ErrorPage from "./pages/ErrorPage";
    import ProductDetailPage from "./pages/ProductDetail";
    
    const router = createBrowserRouter([
      {
        path: "/",
        element: <RootLayout />,
        errorElement: <ErrorPage />,
        children: [
          { path: "/", element: <HomePage /> },
          {
            path: "/products",
            element: <ProductsPage />,
          },
          {
            path: "products/:productId",
            element: <ProductDetailPage />,
          },
        ],
      },
    ]);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    절대 경로와 상대 경로의 차이

    상대 경로는 다음과 같이 바꾸어 주어야 한다. 

    import { createBrowserRouter, RouterProvider } from "react-router-dom";
    import HomePage from "./pages/HomePage";
    import ProductsPage from "./pages/Products";
    import RootLayout from "./pages/Root";
    import ErrorPage from "./pages/ErrorPage";
    import ProductDetailPage from "./pages/ProductDetail";
    
    const router = createBrowserRouter([
      {
        //앞에 /있으면 절대경로
        //root를 통해 이동한다.
        path: "/root",
        element: <RootLayout />,
        errorElement: <ErrorPage />,
        children: [
        	//부모격의 페이지
          { path: "", element: <HomePage /> },
          
          //형제 관계의 페이지
          {
            path: "products",
            element: <ProductsPage />,
          },
          {
            path: "products/:productId",
            element: <ProductDetailPage />,
          },
        ],
      },
    ]);
    
    function Router() {
      return <RouterProvider router={router}></RouterProvider>;
    }
    
    export default Router;

     

    import { Link } from "react-router-dom";
    
    const PRODUCTS = [
      { id: "p1", title: "Product 1" },
      { id: "p2", title: "Product 2" },
      { id: "p3", title: "Product 3" },
    ];
    function ProductsPage() {
      return (
        <>
          <h1>The Products Page</h1>
          <ul>
            {PRODUCTS.map((prod) => (
              <li key={prod.id}>
                 {/* /products에서 상대적으로 이동하기 때문에 앞에 부분은 없애준다 */}
                <Link to={`${prod.id}`}>{prod.title}</Link>
              </li>
            ))}
          </ul>
        </>
      );
    }
    
    export default ProductsPage;

     

    relative의 설정 여부에 따라 경로의 제어가 바뀐다.

     

    path로 하면 현재의 경로에서 한 세그먼트만 제거하는데 id가 사라져 형제 페이지로 가게 된다.

    route로 하면 모든 세그먼트를 제거하여 homepage로 되돌아 가게 된다.

    import { useParams, Link } from "react-router-dom";
    function ProductDetailPage() {
      const params = useParams();
    
      return (
        <>
          <h1>Product Details!</h1>
          <p>{params.productId}</p>
          <p>
            <Link to={".."} relative="path">Back</Link>
          </p>
        </>
      );
    }
    
    export default ProductDetailPage;

     

    반응형