본문 바로가기

javaScript&jQurey/REACT

[React] 6. React Router (리액트 라우터) 사용하기

 

6. [React] 6. React Router (리액트 라우터) 사용하기

 

이번 포스팅은 [ React에서 페이지 이동 처리 하는 방법 입니다. : ) 

 

 

 

우리가 흔히 말하는 "페이지 이동"이라는 기능을 리액트에서는 리액트 라우터를 통해 처리할 수 있다.
라우팅이 무엇인지 간단하게 살펴보자.

1. 라우팅이란?

 - 간단하게 생각 하자면 사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이라고 생각할 수 있다.
 - 리액트에서는 라우팅 관련 라이브러리가 많이 있는데, 이중 가장 많이 쓰이는 리액트 라우터(React Router)를 사용해보려 한다.

※ SPA, SSR, SSG 등의 대한 개념을 어느정도 갖춘 상태에서 다음 내용을 진행하는것을 추천 한다.

리액트는 SPA (Single Page Application) 방식
 - 기존 웹 페이지 처럼(MPA 방식) 여러개의 페이지를 사용, 새로운 페이지를 로드하는 방식이 아니다.
 - 새로운 페이지를 로드하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가진다.

React-Router는 신규 페이지를 불러오지 않는 상황에서 각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링 해주는 라이브러리 라고 볼 수 있다.

 

2. 리액트 라우터(React Router)

 - 사용자가 입력한 주소를 감지하는 역할을 하며, 여러 환경에서 동작할 수 있도록 여러 종유의 라우터 컴포넌트를 제공한다.
 - 이중 가장 많이 사용하는 라우터 컴포넌트는 BrowserRouter와 HashRouter이다.

 

1) 종류

 - BrowserRouter : HTML5를 지원하는 브라우저의 주소를 감지 한다.

 - HashRouter 해시 주소(http://goddaehee.tistory.com/#test )를 감지 한다.

 

※ 참고
현재 이 글을 작성하고 있는 시점 기준으로 최신 버전은 v6이다.
v5와 v6의 문법은 차이가 있으니 v6기준으로만 작성하도록 한다.

v5=>v6 migration 하는 가이드
https://reactrouter.com/docs/en/v6/upgrading/v5#upgrading-from-v5

 

2) 설치

 - npm

npm install react-router-dom

 - yarn

yarn add react-router-dom

 

3) 사용 예시

 - 라우터를 사용하기 전에 먼저 쇼핑몰이라고 가정하여 샘플 페이지를 만들어 보자.

   (App, 헤더, 메인 페이지, 상품 상세 페이지)

ex) App.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'>
			<Header />
			<Main />
			<Product />
		</div>
	);
}

export default App;

 

ex) Header.js

import React from 'react';

function Header(props) {
    return (
		<>
			<h1>헤더입니다.</h1>
		</>
    );
}

export default Header;

 

ex) Main.js

import React from 'react';
const Main = (props) => {
	return (
		<>
			<h3>안녕하세요. 메인페이지 입니다.</h3>
		</>
	);
};

export default Main;

 

ex) Product.js

import React from 'react';

const Product = (props) => {
    return (
        <>
            <h3>상품 페이지입니다.</h3>
        </>
    );
}

export default Product;

 

 - 렌더링 결과

 

 현재는 헤더, 메인페이지, 상품상세 페이지가 같이 보인다.
이제부터 Router를 활용 해보자

 

1. <BrowserRouter>태그로 컴포넌트 사용하기

 - BrowserRouter를 사용 할 것이기 떄문에, <BrowserRouter>태그로 컴포넌트를 감싸주자.
 - Header는 모든 URL에 공통 적용할 Component로 최상단에 위치 할 예정이다.

 

2. <Routes>, <Route> 컴포넌트 사용하기
 - <Routes>컴포넌트는 여러 Route를 감싸서 그 중 규칙이 일치하는 라우트 단 하나만을 렌더링 시켜주는 역할을 한다.
 - <Route>는 path속성에 경로, element속성에는 컴포넌트를 넣어 준다. 여러 라우팅을 매칭하고 싶은 경우 URL 뒤에 *을 사용하면 된다.

 

 2.1) "/"로 접근시 메인페이지(Main.js)를 보여줄 것이다.
 2.2) "/product/상품번호"로 접근시 상품상세페이지(Product.js)를 보여 줄 것이다.

 

3. <Link> 컴포넌트 사용하기

 - 웹 페이지에서는 원래 링크를 보여줄 때 a태그를 사용한다. 하지만 a태그는 클릭시 페이지를 새로 불러오기때문에 사용하지 않는다.
 - Link 컴포넌트를 사용하는데, 생김새는 a태그를 사용하지만, History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있다.
 - 문법 : <Link to="경로">링크명</Link>
 - import { Link } from 'react-router-dom';

 

4. 사전에 정의하지 않은 경로로 접근하는 경우 NotFound 페이지로 이동 처리

