Single Page Application
라우팅을 클라이언트가 담당
라우팅: 어떤 주소에 어떤 UI를 보여줄지 결정하는 것
클라이언트가 웹페이지에 처음 접속하게 되었을 때 UI에 대한 코드를 미리 준비해 놓고 그 후 경로가 이동되면, 바로 보여줄 수 있으며, 만일 데이터가 필요한 경우 필요한 데이터만 서버에 요청하여 사용할 수 있다.
이점
- 서버에서는 서버 자원을 아낄 수 있음
- 클라이언트에서는 더 나은 사용자 경험을 누릴 수 있다.
단점
- 앱의 규모가 커지면 JS 파일의 크기가 너무 커질 수 있다.
- 해결책: Code Splitting
- 브라우저에서 js가 구동되지 않으면 UI를 볼 수 없다
- ex) 검색엔진에서 크롤링 불가능
- 해결책: Server Side Rendering
React Router library VS Next.js library
- React Router
- 컴포넌트 기반으로 라우팅을 한다.
- 컴포넌트를 렌더링하고 거기에 필요한 props를 넣어주어 router을 설정한다.
- Next.js
- 파일 경로, 이름을 기반으로 라우팅을 함
- Server Side Rendering을 엄청 쉽게 구현 가능
React Router
- BroWserRouter
- HTML5 History API 사용
- 주소만 바꾸고 페이지는 다시 불러오지는 않는다.
- HashRouter
- #를 사용한다.
- 옛날 브라우저 전용
- MemoryRouter
- 브라우저의 주소와 무관, 일체 건들이지 않는다.
- 브라우저가 아닌 환경에서 사용하기 좋음
- 임베디드 웹앱, React Native 등에서 사용
- StaticRouter
- Server Side Rendering에서 사용하는 용도
- Route
- 라우트를 정의할 때 사용하는 컴포넌트
- Link
- 사용한 Router의 주소를 바꿈
- a 태그이나 새로고침이 되는 것이 아니다.
사용 예시
- index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import {BrowserRouter} from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
```
App.js
import React from 'react'; import {Route, Link} from 'react-router-dom'; import About from './About'; import Home from './Home'; function App(){ return( <div> <ul> <li> <Link to = "/">홈</Link> </li> <li> <Link to = "/about">소개</Link> </li> </ul> <Route path= "/" component = {Home} exact/> <Route path= "/about" component = {About}/> </div> ); } export default App;
Home.js
import React from 'react'; function Home(){ return( <div> <h1>홈</h1> <p>이 곳은 홈입니다. 가장 먼저 보여지는 페이지 입니다.</p> </div> ); } export default Home;
About.js
import React from 'react'; function About(){ return( <div> <h1>소개</h1> <p>이 프로젝트는 리액트 라우터 기초를 실습해보는 예제 프로젝트 입니다.</p> </div> ); } export default About;
파라미터와 쿼리
주소를 통해서 어떤 동적인 값을 읽어와야 할 때 사용함
App.js
import React from 'react'; import {Route, Link} from 'react-router-dom'; import About from './About'; import Home from './Home'; import Profile from './Profile'; function App(){ return( <div> <ul> <li> <Link to = "/">홈</Link> </li> <li> <Link to = "/about">소개</Link> </li> </ul> <Route path= "/" component = {Home} exact/> <Route path= "/about" component = {About}/> <Route path= "/profile/:username" component = {Profile}/> </div> ); } export default App;
파라미터: /profiles/velopert
Profile.js
import React from 'react'; const profileData = { velopert: { name: 'jh', description: 'Frontend Engineer' }, homer: { name: '호머 심슨', description: '심슨 가족에 나오는 아빠' } } function Profile({match}){ const {username} = match.params; const profile = profileData[username]; if(!profile){ return <div>존재하지 않는 사용자</div> } return( <div> <h3>{username} ({profile.name})</h3> <p> {profile.description} </p> </div> ); } export default Profile;
쿼리: /about?details=true
About.js
import React from 'react'; import qs from 'qs'; function About({location}){ const query = qs.parse(location.search,{ ignoreQueryPrefix: true // ?를 지워준다. }); const detail = query.detail === 'true'; console.log(query); return( <div> <h1>소개</h1> <p>이 프로젝트는 리액트 라우터 기초를 실습해보는 예제 프로젝트 입니다.</p> {detail && <p>detail값이 true입니다.</p>} </div> ); } export default About;
서브 라우트
라우트 내에 있는 또 다른 라우트
예시) App라는 컴포넌트에 Route 설정해주어 Profiles를 참조하고, Profiles 컴포넌트에 Route 설정해주어 Profile를 참조한다.
App.js
import React from 'react'; import {Route, Link} from 'react-router-dom'; import About from './About'; import Home from './Home'; import Profiles from './Profiles'; function App(){ return( <div> <ul> <li> <Link to = "/">홈</Link> </li> <li> <Link to = "/about">소개</Link> </li> <li> <Link to = "/profiles">프로필 목록</Link> </li> </ul> <Route path= "/" component = {Home} exact/> <Route path= "/about" component = {About}/> <Route path= "/profiles" component = {Profiles}/> </div> ); } export default App;
Profiles.js
import React from 'react'; import Profile from './Profile'; import {Link, Route} from 'react-router-dom'; function Profiles(){ return( <div> <h3>사용자 목록</h3> <ul> <li> <Link to = "/profiles/velopert">velopert</Link> </li> <li> <Link to = "/profiles/homer">homer</Link> </li> </ul> <Route path = "/profiles" exact render = {() => <div>사용자를 선택해 주세요</div>} /> <Route path = "/profiles/:username" component = {Profile}/> </div> ); } export default Profiles;
Profile.js
import React from 'react'; const profileData = { velopert: { name: 'jh', description: 'Frontend Engineer' }, homer: { name: '호머 심슨', description: '심슨 가족에 나오는 아빠' } } function Profile({match}){ const {username} = match.params; const profile = profileData[username]; if(!profile){ return <div>존재하지 않는 사용자</div> } return( <div> <h3>{username} ({profile.name})</h3> <p> {profile.description} </p> </div> ); } export default Profile;
React Router 부가 기능
history 객체
라우트로 사용되는 컴포넌트에게 props로 전달이 된다.
이를 사용하여 컴포넌트에서 라우터에 직접적인 접근이 가능하다.
특정 함수를 호출 했을 때, 특정 경로로 이동하거나, 또는 뒤로 가거나 페이지 이탈을 방지할 수 있다.
HistorySample.js
import React, {useEffect} from 'react'; function HistorySample({history}){ const goBack = () => { history.goBack(); } const goHome = () => { // 방문한 페이지 기록을 남김 history.push('/'); } const replaceToHome = () => { // 방문한 페이지 기록을 남기지 않음 history.replace('/'); } useEffect(()=>{ console.log(history); const unblock = history.block('정말 갈거임?'); return () => { unblock() }; },[history]); return( <div> <button onClick = {goBack}>뒤로가기</button> <button onClick = {goHome}>홈으로</button> <button onClick = {replaceToHome}>홈으로 (replace)</button> </div> ); } export default HistorySample;
withRouter
라우터 컴포넌트가 아닌 곳에서 match, location, history를 props로 받아와서 사용
match는 현재 자신이 rendering 된 위치를 기준으로 match값을 받아온다.
WithRouterSample.js
import React from 'react'; import {withRouter} from 'react-router-dom'; function WithRouterSample({location, match, history}){ return( <div> <h4>loacation</h4> <textarea value = {JSON.stringify(location, null, 2)} readOnly /> <h4>match</h4> <textarea value = {JSON.stringify(match, null, 2)} readOnly /> <button onClick = {() => history.push('/')}>홈으로</button> </div> ); } export default withRouter(WithRouterSample);
Switch
- 여러 가지 라우트 중에서 가장 먼저 매칭된 라우트 하나만 보여준다.
- 존재하지 않는 페이지 만들 때 유용하다.
- 사용
<Switch> <Route path= "/" component = {Home} exact/> <Route path= "/about" component = {About}/> <Route path= "/profiles" component = {Profiles}/> <Route path= "/history" component = {HistorySample}/> <Route render = {({location}) => ( <div> <h2>이 페이지는 존재하지 않습니다.</h2> <p>{location.pathname}</p> </div> )}/> </Switch>
NavLink
Link와 비슷한 컴포넌트이다.
현재 주소와 일치한다면 특별한 스타일을 지정해 줄 수 있다.
Profiles.js: Link -> NavLink
import React from 'react'; import Profile from './Profile'; import {NavLink, Route} from 'react-router-dom'; function Profiles(){ return( <div> <h3>사용자 목록</h3> <ul> <li> <NavLink to = "/profiles/velopert" activeStyle={{background: 'black', color: 'white'}}>velopert</NavLink> </li> <li> <NavLink to = "/profiles/homer" activeStyle={{background: 'black', color: 'white'}}>homer</NavLink> </li> </ul> <Route path = "/profiles" exact render = {() => <div>사용자를 선택해 주세요</div>} /> <Route path = "/profiles/:username" component = {Profile}/> </div> ); } export default Profiles;
useReactRouter Hook 사용
import useReactRouter from 'use-react-router';
function RouterHookSample(){
const {history, location, match} = useReactRouter();
console.log({history,location,match});
return null;
}
export default RouterHookSample;
'WebStudy' 카테고리의 다른 글
React API (0) | 2021.02.18 |
---|---|
React 기본 3 (0) | 2021.02.15 |
React 기본 2 (0) | 2021.02.13 |
React 기본 1 (0) | 2021.02.12 |
Web Server 및 WAS (0) | 2021.02.06 |
최근댓글