React-router-dom

박찬영·2024년 2월 12일
0
post-thumbnail

React-router-dom

라우팅

라우팅(Routing)은 웹 애플리케이션에서 사용자가 다른 페이지로 이동할 때 해당 페이지에 맞는 컴포넌트를 렌더링하는 과정을 말합니다.
일반적으로 사용자가 URL을 입력하거나 링크를 클릭하면, 해당 URL의 경로와 쿼리를 분석하여 어떤 컴포넌트를 보여줄지 결정하고, 그에 따라 화면이 업데이트됩니다.

이러한 라우팅은 SPA(Single Page Application)를 구현하는 데 중요한 역할을 합니다.
SPA는 페이지를 새로고침하지 않고도 필요한 데이터만 가져와 화면을 업데이트할 수 있기 때문에, 사용자 경험을 향상시키고 서버의 부담을 줄일 수 있습니다.
또한, 브라우저의 뒤로 가기/앞으로 가기 버튼과 같은 브라우저 기능과의 호환성을 유지하기 위해서도 라우팅이 필요합니다.

React에서는 주로 react-router 라이브러리를 사용하여 라우팅을 구현합니다.
이 라이브러리를 사용하면 URL에 따라 다른 컴포넌트를 렌더링하고, URL을 변경하여 다른 화면을 보여주는 등의 기능을 쉽게 구현할 수 있습니다.
이를 통해 사용자가 웹 애플리케이션을 자연스럽게 탐색할 수 있도록 도와줍니다.

SPA

SPA (Single Page Application)는 하나의 웹 페이지로 이루어진 애플리케이션입니다.
기존의 웹 페이지는 사용자가 새로운 페이지로 이동할 때마다 서버로부터 새로운 HTML, CSS, 그리고 JavaScript 파일을 다운로드하여 화면을 갱신합니다.
하지만 SPA는 초기 페이지 로딩 이후에는 필요한 데이터만 서버로부터 비동기적으로 가져와 동적으로 페이지를 갱신합니다.

주로 SPA는 AJAX 기술을 활용하여 데이터를 비동기적으로 요청하고, JavaScript를 사용하여 동적으로 화면을 업데이트합니다.
이를 통해 사용자가 애플리케이션 내에서 상호작용할 때 새로운 페이지를 로드하지 않고도 빠르게 데이터를 가져오고 화면을 갱신할 수 있습니다.

SPA는 사용자에게 더 나은 경험과 빠른 응답 시간을 제공할 수 있습니다.
또한, 모바일 기기와 같은 저사양 기기에서도 빠르게 작동하여 모바일 애플리케이션에 적합합니다.
그러나 SPA를 구현할 때는 검색 엔진 최적화(SEO) 문제와 초기 페이지 로딩 속도에 대한 고려가 필요합니다.

리액트 라우터 기본 사용법


npm install react-router-dom

리액트 라우터를 프로젝트에 적용할 때, 우리는 src/index.jsx 파일에서 BrowserRouter라는 컴포넌트를 사용합니다.
이 컴포넌트는 웹 애플리케이션에서 페이지를 새로 불러오지 않고도 주소를 변경할 수 있게 해주며, 현재 주소의 경로와 관련된 정보를 리액트 컴포넌트에서 사용할 수 있도록 도와줍니다.

간단히 말해서, BrowserRouter는 우리가 만든 리액트 애플리케이션을 웹 브라우저의 URL과 연결해주는 역할을 합니다.
이를 통해 사용자가 URL을 변경하거나 링크를 클릭할 때마다 적절한 컴포넌트를 렌더링할 수 있습니다.
React-router-dom 은 HTML5의 History API를 사용하여 페이지 전환을 부드럽게 처리하고, 이를 통해 SPA(Single Page Application)의 경험을 제공합니다.


import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>  
    <BrowserRouter>	   // <--- 감싸주기..
      <App />
    </BrowserRouter>   // <--- 
  </React.StrictMode>
);

reportWebVitals();
                            

그리고 우리가 해야할 일은 여러 페이지로 구성된 웹앱을 만들기 위해서는 각 페이지들을 만들어야 합니다.
예시로 Home, About 페이지를 만들어보겠습니다.


// src/pages/Home.tsx
const Home = () => {
  return (
    <div>
      <h1>Home</h1>
      <p>Home 페이지 입니다.</p>
    </div>
  );
}

// src/pages/About.tsx
const About = () => {
  return (
    <div>
      <h1>About</h1>
      <p>About 페이지 입니다.</p>
    </div>
  );
}

그 다음으로 사용자의 브라우저 주소 경로에 따라 우리가 원하는 페이지를 보여주려면 Route라는 컴포넌트를 통해 라우트 설정을 해줘야 합니다.


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

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  );
}

export default App;

여기까지가 react-router-dom 의 가장 기본적인 사용법 입니다.

Link 컴포넌트는 React Router에서 제공하는 라우팅을 위한 중요한 도구입니다.
이 컴포넌트는 웹 애플리케이션에서 다른 페이지로 이동할 때 페이지를 새로고침하지 않고도 애플리케이션 상태를 유지하면서 이동할 수 있게 해줍니다.

