일단 라우터에 대해 알아보기 전에 라우팅이란 무엇인가에 대해서부터 알아보려했다.
이라고 사실 구글링해보면 나오는데 사실 이해가 그렇게 가진 않는다.
또 여기서 깊게 들어가면 동적 라우팅, 정적 라우팅, 라우팅의 구성요소.. 등등 라우팅만 하더라도 방대한 공부량이다.
꾸준히 공부하면서 당연히 알아가야할 지식들이지만, 지금 공부해야할건 리액트에서의 라우터이다.
리액트는 SPA(Single Page Application)으로서 페이지의 이동 없이 한 페이지에서 화면 렌더링이 이루어진다.
만약 회원가입창을 눌렀다면 페이지 전체 렌더링이 아니라 회원가입.js 를 가져와서 그에 맞는 화면을 부분 렌더링을 해주는 것이다.
하지만 리액트로 만들어진 사이트가 아닌 사이트, 즉 MPA(Multi Page Application)이었다면,
사이트에서 회원가입창을 눌렀을때 아예 새로운 회원가입이라는 페이지 자체를 렌더링 해줄 것이고 다른 창을
눌렀을때도 그에 맞는 HTML파일들을 가져와서 페이지 자체를 교체해줄 것이다.
이렇듯 리액트는 SPA이기 때문에 페이지의 화면이 달라지더라도 url은 달라지지 않는 문제가 발생한다.
❗️ 리액트 라우터는 페이지 구분을 하게 해주는 라이브러리이다 ❗️
예를 들어서 www.brgndy.com/ 에서 로그인창을 눌러 www.brgndy.com/login 이라는 URL로 접속한다면
그에 맞는 js파일을 가져와서 필요한 부분만 재렌더링 해줄 수 있도록 하는것이다.
❗️ 즉 소위 말하는 페이지 이동을 가능하게 한다 ❗️
터미널 창에서
npm install react-router-dom
을 입력한다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom'; // import 필수!
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
import {Routes, Route, Link} from 'react-router-dom';
<Route path="/about" component={About} />
<Routes>
<Route path="페이지경로" element ={띄우고 싶은 HTML창}/>
</Routes>
<Routes>
<Route path="/Detail" element ={<div>Detail 페이지입니다.</div>}/>
</Routes>
사이트 내에서 잘 출력이 되는 것을 볼 수있다.
하지만 여기서 문제가 발생했다. 페이지 이동을 한다고 가정하면, 아예 새로운 페이지처럼
보여야하는데 지금은 메인 페이지에 있던 상품들까지 같이 보였다. 어떻게 해결해야할까?
<Routes>
<Route
path="/"
element={
<div>
<div className="container">
<div className="row">
{product.map((a, i) => {
return <Products product={product[i]} i={i} />;
})}
</div>
</div>
</div>
}
/>
<Route path="/Detail" element={<div>Detail 페이지입니다.</div>} />
</Routes>
저기에서 "/"는 메인 페이지를 나타내는 경로인데, 저기 element 안에 메인페이지에 들어갈 코드들을 넣어주었다.
❗️ 이것 또한 div 태그로 한번 감싸주고 그 안에 들어갈 코드를 작성해주어야한다 ❗️
이렇게 작성하면 /detail로 접속했을때, Detail 라우터 안에 있는 내용만 보여준다.
하지만 또 이렇게 하면 문제가 발생한다. 만약에 페이지가 여러개 있다고 가정했을때, 페이지마다 각각 다른 코드들을 다 App.js 안에 넣어주어야하므로 코드가 너무 복잡해진다. 그래서 페이지들마다 컴포넌트로 만들어주고 라우터 안에 컴포넌트만 넣어주면 코드가 훨 간결해진다.
메인창을 컴포넌트화를 하려했는데, 저 안에 쓰인 내용물이 이미 컴포넌트로 빼서 만들어진 내용물이었다.
그래서 어떤식으로 접근을 해야할까 고민됐는데, 저 product 자체를 props로 받아서 안의 내용물들과 합쳐주었다.
//메인 창에서 라우터 안에서 사용
<Routes>
<Route
path="/"
element={
<div>
<Products product = {product}/>
</div>
}
/>
</Routes>
//컴포넌트
function Products(props) {
return (
<div className="container">
<div className="row">
{props.product.map((a, i) => {
return (
<div className="col-md-4" key={i}>
<img
src={process.env.PUBLIC_URL + "/picture" + (i + 1) + ".jpeg"}
width="200px"
/>
<h4>{props.product[i].title}</h4>
<p>{props.product[i].content}</p>
<p>{props.product[i].price}</p>
</div>
);
})}
</div>
</div>
);
}
지금은 직접 주소창에 이동하고 싶은 페이지들을 적었는데, 실제로 사이트를 이용할때는 그러지 않는다.
만약 회원가입을 하고싶다하면 회원가입 버튼을 누르고, 장바구니를 보고싶다하면 장바구니 버튼을 누르면 그에
해당하는 페이지로 이동한다. 이런 페이지 이동 버튼을 Link 태그를 이용해서 구현할 수 있다.
//<Link to = '이동 경로'> 버튼 이름 </Link>
<Link to ='/'> 홈 </Link>
<Link to = '/Detail'> 디테일 </Link>
이런 식으로 작성하면 페이지를 이동하는 버튼이 생기고, 이 버튼을 누르면 해당 페이지로 이동할 수 있게 해준다.
버튼이 생긴 것을 확인할 수 있다.
Detail 페이지에 관련된 내용들을 따로 Detail.js 파일에 만들어서 연결해보자
// Detail.js 따로 만들어주기
/* eslint-disable */
function Detail() {
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img
src="picture4.jpeg"
width="50%"
/>
</div>
<div className="col-md-6">
<h4 className="pt-5">상품명</h4>
<p>상품설명</p>
<p>120000원</p>
<button className="btn btn-danger">주문하기</button>
</div>
</div>
</div>
);
}
export default Detail;
//App.js 에서 import 해오기
import Detail from "./Detail";
<Route path="/Detail" element={<div><Detail/></div>} />