ex) App.js - BrowserRouter를 사용해 보자.

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/*" element={<Product />}></Route>
					{/* 상단에 위치하는 라우트들의 규칙을 모두 확인, 일치하는 라우트가 없는경우 처리 */}
					<Route path="*" element={<NotFound />}></Route>
				</Routes>
			</BrowserRouter>
		</div>
	);
};

export default App;

 

ex) Main.js - Main모듈에 특정 상품 상세 페이지로 이동하는 링크를 추가하여 주자.

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

const Main = (props) => {
	return (
		<>
			<h3>안녕하세요. 메인페이지 입니다.</h3>
			<ul>
				<Link to="/product/1"><li>1번상품</li></Link>
				<Link to="/product/2"><li>2번상품</li></Link>
			</ul>
		</>
	);
};

export default Main;

 

ex) Header.js - "헤더입니다."를 클릭시 "/"페이지로 이동할 수 있게 링크를 추가 하자.

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

function Header(props) {
    return (
        <>
            <Link to="/">
                <h1>헤더입니다.</h1>
            </Link>
        </>
    );
}

export default Header;

 

ex) NotFound.js

import React from 'react';

const NotFound = () => {
    return (
        <div>
            404 Error
        </div>
    );
};
  
export default NotFound;

 

※ 4개의 모듈을 모두 작성한 후 다음과 같이 접속 하면 페이지 분기 처리되는것을 볼 수 있다.


case1) 루트경로 접속시 (/)

   <Route path="/" element={<Main />}></Route>


case2) 상품상세 페이지 접속시 (/product/*)

   <Route path="/product/*" element={<Product />}></Route>

 - 아직까진 1번 상품, 2번 상품과 상관없이 동일한 상품 페이지가 노출된다.


case3) 정의하지 않은 경로 접속시 (/kkkkkk)

  <Route path="*" element={<NotFound />}></Route>


 

5. URL 파라미터와 쿼리 스트링 사용하기

 - 파라미터, 쿼리스트링을 통해 유동적으로 동작할 수 있다.

ex) 

URL 파라미터 : /product/1
쿼리스트링 : /product?product=1&searchKeyword=productName

 

5.1) URL 파라미터

 - /product/:productId 와 같이 경로에 : 를 사용하여 설정 한다. 
 - URL 파라미터가 여러개인 경우엔 /product/:productId/:productName 과 같은 형태로 설정할 수 있다.
 - 다음 구문을 사용하는 컴포넌트에 추가하여 사용 가능하다.

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

const { 파라미터명 } = useParams(); // const 변수명 = useParams().파라미터명;


ex) App.js => 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;

 

ex) Product.js => useParams를 통해 App.js 에 추가한 productId를 받아 활용 가능하다.

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

const Product = () => {
    const { productId } = useParams();
    return (
        <>
            <h3>{productId}번 상품 페이지 입니다.</h3>
        </>
    );
}

export default Product;

 

※ 파라미터를 통해 상품ID를 활용할 수 있게 되었다.


5.2) 쿼리스트링

 - 하기 useLocation, useSearchParams 도 개발시 활용 가능할 것 같아 간단히 정리만 하고 넘어가자.

 

1) useLocation

 - hash : 주소의 #문자열 뒤의 값
 - pathname : 현재 주소 경로
 - search : ?를 포함한 쿼리스트링
 - state : 페이지로 이동시 임의로 넣을 수 있는 상태 값
 - key : location 객체의 고유 값, 초기값은 default, 페이지가 변경될 때 마다 고유의 값이 생성된다.

 

ex) Product

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

const Product = () => {
    const productId = useParams().productId;
    const location = useLocation();
    return (
        <>
            <h3>{productId}번 상품 페이지 입니다.</h3>
            <ul>
                <li>hash : {location.hash}</li>
                <li>pathname : {location.pathname}</li>
                <li>search : {location.search}</li>
                <li>state : {location.state}</li>
                <li>key : {location.key}</li>
            </ul>
        </>
    );
}

export default Product;

 - 샘플 url

http://localhost:3000/product/1?search=productName&q=demo#test


2) useSearchParams

ex) 

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

const Product = () => {
    const productId = useParams().productId;
    const keyWords = searchParams;
    const keyWord = searchParams.get("search");
  
    return (
        <>
            <h3>{productId}번 상품 페이지 입니다.</h3>
            <ul>
                <li>keyWords : {keyWords}</li>
                <li>keyWord : {keyWord}</li>
            </ul>
        </>
    );
}

export default Product;

 - 결과 페이지

 


6. useNavigate

 - Link 컴포넌트를 사용하지 않고 다른 페이지로 이동을 해야 하는 경우, 뒤로가기 등에 사용하는 Hook 이다.
 - replace 옵션을 사용하면 페이지를 이동할 때 히스토리를 남기지 않는다.

ex)

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;

 

 

 

 

출처 :  https://goddaehee.tistory.com/305?category=395445