일반적으로 웹 페이지에서는 링크를 클릭하면 해당 링크의 URL로 이동하게 됩니다.
그러나 이렇게 하면 페이지가 새로 고쳐지고 애플리케이션의 상태가 초기화될 수 있습니다.
Link 컴포넌트는 이러한 문제를 해결하기 위해 사용됩니다.
a 태그와 비슷한 클릭 이벤트를 제공하면서도 페이지를 새로 고치지 않고 브라우저의 주소창의 URL을 변경할 수 있습니다.

예를 들어, Home 페이지에서 About 페이지로 이동하려면 Link 컴포넌트를 사용할 수 있습니다.
이때 Link 컴포넌트의 to 속성을 사용하여 이동하고자 하는 페이지의 경로를 지정할 수 있습니다.
이 경로는 문자열 형태로 전달되며, React Router는 이를 해석하여 해당 페이지를 렌더링합니다.
이렇게 함으로써 페이지 간의 이동이 부드럽게 이루어지고 애플리케이션의 상태가 유지될 수 있습니다.


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

const Home = () => {
  return (
    <div>
      <h1>Home</h1>
      <p>Home 페이지 입니다.</p>
      <Link to="/about">About page</Link>  // <-- <Link to=""> </Link>
    </div>
  );
}

URL 파라미터와 쿼리스트링

웹 애플리케이션에서 페이지 주소를 정의할 때 때로는 유동적인 값을 사용해야 하는 경우가 있습니다.
이때 사용되는 방법으로는 URL 파라미터와 쿼리스트링이 있습니다.

  1. URL 파라미터(Parameter)

    • URL 경로 뒤에 슬래시(/)로 구분된 값들을 말합니다.
    • 예를 들어, https://example.com/products/123과 같은 URL에서 "123"은 products 페이지에서 사용될 수 있는 파라미터입니다.
    • 이러한 파라미터는 브라우저의 주소창에서 직접 수정하여 값을 변경할 수 있습니다.
    • React Router에서는 useParams 훅을 사용하여 URL 파라미터를 추출할 수 있습니다.
  2. 쿼리스트링(Query String)

    • URL 경로와 물음표(?)로 구분된 값들을 말합니다.
    • 예를 들어, https://example.com/search?name=mapple&category=games와 같은 URL에서 name=mapple과 category=games는 검색 결과를 필터링하는 데 사용될 수 있는 쿼리스트링 매개변수입니다.
    • 쿼리스트링은 JavaScript 코드에서 동적으로 생성하고 사용할 수 있으며, 주소창에서도 직접 수정할 수 있습니다.
    • 보안에 민감한 데이터는 쿼리스트링으로 전송하지 않는 것이 좋습니다.
    • React Router에서는 useLocation 훅을 사용하여 현재 URL 정보를 담은 객체를 반환하고, 이 객체의 search 프로퍼티를 통해 쿼리스트링 값을 추출할 수 있습니다.

URL 파라미터와 쿼리스트링은 라우팅 및 데이터 전달에 유용하게 사용됩니다.
이를 활용하여 웹 애플리케이션의 동적인 요구사항을 충족시킬 수 있습니다.

URL 파라미터 예시

불러오기


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

// 만약 https://example.com/products/123 로 접속했다면 ..

const ProductDetail = () => {
  // useParams 훅을 사용하여 URL 파라미터를 추출합니다.
  const { id } = useParams();

  return (
    <div>
      <h2>Product Detail</h2>
      <p>Product ID: {id}</p>    // Product ID: 123
    </div>
  );
};

설정하기
내 Route 의 path 에는 : 을 붙이고 원하는 이름을 입력해 주면 됩니다.


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

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/products/:id" element={<ProductDetail />} />
    </Routes>
  );
}

export default App;

쿼리스트링 예시


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

// localhost:3000/?detail=true&page=2

const MyComponent = () => {
  const [searchParams, setSearchParams] = useSearchParams();

  // 쿼리스트링 값을 읽어옴
  const query = searchParams.get("detail");

  return (
    <div>
      <p>Query: {query}</p>  // Query: true
    </div>
  );
};

중첩 라우트

중첩된 라우트(Nested Route)는 리액트에서 라우팅을 구성하는데 사용되는 개념입니다.
이는 라우트 안에 또 다른 라우트를 중첩하여 구성하는 것을 의미합니다.
쉽게 말해, 한 페이지 안에서도 여러 개의 하위 페이지로의 이동을 설정할 수 있는 것입니다.

중첩 라우트를 사용하지 않았을 경우


// src/pages/Articles.tsx
import { Link } from "react-router-dom";

const Articles = () => {
  return (
    <ul>
      <li>
        <Link to="/articles/1">게시글 1</Link>
      </li>
      <li>
        <Link to="/articles/2">게시글 2</Link>
      </li>
      <li>
        <Link to="/articles/3">게시글 3</Link>
      </li>
    </ul>
  );
}

// src/pages/Article.tsx
import { useParams } from "react-router-dom";

