React- React Router Dom

민찬홍·2024년 2월 4일

React

목록 보기
1/1

Routing?

라우팅은 기본적으로 네트워크에서 경로를 선택하는 프로세스를 의미한다.
조금 풀어서 얘기하면, 다양한 주소의 요청이 들어왔을 때 각각 맞는 콘텐트로 이동시켜 주는 작업이라고 볼 수 있다.

React-Router-Dom을 사용하는 이유

혹자는 그렇게 생각할 것이다. 그냥 a태그가 있으니 이거로 이동해도 괜찮은데, 굳이 라우터를 따로 정의하고 사용해야 하는 이유가 있나.

사용 이유를 생각해보면 SPA 사용자 경험 향상의 목적이 있다고 할 수 있다.

그냥 a태그를 사용하면 페이지 전체가 새로 로딩된다. 따라서 라우팅을 통해 부드러운 화면 전환을 유도하는 것이다.

Router 종류

HashRouter

URL의 해쉬(#) 값을 이용하는 라우터

다음과 같은 특징을 가진다.

  • 주소에 해쉬(#) 가 붙는다.
  • 검색 엔진이 읽지 못한다.
  • 별도의 서버 설정을 하지 않더라도 새로고침 시 오류가 발생하지 않는다. 이는 해시 라우터가 해쉬(#) 뒤에 붙은 값은 브라우저에서만 관리하고(라우팅사실을 서버는 모름) 서버는 기본 url로 서버에 데이터를 요청하기 때문이다.
  • history API를 사용하지 않기 때문에 동적 페이지에서 불러온다.

BrowserRouter

  • history API를 사용한다.
  • 별도의 서버 설정이 없다면 새로고침 시 404에러가 발생한다.

    서버에서는 기본 라우트'/'의 정보만 저장되어 있고, 이외의 모든 하위 라우팅은 이 default 경로를 통해 이루어지기 떄문에 이 경로를 제외하고는 서버에서 인식하지 못한다. 만일 필요하다면 해당 주소와 그에 맞는 페이지를 서버에 알려주어야 한다. 그런게 아니라면 일반적으로는 '/*' 의 경로로 접근 시 서버에는 '/'로 리다이렉션 해주면 된다.

  • 큰 프로젝트에 적합

서버가 존재하고 , SEO가 필요한 프로젝트라면 BrowserRouter를 사용하는 것이 좋고, 그 외에 개인적인 프로젝트라면 HashRouter를 사용해도 괜찮다.

React-Router-Dom 세팅하기

설치 방법은 구글링을 통해 많은 자료를 얻을 수 있으니 생략하겠다.

import { BrowserRouter, Routes, Route } from 'react-router-dom'

가장 많이 사용되는 모듈 3가지다.

BrowserRouter

  • history API를 활용해 history 객체를 생성
  • history API는 내부적으로 stack 자료구조의 형태를 띄기 때문에 사용자가 방문한 url 기록들을 차곡차곡 쌓는 형태로 저장해둔다.
  • 라우팅을 진행할 컴포넌트 상위에 BrowserRouter 컴포넌트를 생성하고 감싸주어야 한다.

Route

  • 현재 브라우저의 location 상태에 따른 element를 렌더링 한다.
  • Route.element: 조건이 맞을 때 렌더링할 element, <Element /> 의 형식으로 전달된다.
  • Route.path: 현재 path값이 url과 일치하는지 확인해 해당 url 에 매칭된 element를 렌더링해준다.

Routes

  • 모든 Route의 상위 경로에 존재해야 하며, location 변경 시 하위에 있는 모든 Route를 조회해 현재 location과 맞는 Route를 찾아준다.

Router는 다음과 같은 형식으로 설정해준다.

const Router = () => {
  return (
    <BrowserRouter>
        <Routes>
          <Route path="/" element={<GalleryPage />} />
          <Route path="/gallery" element={<DetailCardPage />}>
            <Route path=":cardId" element={<DetailCard />} />
          </Route>
        </Routes>
    </BrowserRouter>
  );
};

위와 같은 방식으로 Router 컴포넌트를 생성해 준 다음

import Router from "./Router";

const App = () => (
  <>
      <Router />
  </>
);

export default App;

상위 렌더링 요소에 컴포넌트를 붙여준다.

Link 컴포넌트는 라우터 내에서 직접적으로 페이지 이동을 하고자 할 때 사용되는 컴포넌트다.

import React from 'react';
import {Link} from 'react-router-dom';

function Nav(){
  return (
    <div>
      <Link to='/'> Home </Link>
      <Link to='/about'> About </Link>
    </div>
  );
}

export default Nav;

위와 같은 방식으로 간단하게 to 속성에 경로를 넣어주는 방식으로 사용한다. Link의 특징은 다음과 같다.

  1. Relative
  • 계층 구조에 상대적이다.
  • 상대 경로 표현이 가능하므로, ./.. 과 같은 표현도 사용이 가능하다.
  1. preventScrollReset
  • 페이지 중간에 있는 컨텐츠 내부에서 tab 목록을 누르는 것과 같은 시도를 할 때, 기존의 Link 컴포넌트 였다면 클릭 시 스크롤이 초기화되어 페이지 가장 위로 이동하게 된다.
  • 그러나 이 속성을 true로 설정해주면 이를 방지할 수 있다.
  1. state
  • useLocation 훅과 연계하여 특정 state를 넘겨주는 것도 가능하다.
<Link to="new-path" state={{ some: "value" }} />

let { state } = useLocation();

중첩 라우팅

특정 페이지 내에서 하위 페이지를 만들 수 있고, 해당 페이지마다 경로를 이용한 데이터 전달도 가능하다.

또한 중첩 라우팅을 구현할 경우 해당 하위 페이지 이외에는 컨텐츠가 바뀌지 않는다.

<Route path="/about" element={<About />}>
  <Route path="location" element={<Location />}></Route>
</Route>

라우터 내부에 위와 같은 자식 요소 Route를 만들어준다. 이렇게만 설정해도 라우터 내부적으로는 /about 주소 하위에 /location 이라는 하위 라우팅이 되었다고 판단한다. 따라서 우리가 /about/location 으로 주소를 이동할 경우 주어진 Location 컴포넌트가 렌더링 되는 것이다.

물론 라우터에서 위와 같이 설정한 것만으로는 아무 변화가 안생긴다.

실제로 해당 라우팅이 발생하는 부모 요소인 About 페이지에 하위 라우팅 발생 시 컴포넌트를 렌더링할 자리를 명시해주어야 하기 떄문이고, 이때 사용되는 것이 Outlet 컴포넌트이다.

import { Outlet } from 'react-router-dom';

function About() {
  return (
    <div>
      <div>
        <h2>여기는 About 페이지입니다.</h2>
        <p>대충 쇼핑몰 페이지라는 뜻</p>
      </div>
      <Outlet />
    </div>
  );
}

이처럼 About 컴포넌트 내부에 Outlet 컴포넌트를 렌더링 해주면 라우터에서 이를 인식하고 Outlet 자리에 Location 컴포넌트를 렌더링하게 되는 것이다.

Outlet 없이 중첩 라우팅 구현하기

우선 라우터에서 중첩 라우팅을 하는 주소에 다음과 같이 * 를 추가해주어 중첩 라우팅이 발생할 주소임을 명시해준다.

<Routes>
  <Route path="/" element={<Home />}></Route>
  <Route path="/about/*" element={<About />}></Route>
  <Route path="/products" element={<Products />}></Route>
</Routes>

이후 해당 About 컴포넌트에서 본래 Outlet이 들어가있던 자리에 마치 라우터를 구현한 것처럼 중첩 라우팅을 전달해주면 된다.

function About() {
  return (
    <div>
      <div>
        <h2>여기는 About 페이지입니다.</h2>
        <p>대충 쇼핑몰 페이지라는 뜻</p>
      </div>
      <Routes>
        <Route path="/location" element={<Location />}></Route>
      </Routes>
    </div>
  );
}

Params

주소 경로 내부에 특정 데이터를 넣어 전달하는 것이다. url 파라미터와 쿼리스트링으로 나뉜다

url 파라미터

<Route path="/new/:id" element={<NewId />} />

쿼리스트링

?,& 을 기준으로 key와 value를 나눠 데이터를 전달받는다. 이렇게 전달 받은 값은 이후 useLocation훅을 통해 추출하고 사용할 수 있다.

이전까지는 직접 추출하여 사용해야 했지만, useSearchParams 를 사용하면 쉽게 해결할 수 있다.

useParams

위에 말한 것처럼 url 파라미터를 조회할 때 사용된다.

import React from 'react';
import { useParams } from 'react-router-dom';

const NewId = () => {
  let { id } = useParams();

  return (
    <div className="test">
      <p>현재 유저의 아이디는 { id } 입니다.</p>
    </div>
  )
}

export default NewId;

이처럼 http://hello.com/new/1234주소로 이동하여 렌더링된 NewId 컴포넌트 내부에서 useParams 를 이용해 아이디를 받을 수 있다.

useSearchParams

위의 언급대로 쿼리스트링을 추출하는 데 사용된다.

const [serchParams, setSearchParams] = useSearchParams();

값을 읽어오는 메서드

searchParams.get(key): 특정한 key의 value를 가져오는 메서드, 해당 key의 value가 두개이상이라면 처음 값을 반환한다.
searchParams.getAll(key): 특정 key에 해당되는 모든 value를 가져온다.

값 변경 메서드

searchParams.set(key,value): 인자로 전달한 key값을 value로 설정한다. 만일 기존에 존재하는 value면 덮어씌운다.
searchParams.append(key,value): 추가한다.

profile
백엔드 개발자를 꿈꿉니다

0개의 댓글