ReactJS Router Dom
임광규
SPA
SPA는 Single Page Application의 약어 입니다. 말 그대로 한개의 페이지로 구성된 애플리케이션을 뜻합니다. 전총적인 웹 페이지는 여러 페이지로 구성되어 있습니다.
라우팅
다른 주소에 다른 화면을 보여주는 것을
라우팅
이라고 합니다. 리액트 라이브러리 자체에 이 기능이 내장 되어 있지는 않습니다.
리액트 라우팅 라이브러리는 리액트 라우터(react-router), 리치 라우터(reach-router), Next.js 등 여러 가지가 있습니다.
이중 가장 오랫동안 사용되었고 사용빈도 역시 높은 리액트 라우터
를 알아봅니다.
SPA의 단점
SPA의 단점은 앱의 규모가 커지면 자바스크립트 파일이 너무 커진다는 것입니다. 페이지 로딩 시 사용자가 실제로 방문하지 않을 수도 있는 페이지의 스크립트도 불러오기 때문입니다.
이때 코드 스플리팅(code splitting)을 사용하면 라우트별로 파일을 나누어서 트래픽과 로딩 속도를 개선할 수 있습니다.
리액트 라우터 설치
설치는 아래 명령어를 이용해서 진해합니다.
$ yarn add react-router-dom
or
$ npm install react-router-dom --save
라우터 적용
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(<BrowserRouter> <App /> </BroserRouter>,
document.getElementById('root'));
}
라우터 적용
app.js
import React from 'react';
import { Route } from 'react-router-dom';
import About from './About';
import Home from './Home';
export default () => {
return (
<div>
<Route path="/" component={Home} exact={true} />
<Route path="/about" component={About} />
</div>
);
}
Router
사용법
Route 컴포넌트를 사용하여 사용자의 현재 경로에 따라 다른 컴포넌트를 보여줄수 있습니다.
<Route path="주소규칙" component={보여 줄 컴포넌트} />
Link
컴포넌트를 사용하여 다른 주소로 이동
Link 컴포넌트는 클릭하면 다른 주소로 이동시켜주는 컴포넌트입니다. 일반 웹에서는 a 태그를 사용하여 페이지를 전환 하는데 리액트 라우터를 사용할 때는 이 태그를 직접 사용하면 안됩니다.
사용법
<Link to="주소">내용</Link>
Link 컴포넌트 사용 예
app.js
import React from 'react';
import { Route, Link } from 'react-router-dom';
import About from './About';
import Home from './Home';
export default () => {
return (
<div>
<ul>
<li><Link to="/">홈</Link></li>
<li><Link to="/about">소개</Link></li>
</ul>
<Route path="/" component={Home} exact={true} />
<Route path="/about" component={About} />
</div>
);
}
Route 하나에 여러 개의 path 설정하기
Route 하나에 여러 개의 path를 지정하는 것은 최신 버전의 리액트 라우터 v5부터 적용된 기능입니다.
/about
, /info
에 접근시 About 컴포넌트로 보여줌
import React from 'react';
import { Route } from 'react-router-dom';
import About from './About';
import Home from './Home';
export default () => {
return (
<div>
<Route path="/" component={Home} exact={true} />
<Route path={['/about', '/info']} component={About} />
</div>
);
}
URL 파라미터와 쿼리
페이지 주소를 정의할 때 가끔은 유동적인 값을 전달해야 할 때도 있습니다. 이를 파라미터와 쿼리로 나눌수 있습니다.
- 파라미터 예시 : /info/lahuman
- 쿼리 예시 : /about?id=lahuman
URL 파라미터 예
/info 페이지에서 파라미터를 사용시 /info/:id 형식으로 값을 넣어주어 props로 받아와서 조회가 가능합니다.
import React from 'react';
export default ({ match }) => {
const { id } = match.params;
return (
<div>
<h1> {id} </h1>
</div>
);
}
app.js
import React from 'react';
import { Route, Link } from 'react-router-dom';
import About from './About';
import Info from './Info';
import Home from './Home';
export default () => {
return (
<div>
<ul>
<li><Link to="/">홈</Link></li>
<li><Link to="/about">소개</Link></li>
<li><Link to="/info/lahuman">lahuman 정보 조회</Link></li>
</ul>
<Route path="/" component={Home} exact={true} />
<Route path="/about" component={About} />
<Route path="/info/:id" component={Info} />
</div>
);
}
URL 쿼리
쿼리는 location 객체에 들어 있는 search 값에서 조회할 수 있습니다. location 객체는 라우트로 사용된 컴포넌트에게 props로 전달되며 웹의 현재 주소에 대한 정보를 지니고 있습니다.
location 객체 정보
{
"pathname": "/about",
"search": "?id=lahuman",
"hash": ""
}
qs 라이브러리
쿼리 문자열로 객체로 변환할 때는 qs 라이브러리를 사용하여 쉽게 처리할 수 있습니다.
$ yarn add qs
or
$ npm install qs --save
URL 쿼리 예제
qs를 이용하여 파싱된 결과는 언제나 문자열 입니다.
import React from 'react';
import qs from 'qs';
export default ({location}) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true // 문자열 맨 앞의 ?를 생략 합니다.
});
return <h1>{query.id}</h1>
}
서브 라우트
서브 라우트는 라우트 내부에 도 라우트를 정의하는 것을 의미 합니다. 그냥 라우트로 사용되고 있는 컴포넌트의 내부에 Route 컴포넌트를 또 사용하면 됩니다.
import React from 'react';
import { Route, Link } from 'react-router-dom';
import Info from './Info';
export default () => {
return (
<div>
<ul>
<li><Link to="/info/abcd">abcd 정보 조회</Link></li>
<li><Link to="/info/lahuman">lahuman 정보 조회</Link></li>
</ul>
<Route path="/info" exact render={() => <div>사용자를 선택해주셔요.</div>} />
<Route path="/info/:id" component={Info} />
</div>
);
}
리액트 라우터 부가 기능
- history
- 라우트로 사용된 컴포넌트에 match, location과 함께 전달되는 props 중 하나로, 이 객체를 통해 컴포넌트 내에 구현하는 메소드에서 구현하는 메서드에서 라우터 API를 호출 할수 있습니다.
- withRouter
- HoC(Higher-order Component)로 라우트로 사용된 컴포넌트가 아니어도 match, location, history 객체를 접근할 수 있게 해줍니다.
- Switch
- 여러 Route를 감싸서 그중 일치하는 단 하나의 라우트만 랜더링 시켜줍니다. 모든 규칙과 일치하지 않을 때 Not Found 페이지도 구현할 수 있습니다.
- NavLink
- Link와 비슷, 단 링크가 활성화 되었을 때의 스타일을 activeStyle에 적용하면됩니다.
history 예제
import React from 'react';
export default ({history}) => {
return (
<div>
<button onClick={() => history.push('/')}>홈으로</button>
<button onClick={() => history.goBack()}>뒤로</button>
</div>
);
}
withRouter 예제
import React from 'react';
import { withRouter } from 'react-router-dom';
export default withRouter(({location, match, history}) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true // 문자열 맨 앞의 ?를 생략 합니다.
});
return
<div>
<h1>{query.id}</h1>
<button onClick={() => history.push('/')}>홈으로</button>
<button onClick={() => history.goBack()}>뒤로</button>
</div>
})
Switch 예제
import React from 'react';
import { Route, Link, Switch } from 'react-router-dom';
import About from './About';
import Info from './Info';
import Home from './Home';
export default () => {
return (
<div>
<ul>
<li><Link to="/">홈</Link></li>
<li><Link to="/about">소개</Link></li>
<li><Link to="/info/lahuman">lahuman 정보 조회</Link></li>
</ul>
<Switch>
<Route path="/" component={Home} exact={true} />
<Route path="/about" component={About} />
<Route path="/info/:id" component={Info} />
<Route render={({location}) => <div>
<h2>페이지가 존재 하지 않습니다.</h2>
<p>{location.pathname}</p>
</div>} />
</Switch>
</div>
);
}
NavLink 예제
import React from 'react';
import { Route, NavLink } from 'react-router-dom';
import Info from './Info';
export default () => {
const activeStyle = {
background: 'red',
color: 'white'
}
return (
<div>
<ul>
<li><NavLink activeStyle={activeStyle} to="/info/abcd" active>abcd 정보 조회</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/info/lahuman">lahuman 정보 조회</NavLink></li>
</ul>
<Route path="/info" exact render={() => <div>사용자를 선택해주셔요.</div>} />
<Route path="/info/:id" component={Info} />
</div>
);
}