[ React ] React Router 사용하기

ma.caron_g·2022년 12월 13일
0

React

목록 보기
8/8
post-thumbnail

< 참고 링크 >

[ 라우팅이란 ? ]

사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이라고 생각할 수 있습니다.

이 글에서는 리액트에서 라우팅 관련 라이브러리가 많은데, 이 중 가장 많이 사용하는 리액트 라우터(React Router)를 사용해보겠습니다.

[ React Router ]

사용자가 입력한 주소를 감지하는 역할.

여러 환경에서 동작할 수 있도록 여러 종류의 라우터 컴포넌트를 제공합니다.

이 중 가장 많이 사용하는 라우터 컴포넌트는
BrowserRouteHashRouter입니다.

[ 설치 ]

리액트 개발 폴더 쉘에서 다음 명령어를 이용하여 리액트 라우터 돔을 설치해줍니다.

$ npm install react-router-dom

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

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

[ 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;

[ Header.js ]

import React from 'react';

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

export default Header;

[ Main.js ]

import React from 'react';

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

export default Main;

[ Product.js ]

import React from 'react';

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

export default Product;

[ 렌더링 결과 ]

다음과 같이 App.js에 컴포넌트를 조건없이 모두 넣어서 모든 페이지의 값이 나타납니다.

이를 해결하기 위해 Router를 활용해보겠습니다.



[ BrowserRouter ]

BrowserRouter를 사용할 것이기 때문에, <BrowserRouter> 태그로 컴포넌트를 감싸줍니다.

Hedaer는 모든 URL에서 공통으로 들어갈 내용이므로 Component로 최상단에 놓아줍니다.

[ 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'>
			<BrowserRouter>
				<Header />
				<Main />
      			<Product />
			</BrowserRouter>
		</div>
	);
};

export default App;


[ Routes와 Route ]

<Routes> 컴포넌트는 여러 Route를 감싸서 그 중 규칙이 일치하는 단 하나만을 렌더링 시켜주는 역할을 합니다.

<Route>는

  • path : 경로
  • element : 컴포넌트
    다음 내용을 입력하여 Path값에 따라 보여줄 element를 지정해줍니다.

여러 라우팅을 매칭하고 싶다면 URL뒤에 *를 사용하면 됩니다.

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

[ 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'>
			<BrowserRouter>
				<Header />
				<Routes>
					<Route path="/" element={<Main />}></Route>
					<Route path="/product/*" element={<Product />}></Route>
				</Routes>
			</BrowserRouter>
		</div>
	);
};

export default App;

그럼 다시 렌더링을 해본다면

[ localhost:3000/ ]

path="/" 로 지정했던 main페이지만 보이게 됩니다.

URL에 "/product" 값을 추가한다면

path:"/product"로 설정했던 상품 페이지가 보여집니다.



일반 HTML에서는 링크를 보여줄 때 a태그에 href값을 넣어 사용합니다.
하지만, a태그는 클릭 시 페이지를 새로 불러오기 때문에 사용하지 않습니다.

이를 해결하기 위해 Link 컴포넌트를 사용합니다.
생김새는 a태그를 사용하지만, History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있습니다.

import { Link } from 'react-router-dom'
...

<Link to="[경로]">링크명</Link>

[ 정의되지 않은 페이지로 접근 ]

링크에 잘못된 URL을 입력하여 접근하는 경우
보여주고 싶은 페이지를 정의

[ NotFound.js ]

import React from 'react';

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

export default NotFound;

URL에 정의되지 않는 값을 넣으면 다음과 같이 렌더링 됩니다.

[ URL 파라미터와 쿼리 스트링 ]

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

상품이 100가지가 있는데 이 100개의 페이지를 하나씩 설정해주기엔 비효율적입니다. 이를 해결하기 위해 사용합니다.

/product/:productId 와 같이 경로에 :를 사용하여 설정합니다.

URL 파라미터가 여러 개인 경우 /product/:prodcutId/:productName 과 같은 형태로 설정 가능합니다.

다음과 같이 사용하는 컴포넌트를 추가하여 사용합니다.

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

const [파라미터명] = useParams();

[ 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;

[ Product.js ]

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도 개발 시 활용 가능할 것 같아 간단히 정리

[ 1) useLocation ]

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

[ useNavigate ]

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

[ Product.js ]

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;

profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글