벨로퍼트 리액트 - 5. 리액트 라우터
react-router 를 통한 리액트 싱글페이지 애플리케이션 만들기
SPA
: Single Page Application(싱글 페이지 어플리케이션). 페이지가 1개인 어플리케이션을 말한다.
라우터
: 다른 주소에 따라 다른 뷰를 보여주는 것.
ㄴ 리액트 자체에는 내장되어 있지 않아 직접 브라우저의 API를 사용하고 상태를 설정하여 다른 뷰를 보여주어야 한다.
react-router : 써드파티 라이브러리. 클라이언트 사이드에서 이뤄지는 라우팅을 간단하게 해줌. 서버 사이드 렌더링도 도와주는 도구들이 함께 딸려옴. react-native에서도 사용 가능!
SPA의 단점
앱의 규모가 커지면 JS 파일 사이즈가 너무 커져버린다는 것. 유저가 실제로 방문하지 않을 수도 있는 페이지에 관련된 렌더링 관련 스크립트도 불러오기 때문이다.
⇒ Code Splitting 사용으로 라우트 별로 파일들을 나눠 트래픽과 로딩 속도 개선 가능!
리액트 라우터처럼 브라우저 측에서 자바스크립트를 사용하여 라우트를 관리하는 것의 잠재적 단점은 js를 실행하지 않는 일반 크롤러에서 페이지의 정보를 제대로 받아가지 못한다는 것이다. 때문에 구글, 네이버, 다음 등 검색엔진에서 페이지가 검색 결과에 잘 나타나지 않을 수 있다. 또 js가 실행될 때까지 페이지가 비어있기 때문에 파일이 아직 캐싱되지 않은 사용자는 아주 짧은 시간동안 흰 페잊가 나타날 수 있다는 단점도 있다. ⇒ 서버사이드 렌더링을 통해 해결 가능!
리액트 라우터 사용법
라이브러리 설치
$ npm add react-router-dom
index.js에서 BrowserRouter
컴포넌트를 사용해서 구현
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'; // * BrowserRouter 불러오기
// import * as serviceWorker from './serviceWorker';
const root = ReactDOM.createRoot(document.getElementById('root'));
// * App 을 BrowserRouter 로 감싸기
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();
페이지 만들기 - src/Home.js
import React from "react";
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>이곳은 홈이에요. 가장 먼저 보여지는 페이지죠.</p>
</div>
);
}
export default Home;
페이지 만들기 - src/About.js
import React from "react";
const About = () => {
return (
<div>
<h1>소개</h1>
<p>이 프로젝트는 리액트 라우터 기초를 실습해보는 예제 프로젝트입니다.</p>
</div>
);
}
export default About;
Route : 특정 주소에 컴포넌트 연결하기
사용자가 요청하는 주소에 따라 다른 컴포넌트 보여주기.
https://reactrouter.com/en/v6.3.0/getting-started/overview < 공식문서
<Route path="주소규칙" element={<보여줄 컴포넌트 />}>
import { render } from "react-dom";
import {
BrowserRouter,
Routes,
Route,
} from "react-router-dom";
// import your route components too
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route index element={<Home />} />
<Route path="teams" element={<Teams />}>
<Route path=":teamId" element={<Team />} />
<Route path="new" element={<NewTeamForm />} />
<Route index element={<LeagueStandings />} />
</Route>
</Route>
</Routes>
</BrowserRouter>,
document.getElementById("root")
);
Link : 누르면 다른 주소로 이동시키기
(X)
ㄴ 사용한다면 onClick에 e.preventDefault() 호출하고 따로 주소를 변환시켜줘야함
a 태그는 페이지를 이동시키면서 페이지를 아예 새로 불러옴
⇒ 리액트 앱이 지니고 잇는 상태들이 초기화되면서 렌더링된 컴포넌트가 모두 사라지고 새로 렌더링을 하게 됨 ⇒ Link 컴포넌트 사용! 주소만 바꿀뿐 페이지를 새로 불러오지는 않는다.
<Link to="/">홈</Link>
파라미터와 쿼리
파라미터: /profiles/harry
쿼리: /about?details=true
파라미터 : 특정 id, 이름으로 조회할때
쿼리 : 키워드 검색 또는 요청할때 필요한 옵션 전달시 사용
URL Params
Profile 페이지에서 파라미터 사용
import React from "react";
import { useParams } from "react-router-dom";
const profileData = {
harry : {
name: "박혜원",
discription : "리액트 공부중"
},
tester11 : {
name: '김철수',
discription : '테스트 유저'
}
};
const Profile = () => {
// useParams() 사용해서 파라미터 읽어오기
const {username} = useParams();
const profile = profileData[username];
if (!profile) {
return <div>존재하지 않는 유저입니다.</div>;
}
return (
<div>
<h3>
{username}({profile.name})
</h3>
<p>{profile.description}</p>
</div>
)
};
export default Profile;
match 객체 안에는 현재 주소가 Route 컴포넌트에서 정한 규칙과 어떻게 일치하는지에 대한 정보가 들어있다.
Profile을 App에 적용
path 규칙에 /profiles/:username
이라고 적어주면 username에 해당하는 값을 파라미터로 넣어줘서 Profile 컴포넌트에서 match props를 통해 전달받을 수 있다.
import React from 'react';
import { Route, Routes, Link } from 'react-router-dom';
import About from './About';
import Home from './Home';
import Profile from './Profile';
const App = () => {
return (
<div>
<ul>
<li>
<Link to="/">홈</Link>
</li>
<li>
<Link to="/about">소개</Link>
</li>
</ul>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
</Routes>
</div>
);
};
export default App;
Query
쿼리는 라우트 컴포넌트에게 props 전달되는 loaction 객체에 있는 search 값에서 읽어올 수 있다.
loaction 객체는 현재 앱이 갖고 있는 주소에 대한 정보를 갖고 있다.
search값 - 문자열 형태. 객체 형태로 변환하는것은 개발자가 해야함. ⇒
qs 라이브러리 사용.
⇒ useSearchParams 사용!
예제) About 컴포넌트에서 search 값에 있는 detail 값을 받아와서 해당 값이 true 일때 추가정보 보여주도록 구현.
import React from "react";
import { useSearchParams } from "react-router-dom";
const About = () => {
const [searchParams] = useSearchParams();
const detail = searchParams.get('detail') === 'true'; // 쿼리의 파싱결과 값은 문자열
return (
<div>
<h1>소개</h1>
<p>이 프로젝트는 리액트 라우터 기초를 실습해보는 예제 프로젝트입니다.</p>
{detail && <p>추가 정보~!~!~!~!~! </p>}
</div>
);
}
export default About;