const Article = () => {
  const { id } = useParams();
  return (
    <div>
      <h2>게시글 {id}</h2>
    </div>
  );
}

// App.jsx
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
      <Route path="/articles" element={<Articles />} />
      <Route path="/articles/:id" element={<Article />} />
    </Routes>
  );
}

이렇게 게시글 페이지 에서 하위 게시글로 이동하는 페이지를 만들었습니다.
그리고 App.jsx 에서 params 에 따라 설정해준 값대로 페이지가 렌더링 됩니다.

중첩 라우트를 사용했을 경우


// src/pages/Article.tsx
import { Outlet ,useParams } from "react-router-dom";

const Article = () => {
  const { id } = useParams();
  return (
    <div>
      <Outlet/> // <-- Articles 페이지를 보여줍니다.
      <h2>게시글 {id}</h2>
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/profiles/:username" element={<Profile />} />
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
    </Routes>
  );
}

중첩 라우트의 장점은 각각의 하위 페이지를 별도의 라우트로 구성하여 관리할 수 있으며, 이는 코드의 가독성과 유지보수성을 높여줍니다.

공통 레이아웃

공통 레이아웃 컴포넌트는 여러 페이지에서 반복적으로 사용되는 레이아웃을 구현할 때 유용한 컴포넌트입니다.
이 컴포넌트는 모든 페이지에서 공통적으로 사용되는 요소들을 포함하고 있으며, 각 페이지의 내용을 감싸서 일관된 디자인과 레이아웃을 제공합니다.
주로 헤더, 푸터, 사이드바 등의 요소들을 포함하며, 페이지 간의 전환 시에도 이 요소들이 유지되어 일관된 사용자 경험을 제공합니다.


// src/pages/Navbar.jsx
import { Outlet } from "react-router-dom";

const Navbar = () => {

  return (
    <div>
      <p>Navbar 입니다.</p>
      <Outlet/>
    </div>
  )
}
function App() {
  return (
    <Routes>
      <Route element={<Navbar />}>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profiles/:username" element={<Profile />} />
      </Route>
      <Route path="/articles" element={<Articles />}>
        <Route path=":id" element={<Article />} />
      </Route>
    </Routes>
  );
}

이렇게 설정을 하면 Home, About, Profile 페이지는 Navbar 컴포넌트에서 설정한 Outlet 안에 나타나게 되어 해당 페이지는 항상 <p>Navbar 입니다.</p> 가 포함되게 됩니다.

useNavigate

보통, <Link> 컴포넌트를 사용하여 특정 경로로 이동하는 것과 달리, useNavigate를 사용하면 URL을 조작할 수 있습니다.
이 Hook을 사용하면 현재 URL을 기반으로 새 URL로 이동하는 함수를 반환합니다.
이 함수를 호출하면 URL이 변경되며, 해당 URL에 대한 새로운 페이지가 렌더링됩니다. 이 함수는 어떤 조건에 따라 다른 페이지로 이동하는 경우 등에 사용할 수 있습니다.

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

const Home = () => {
  const naviagate = useNavigate();
  
  const goAbout = () => {
    navigate("/about")
  }
  
  return (
    <div>
      <button onClick={goAbout}>About 페이지 이동</button>
    </div>
  )
}

이 외에도 전 페이지로 이동하는 navigate(-1) , 특정 페이지로 이동한뒤 그 전 페이지의 기록을 삭제하는 navigate("/about", { replace : true }) 등이 있습니다.

NavLink 컴포넌트는 Link와 같이 클릭하면 경로를 변경할 수 있는 요소입니다.
하지만 NavLink는 Link와 달리 현재 경로와 일치하는 경우 자동으로 스타일을 적용할 수 있습니다.

import { NavLink, Outlet } from "react-router-dom";

export default function Articles() {
  const activeStyle = {
    color: "green",
    fontSize: 21,
  };

  return (
    <div>
      <Outlet />
      <ul>
        <li>
          <NavLink
            to="/articles/1"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 1
          </NavLink>
        </li>
        <li>
          <NavLink
            to="/articles/2"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 2
          </NavLink>
        </li>
        <li>
          <NavLink
            to="/articles/3"
            style={({ isActive }) => (isActive ? activeStyle : undefined)}
          >
            게시글 3
          </NavLink>
        </li>
      </ul>
    </div>
  );
}

Navigate 컴포넌트는 조건부로 페이지를 전환하기 위해 사용됩니다.
주로 사용자의 인증 상태나 특정 조건에 따라 페이지 전환이 필요한 경우에 활용됩니다.
예를 들어, 사용자가 로그인하지 않은 상태에서 접근할 수 없는 페이지에 접근하려고 할 때, Navigate 컴포넌트를 사용하여 조건부로 로그인 페이지로 리다이렉션할 수 있습니다.


// src/pages/MyPage.tsx
import { Navigate } from "react-router-dom";

export default function MyPage() {
  const isLogin = false;

  if (!isLogin) {
    return <Navigate to="/login" replace={true} />;
  }

  return <div>마이 페이지</div>;
}
profile
오류는 도전, 코드는 예술

0개의 댓글

관련 채용 정보