본 게시물은 벨로퍼트님의 React-Router 강의를 보며 정리한 내용입니다.
라우팅이란, 어떤 주소에서 어떤 UI를 보여줄 것인가 규칙을 정하는 작업을 말한다.
과거의 라우팅은 주로 서버에서 처리했지만, 최근 웹에서는 클라이언트가 관리합니다.
Single Page Application
라우팅에 대해 더 알아보기 전에, 먼저 SPA에 대해 간략하게 알아보겠습니다.
과거에는 클라이언트는 원하는 주소 (/root)를 서버에 요청하면 서버가 그에 해당하는 html 파일을 전달해주고, 클라이언트는 그 html 파일을 브라우저에 보여주는게 주된 역할이었습니다.
하지만 사용자 인터렉션이 많은 경우에 계속 서버에 요청하고, 받는 과정이 UX에 좋지 않고, 서버 자원도 낭비되었습니다.
이러한 문제를 해결하기 위해 SPA가 등장했습니다. SPA는 웹 어플리케이션 구성에 필요한 모든 정적 리소스를 최초에 한번 다운 받습니다. 이후 변경이 필요하면 클라이언트에서 자체적으로 UI를 리렌더링하며, 필요한 데이터가 있을 때만 서버에 추가적인 데이터를 요청하고 처리합니다. 이 때 페이지 전체가 아닌 필요한 부분만 리렌더링을 진행하며, 이로 인해 사용자 경험(UX)이 향상됩니다.
앱의 규모가 커지면 JS 파일이 너무 커질 수 있다.
=> Code splitting으로 해결 가능
브라우저에서 JS가 구동 되지 않으면 UI를 볼 수 없다. (ex. 검색엔진에서 크롤링 불가능)
=> SSR(Server Side Rendering)을 통해 해결 가능
리액트에서 SPA를 만들기 위해 가장 많이 사용되는 라이브러리입니다. 최근에는 Next가 치고 올라오고 있습니다!
컴포넌트를 기반으로 라우팅합니다.
파일 경로, 이름을 기반으로 라우팅합니다.
SSR, Code Splitting을 매우 쉽게 구현할 수 있습니다.
HTML5 History API를 사용하며 주소만 바꾸고 페이지는 다시 불러오진 않습니다
서버측에 새로운 요청을 하지 않으며 이를 통해 'history'를 남겨서 SPA에서 '뒤로가기'를 구현할 수 있습니다. (본래 SPA는 싱글 페이지이기 때문에 뒤로가기 개념이 없습니다)
브라우저의 주소와 전혀 관계 없습니다.
그래서 브라우저가 아닌 환경에서 쓰기 좋습니다. 임베디드 웹앱, 리액트 네이티브..
특정 페이지에 일부분을 리액트로 구현해서 삽입하고 싶을 때
브라우저 주소가 변경되지 않는다!
<Route path="/" component={Home}>
<Route path="/about" component={About} exact>
path에 해당하는 주소값에 지정한 component를 보여주겠다는 뜻입니다
이 경우 "/about"주소에 들어가면 About 컴포넌트만 보일 것 같지만, Home 컴포넌트도 같이 보입니다. 왜냐하면 "/about"이라는 경로에 "/"도 포함되어있기 때문!
이를 해결하기 위해 "/"를 지정한 Route 컴포넌트에 exact 속성을 추가합니다.
<Route path="/" component={Home} exact>
<Link to="/">홈</Link>
<Link to="/about">어바웃</Link>
정해진 특정 데이터를 가져올 때 주로 사용
/users/DD
Route 컴포넌트의 path주소에 /:target을 입력한다.
<Route path="/users/:username" component={UserView}/>```
component에 URL Parameter 처리가 구현된 컴포넌트를 입력한다.
const User = ({match}) => {
const { username } = match.params;
...
};
다양한 옵션으로 조회할 때(주로 검색)
/filter?type=user&sort_by=data
마찬가지로, Query를 처리할 수 있는 컴포넌트를 작성한다.
import qs from 'qs';
const About = ({location}) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true
});
};
{
pathname : "/about",
search : "?a=1",
hash : "",
state : undefined
}
// ignoreQueryPrefix값을 따로 지정하지 않았을 때(default false) 결과
{
?a : 1
}
// true로 했을 때
{
a : 1
}
// /about/?a=1&b=1&c=1 로 URL에 입력했을 때
{
a : 1,
b : 2,
c : 3
}