react-router-dom은 웹에서 페이지 이동 기능을 구현하기 위한 라이브러리이다.
Routing이란 네트워크간 데이터 전송의 최적 경로를 선택하는 과정이다. 여기서 최적 경로는 최단거리가 될 수도 있고, 가장 빠른 시간에 전달하는 것으로 계산될 수도 있다.
Router란 각기 독립된 네트워크들을 연결시켜주는 장치이다.
간단하게 생각해서 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이 라우팅이다. react-router-dom은 SPA(single page application)에서 선택된 url에 해당하는 데이터를 하나의 페이지에서 렌더링해서 보여주는 라이브러리이다.
설치
- npm
npm install react-router-dom
- yarn
yarn add react-router-dom
React Router는 사용자가 입력한 주소를 감지하는 역할을 하며, 다양한 환경에서 동작할 수 있도록 여러가지 라우터 컴포넌트가 제공된다. 그 중 가장 많이 사용되는 라우터는 BrowserRouter와 HashRouter이다.
우리가 접하고 있는 중 가장 친숙한 url 주소를 감지하는 BrowserRouter 구현 방법에 대해 설명하겠다. 우선 아래 코드와 같이 App의 컴포넌트 최상단을 BrowserRouter 컴포넌트로 감싸주면 된다.
import { BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Header />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/tv" element={<Tv />}></Route>
<Route path="/search" element={<Search />}></Route>
</Routes>
</BrowserRouter>
);
}
여기에서 basename에 입력되는 값은 기본 주소이며, process.env.PUBLIC_URL로 입력하면 작업하는 프로젝트 환경(create-react-app 등)의 이름으로 입력된다.
Routes & Route를 간단하게 설명하자면, Routes는 여러 Routes를 감싸서 유저의 현재 url과 일치하는 Route가 있으면 그것에 해당하는 컴포넌트를 화면에 렌더링하는 개념이다. Route는 path속성에 경로, element속성에는 컴포넌트를 넣어 준다. 여러 라우팅을 매칭하고 싶은 경우 URL 뒤에 *을 사용하면 된다.
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Header />
<Routes>
<Route path="/" element={<Home />}></Route> // (1)
<Route path="/tv/*" element={<Tv />}></Route> // (2)
<Route path="/search" element={<Search />}> // (3)
<Route path=":movieId" element={<Search />}></Route>
<Route path=":tvId" element={<Search />}></Route>
</Route>
<Route path="*" element={<NotFound />}></Route>
</Routes>
</BrowserRouter>
);
}
위 코드에서 2번 Route는 *을 작성해서 /tv로 시작하는 어떤 url이라도(ex. /tv/tvId) 매칭될 수 있게 구현되었다. 또한 3번 Route에서는 /search 뒤에 movieId와 tvId에 해당하는 값이 입력된 경우에만 매칭될 수 있게 구현되었다(Nested Routes).
웹 페이지에서는 원래 링크를 보여줄 때 a태그를 사용한다. 하지만 a태그는 클릭시 페이지를 새로 불러오기 때문에 사용하지 않는다. Link 컴포넌트를 사용하는데, 생김새는 a태그를 사용하지만, History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있다.
import { Link } from "react-router-dom";
<Link to={`/search/${movie.id}`}>
{movie.name}
</Link>
to에 이동할 경로를 입력하는 것을 기본으로 하고, 추가로 state에 object 형태로 값을 입력하여 페이지 이동 시 정보를 함께 전달해줄 수 있다.
useParams
위 함수들은 다음과 같이 사용할 수 있다.
import { useParams, useMatch, useLocation } from "react-router-dom";
const params = useParams();
const match = useMatch(`search/:movieId`);
const location = useLocation();
useEffect(() => {
console.log(params);
console.log(matchs);
console.log(location);
}, []);
위 코드가 실행된 결과는 아래와 같다.
useParams 결과
useMatch 결과
현재 유저의 url과 match url이 같은 경우
현재 유저의 url과 match url이 다른 경우
useLocation 결과
useNavigate는 일반적인 url 이동뿐만 아니라, history 기반으로 url을 이동할 때 사용한다.
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
// 일반적인 절대 경로 url 이동
navigate(`/search/39929?category=movies&keyword=${data.keyword}`)
// 일반적인 상대 경로 url 이동
navigate(`search/39929?category=movies&keyword=${data.keyword}`)
// history 기반 url 이동
navigate(-1) // 한 페이지 뒤로 이동
navigate(2) // 두 페이지 앞으로 이동
URLSearchParams는 url에 쿼리 형태로 입력된 정보를 받아오는데 사용한다. 앞선 useLocation 결과에서 hello 값을 아래와 같이 받아올 수 있다.
import { useLocation } from "react-router-dom";
const location = useLocation();
const srcParams = new URLSearchParams(location.search);
const keyword = srcParams.get("keyword");
또한 set 함수로 쿼리 데이터를 수정할 수 있다.
srcParams.set("category", "tvs");