- 라우팅 : 사용자가 요청한 URL에 따라 알맞은 페이지를 보여주는 것
- 웹 애플리케이션을 만들 때 프로젝트를 하나의 페이지로 구성할 수도 있고 여러 페이지로 구성할 수도 있다.
- 여러페이지로 구성된 웹 애플리케이션을 만들 때 페이지 별로 컴포넌트들을 분리해가면서 프로젝트를 관리하기 위해 필요함
- 리액트에서 라우트 시스템을 구축하기 위해 사용할 수 있는 선택지2
(1) React Router 라이브러리 : 컴포넌트 기반으로 라우팅 시스템을 설정할 수 있다.
(2) Next.js : 리액트프로젝트의 프레임워크. creat-react-app처럼 리액트 프로젝트 설정을 하는 기능, 라우팅 시스템, 최적화, 다국어시스템 지원, ssr 등 다양한 기능 제공, 파일경로 기반으로 작동함.
- 라우팅 관련 기능은 리액트 라이브러리에서 공식적으로 지원하는 것이 아니고 서드파티로 제공
- 하나의 페이지로 이루어진 애플리케이션 (이전: 멀티 페이지 애플리케이션)
- MPA : 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고 페이지를 로딩 때마다 서버에서 css, js, 이미지 파일 등의 리소스를 전달받아 브라우저 화면에 보여줌. 각 페이지마다 다른 html파일을 만들어서 제공하거나, 데이터에 따라 유동적 html 생성해주는 템플릿 엔진 사용하기도 함
- 사용자 인터렉션이 많고 다양한 정보를 제공하는 모던 웹 애플리케이션은 이 방식이 적합하지 않다. 서버의 자원, 트래픽 문제
- 리액트 같은 라이브러리 사용해서 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고 새로운 데이터 필요하면 서버 API 호출해서 필요 데이터만 새로 불러옴
- SPA : html을 한번만 받아와서 웹 애플리케이션 실행 시킨 후 이후에는 필요한 데이터만 받아와서 화면에 업데이트하는 것
- 기술적으로는 한 페이지만 존재하지만, 사용자 경험으로는 여러 페이지가 존재하는 것처럼 느껴진다.
- 리액트 라우터 같은 라우팅 시스템은 : 사용자 브라우저 주소창의 경로에 따라 알맞은 페이지를 보여주는데 링크를 눌러서 다른 페이지로 이동시 다른 페이지의 html을 새로 요청하는 것이 아니라 브라우저의 History API를 사용하여 브라우저의 주소창의 값만 변경하고 기존에 페이지에 띄웠던 웹 애플리케이션 유지하면서 라우팅 설정에 따라 또 다른 페이지를 보여줌
$ yarn create react-app 새로운프로젝트
$ cd 새로운프로젝트
$ yarn add react-router-dom
- 프로젝트에 리액트 라우터 적용할 때는 src/index.js 에서 react-router-dom에 내장되어 있는 `BrowserRouter` 라는 컴포넌트를 사용하여 감싸면 된다.
- 페이지 새로 불러오지 않아도 HTML5의 History API 사용하여 주소변경, 현재 주소경로에 관련 정보를 리액트 컴포넌트에서 사용할 수 있게 해준다.
//src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import {BrowserRouter} from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
document.getElementById('root')
);
// src/pages/Home.js
const Home = () => {
return (
<div>
<h1> 홈 </h1>
<p> 이 페이지는 가장 먼저 보여지는 화면입니다. </p>
</div>
)
}
// src/pages/About.js
const About = () => {
return (
<div>
<h1> 페이지 소개 </h1>
<p> 리액트라우터를 사용해보는 페이지입니다. </p>
</div>
);
};
export default About;
- 페이지로 사용할 이러한 컴포넌트들을 꼭 pages경로에 넣을 필요는 없다.
- 이것은 단순히, 페이지를 위한 컴포넌트들을 다른 파일들과 구분하기 위함이고, routes라는 이름을 써도 되고 그냥 src 경로에 바로 생성해도 문제가 되지는 않음.
// src/App.js
import {Route, Routes} from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
const App = () => {
return (
<Routes>
<Route path="/" elements={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
};
export default App;
<Link to="경로"> 링크이름 </Link>
이렇게 사용함- Home페이지에서 About페이지로 이동할 수 있도록 Link 컴포넌트를 Home페이지컴포넌트에서 사용해보기,
// src/pages/Home.js
import {Link} from 'react-router-dom';
const Home = () => {
return (
<div>
<h1> 홈 </h1>
<p> 가장먼저 보여지는 페이지입니다. </p>
<Link to="/about"> 소개 </Link>
</div>
)
}
URL파라미터는, 주소의 경로에 유동적인 값을 넣는 형태이고,
쿼리스트링은, 주소의 뒷부분에 ? 문자열 이후에 key=value 로 값을 정의하며 & 로 구분하는 형태이다.
URL파라미터는 주로, ID 또는 이름을 사용하여 특정 데이터를 조회할 때 사용,
쿼리스트링(Querystring)은 키워드검색, 페이지네이션, 정렬방식 등 데이터조회에 필요한 옵션을 전달할 때 사용
// src/pages/Profile.js
import {useParams} from 'react-router-dom';
const data = {
velopert: {name: 'kim', description: 'reactDev'},
gildong: {name: 'lee', description: 'hongName'}
};
const Profile = () => {
// URL파라미터는 useParams라는 Hook을 사용하여 객체 형태로 조회할 수 있다.
// URL파라미터의 이름은, 라우트설정을 할 때 Route컴포넌트의 path props를 통해 설정한다.
const params = useParams();
const profile = data[params.username];
return (
<div>
<h1> 사용자프로필 </h1>
// 삼항연산자 {profile ? () : ()}
{profile ? (
<div>
<h2> {profile.name} </h2>
<p> {profile.description} </p>
</div>
) : (
<p> 존재하지 않는 프로필입니다.</p>
)}
</div>
);
}
- 여기서는, data객체에 예시프로필 정보들을 key-value 형태로 담았고,
- Profile컴포넌트에서는 username URL파라미터를 통하여 프로필을 조회한 뒤에 true, false 결과값 보여지도록
// src/App.js
import {Route, Routes} from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
import Profile from './pages/Profile';
const App = () => {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
</Routes>
);
};
export default App;
- URL파라미터는, /profiles/:username 처럼 경로에 :를 사용하여 설정
- 만약, URL파라미터가 여러개면, /profiles/:username/:field 같은 형태로 설정할 수 있다.
// src/pages/Home.js
import {Link} from 'react-router-dom';
const Home = () => {
return (
<div>
<h1> 홈 </h1>
<p> 가장먼저 보여지는 페이지입니다. </p>
<ul>
<li>
<Link to="/about"> 소개 </Link>
</li>
<li>
<Link to="/profiles/velopert"> velopert님의 프로필 </Link>
</li>
<li>
<Link to="/about"> 소개 </Link>
</li>
</ul>
</div>
);
};
export default Home;
// src/pages/About.js
import {useLocation} from 'react-router-dom';
const About = () => {
const location = useLocation();
return (
<div>
<h1> 소개 </h1>
<p> 리액트 라우터를 사용해보는 프로젝트입니다. </p>
<p> 쿼리스트링: {location.search} </p>
</div>
);
};
export default About;
- useLocation 이라는 Hook : location 객체를 반환한다.
- 이 객체는 현재 사용자가 보고있는 페이지의 정보를 지니고 있다.
* pathname : 현재주소의 경로(쿼리스트링 제외)
* search : 맨 앞의 ? 문자를 포함한 쿼리스트링 값
* hash : 주소의 # 문자열 뒤의 값 (주로 History API가 지원되지 않는 구형 브라우저에서 클라이언트 라우팅을 사용할 때 쓰는 해시라우터에서 사용)
* state : 페이지로 이동할 때 임의로 넣을 수 있는 상태 값
* key : location 객체의 고유값, 초기에는 default 이며 페이지가 변경될때마다 고유의 값이 생성 됨.
// src/Layout.js
import {Outlet, useNavigate} from 'react-router-dom';
const Layout = () => {
const navigate = useNavigate();
const goBack = () => {
navigate(-1);
// 이전페이지로 이동
};
const goArticle = () => {
navigate('/articles');
};
return (
<div>
<header style={{background: 'lightgray', padding: 16, fontSize: 24}}>
<button onClick={goBack}> 뒤로가기 </button>
<button onClick={goArticle}> 게시글 목록 </button>
</header>
<main>
<Outlet />
</main>
</div>
)
}
// replace : 페이지 이동시 현재페이지를 페이지기록에 안남긴다.
const goArticles = () => {
navigate('/articles', {replace: true});
};
- 파라미터 값이 주어지면 1초 뒤에 10을 더해서 반환하는 함수가 있다고 가정,
- 그리고 `해당 함수가 처리된 직후 어떠한 작업을 하고 싶다`면 콜백함수를 활용한다.
const increase = (number, callback) => {
setTimeout(() => {
const result = number + 10;
if (callback) {
callback(result);
}
}, 1000)
}
increase (0, result => {
console.log(result);
});
- 1초에 걸쳐서 10, 20, 30, 40 과 같은 형태로 여러번 순차적으로 처리하고 싶다면 콜백함수를 중첩하여 구현한다.