React Router

WebStudy / / 2021. 2. 19. 23:44

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
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기