< 참고 링크 >
사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이라고 생각할 수 있습니다.
이 글에서는 리액트에서 라우팅 관련 라이브러리가 많은데, 이 중 가장 많이 사용하는 리액트 라우터(React Router)를 사용해보겠습니다.
사용자가 입력한 주소를 감지하는 역할.
여러 환경에서 동작할 수 있도록 여러 종류의 라우터 컴포넌트를 제공합니다.
이 중 가장 많이 사용하는 라우터 컴포넌트는
BrowserRoute
와 HashRouter
입니다.
리액트 개발 폴더 쉘에서 다음 명령어를 이용하여 리액트 라우터 돔을 설치해줍니다.
$ npm install react-router-dom
라우터를 사용하기에 먼저 쇼핑몰이라고 가정하여 샘플 페이지를 만들어보겠습니다.
(App, 헤더, 메인 페이지, 상품 상세 페이지)
import React, { Component } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Header from './Header'; import Main from './Main'; import Product from './Product'; const App = () => { return ( <div className='App'> <Header /> <Main /> <Product /> </div> ); } export default App;
import React from 'react'; function Header(props) { return ( <> <h1>헤더입니다.</h1> </> ); } export default Header;
import React from 'react'; const Main = (props) => { return ( <> <h3>안녕하세요. 메인페이지 입니다.</h3> </> ); }; export default Main;
import React from 'react'; const Product = (props) => { return ( <> <h3>상품 페이지입니다.</h3> </> ); } export default Product;
다음과 같이 App.js에 컴포넌트를 조건없이 모두 넣어서 모든 페이지의 값이 나타납니다.
이를 해결하기 위해 Router
를 활용해보겠습니다.
BrowserRouter를 사용할 것이기 때문에, <BrowserRouter> 태그로 컴포넌트를 감싸줍니다.
Hedaer는 모든 URL에서 공통으로 들어갈 내용이므로 Component로 최상단에 놓아줍니다.
import React, { Component } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Header from './Header'; import Main from './Main'; import Product from './Product'; const App = () => { return ( <div className='App'> <BrowserRouter> <Header /> <Main /> <Product /> </BrowserRouter> </div> ); }; export default App;
<Routes> 컴포넌트는 여러 Route를 감싸서 그 중 규칙이 일치하는 단 하나만을 렌더링 시켜주는 역할을 합니다.
<Route>는
여러 라우팅을 매칭하고 싶다면 URL뒤에 *를 사용하면 됩니다.
"/"로 접근 시 메인 페이지(Main.js)를 보여줍니다.
"/product/[상품 번호]"로 접근 시 상품 상세페이지(Product.js)를 보여줄 것입니다.
import React, { Component } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Header from './Header'; import Main from './Main'; import Product from './Product'; const App = () => { return ( <div className='App'> <BrowserRouter> <Header /> <Routes> <Route path="/" element={<Main />}></Route> <Route path="/product/*" element={<Product />}></Route> </Routes> </BrowserRouter> </div> ); }; export default App;
그럼 다시 렌더링을 해본다면
path="/" 로 지정했던 main페이지만 보이게 됩니다.
URL에 "/product" 값을 추가한다면
path:"/product"로 설정했던 상품 페이지가 보여집니다.
일반 HTML에서는 링크를 보여줄 때 a태그에 href값을 넣어 사용합니다.
하지만, a태그는 클릭 시 페이지를 새로 불러오기 때문에 사용하지 않습니다.
이를 해결하기 위해 Link 컴포넌트를 사용합니다.
생김새는 a태그를 사용하지만, History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있습니다.
import { Link } from 'react-router-dom' ... <Link to="[경로]">링크명</Link>
링크에 잘못된 URL을 입력하여 접근하는 경우
보여주고 싶은 페이지를 정의
import React from 'react'; const NotFound = () => { return ( <div> 404 Error </div> ); }; export default NotFound;
URL에 정의되지 않는 값을 넣으면 다음과 같이 렌더링 됩니다.
파라미터, 쿼리 스트링을 통해 유동적으로 동작할 수 있습니다.
상품이 100가지가 있는데 이 100개의 페이지를 하나씩 설정해주기엔 비효율적입니다. 이를 해결하기 위해 사용합니다.
/product/:productId 와 같이 경로에 :를 사용하여 설정합니다.
URL 파라미터가 여러 개인 경우 /product/:prodcutId/:productName 과 같은 형태로 설정 가능합니다.
다음과 같이 사용하는 컴포넌트를 추가하여 사용합니다.
import { useParams } from 'react-router-dom' const [파라미터명] = useParams();
productId를 파라미터로 받을 수 있도록 코드를 추가합니다.
import React, { Component } from 'react'; import { BrowserRouter, Routes, Route } from 'react-router-dom'; import Header from './Header'; import Main from './Main'; import Product from './Product'; import NotFound from './NotFound'; const App = () => { return ( <div className='App'> <BrowserRouter> <Header /> <Routes> <Route path="/" element={<Main />}></Route> <Route path="/product/:productId" element={<Product />}></Route> {/* 엘리먼트의 상단에 위치하는 라우트들의 규칙을 모두 확인하고, 일치하는 라우트가 없다면 이 라우트가 화면에 나타나게 됩니다. */} <Route path="*" element={<NotFound />}></Route> </Routes> </BrowserRouter> </div> ); }; export default App;
useParams를 통해 App.js에 추가한 productId를 받아 활용 가능합니다.
import React from 'react'; import { useParams } from 'react-router-dom'; const Product = (props) => { const { productId } = useParams(); return ( <> <h3>{productId}번 상품 페이지입니다.</h3> </> ); } export default Product;
URL에 :productId에 입력된 값을 가져와 페이지에서 그대로 productId를 사용합니다.
useLocationm useSearchParams도 개발 시 활용 가능할 것 같아 간단히 정리
Link 컴포넌트를 사용하지 않고 다른 페이지로 이동해야 하는 경우, 뒤로가기 등에 사용하는 Hook입니다.
replace 옵션을 사용하면 페이지를 이동할 때 히스토리를 남기지 않습니다.
import React from 'react'; import { useParams } from 'react-router-dom'; import { useNavigate } from 'react-router-dom'; const Product = () => { const productId = useParams().productId; const navigate = useNavigate(); return ( <> <h3>{productId}번 상품 페이지 입니다.</h3> <ul> <li><button onClick={() => navigate(-2)}>Go 2 pages back</button></li> <li><button onClick={() => navigate(-1)}>Go back</button></li> <li><button onClick={() => navigate(1)}>Go forward</button></li> <li><button onClick={() => navigate(2)}>Go 2 pages forward</button></li> <li><button onClick={() => navigate('/')}>Go Root</button></li> <li><button onClick={() => navigate('/', {replace: true})}>Go Root</button></li> </ul> </> ); } export default Product;