Route, Link, react-router v6

zzwwoonn·2022년 5월 27일
0

React

목록 보기
16/23

Route 와 Link, react-router v6 에 대해 알아보고 지금까지 리액트 짜잘하게 공부해오면서 쌓아놨던? 예제 코드들을 라우터와 링크를 이용해서 리팩토링 해보자.

기본적으로 SPA는 index.html 파일에 div 엘리먼트만 하나 두고, 자바스크립트로 모든 부분을 동적으로 렌더링하는 구조를 취한다. 그리고 화면의 전체 또는 일부(Header 와 Main을 따로 두고 Header는 렌더링 x , Main만 업데이트)를 브라우저에서 발생하는 이벤트에 따라서 동적으로 갱신(이전에 포스팅 했던 내용, 렌더링 최적화)할 수 있기 때문에 인터랙티브 한 사용자 경험을 제공할 수 있다.

React 렌더링 성능 최적화 하기

Route

=> 특정 주소에 컴포넌트 연결하기

Route
현재 주소창의 경로와 매치될 경우 보여줄 컴포넌트를 지정하는데 사용된다.
path property를 통해서 매치시킬 경로를 지정하고, component prop을 통해서 매치되었을 때 보여줄 컴포넌트를 할당한다.

라우트를 설명할 때 가장 많이 나오는 예제를 통해 사용법을 보자

import React from 'react';
import { Route } from 'react-router-dom';
import About from './About';
import Home from './Home';

const App = () => {
  return (
    <div>
      <Route path="/" exact={true} component={Home} />
      <Route path="/about" component={About} />
    </div>
  );
};

export default App;

exact 라는 props 를 true 로 설정하면 경로가 완벽히 똑같을때만 컴포넌트를 보여주게 된다.

=> 뒷 부분에 다루겠지만 이 코드 안돌아간다...

=>누르면 다른 주소로 이동시키기

Link 컴포넌트는 클릭하면 다른 주소로 이동시키는 컴포넌트이다.
리액트 라우터를 사용할땐 일반적으로 사용하는 a 태그

<a href="...">...</a> 

위의 태그를 사용하시면 안된다. 그 대신에 Link 라는 컴포넌트를 사용해야한다.

<Link to="/about">소개</Link>

그 이유는 a 태그의 기본적인 속성은 페이지를 이동시키면서, 페이지를 아예 새로 불러오게된다.

그렇게 되면서 리액트 앱이 지니고 있는 상태들도 초기화되고, 렌더링된 컴포넌트도 모두 사라지고 새로 렌더링을 하게된다.

그렇기 때문에 Link 컴포넌트를 사용하는데, 이 컴포넌트는 HTML5 History API 를 사용하여 브라우저의 주소만 바꿀뿐, 페이지를 새로 불러오지는 않는다.

import React from 'react';
import { Route, Link } from 'react-router-dom';
import About from './About';
import Home from './Home';

const App = () => {
  return (
    <div>
      <ul>
        <li>
          <Link to="/"></Link>
        </li>
        <li>
          <Link to="/about">소개</Link>
        </li>
      </ul>
      <hr />
      <Route path="/" exact={true} component={Home} />
      <Route path="/about" component={About} />
    </div>
  );
};

export default App;

=> 이것도 안돌아간다..........


위의 예제 코드 2개는 구글에 route 와 link 를 검색하면 나오는 대표적인 코드이다. 근데 지금 돌려보면 돌아가지 않는다. 도대체 왜?

react-router v6

react-router 버전이 5에서 6으로 바뀌면서 정말 많은? 부분이 바뀌었다.
이것도 모르고 몇시간동안 삽질... 너무 어이가 없고 화가 치밀어 올랐지만 (아니 잘 되던게 갑자기 안되니까ㅡㅡ) 많은 걸 알게됐다고 자위했다.

왜 안되는지를 모르니 얼마나 답답했으면 프로젝트 새로 만들어서까지 해봤다고...

react-router v6 에서 바뀐 점에 대해 하나씩 알아보자. 마지막으로는 지금까지 공부했던 리액트 코드, 디렉토리를 라우터를 이용해서 리팩토링 해보자.

Switch -> Routes

V5 에서는 routes 들을 구성하는 부모 요소로 Switch를 이용하였는데 V6 에서는 route의 복수개?를 뜻하는 routes로 이름이 바뀌었다.

// v5
<Switch>
  <Route ... />
</Routes>

// v6
<Routes>
  <Route ... />
</Routes>

Switch 말고 Routes 쓰래요 Switch 없대요 이제..

(리팩토링 실습 코드 미리보기)

exact 옵션 삭제

기존의 / 라우트의 경우 React Router의 디폴트 매칭 규칙으로 인해 앞부분만 일치해도 전부 매칭되기 때문에 정확하게 라우트를 일치시켜줘야 했는데 이를 위해 exact 속성을 사용했다.

여기서 / 경로를 사용하는 컴포넌트에만 exact prop이 사용된 이유는, React Router의 디폴트 매칭 규칙 때문입니다. React Router는 path prop의 경로와 현재 브라우저의 주소창의 URL 경로 (location.pathname)와 비교를 하는데요.
현재 URL 경로 값이 의 path porp 값과 전체가 아닌 앞부분만 일치해도 매치되는 것으로 간주합니다. 따라서 path가 /일 경우, / 뿐만 아니라 /로 시작하는 모든 URL 경로, 사실 상 가능한 모든 경우의 수의 경로와 매치가 됩니다. 그렇기 때문에, exact prop이 없으면, 의도치 않게 Home 컴포넌트가 URL 경로와 상관없이 항상 보여지게 됩니다. 하지만 exact prop을 붙여주면 URL 경로 값이 의 path 값과 완벽히 전체가 일치해야 매치되는 것으로 처리를 해줍니다.
[출처] - DaleSeo : React Router로 라우팅 하기

하지만 V6부터 기본적으로 정확히 일치하도록 매칭 규칙이 변하여 exact 옵션을 사용하지 않는다.

만약 하위 경로에 여러 라우팅을 매칭시키고 싶다면 아래와 같이 URL 뒤에다가 * 을 사용하여 일치시킬 수 있다.

// categores 로 시작되는 모든 라우팅 매칭
<Route path='categories/*' />

리팩토링 실습 코드에서도 exact 없이 잘 동작하는 것을 확인했다.
=> 있든 없든 상관 x

route 에서 컴포넌트 렌더링

이게 진짜 ㅡㅡ 하 이거 때문에 얼마나 삽질을 해댔는지 모르겠다. 에러도 안뜨고 왜 안되는지도 안뜨고 심지어 warning 메세지도 뜨지 않더라.

근데? 렌더링이 안돼 => 화면이 안보여

이전 버전에서는

<Route path='user' component={UserInfo} />

위와 같이 컴포넌트를 엮어주었다.

V6 버전에서는 element 속성을 통해 바로 넣어줄 수 있도록 개편되었다.

<Route path='user' element={<UserInfo />} />

실습 코드로 예를 들어보면

<Router> 
	<Header/>
    <Routes>
   		<Route path="/" element={<Home />} />
        <Route exact path="/" element={<Home/>}/>
        <Route path="/about" element={<About/>}/>
        <Route path="/03page" element={<Example3Page/>}/>
    </Routes>
</Router> 

이건 잘 돌아간다.

<Router> 
	<Header/>
    <Routes>
   		<Route path="/" component={Home} />
        <Route exact path="/" element={<Home/>}/>
        <Route path="/about" element={<About/>}/>
        <Route path="/03page" element={<Example3Page/>}/>
    </Routes>
</Router> 

이건 안돌아간다.

리팩토링 실습

Structure

code

// App.js

import './App.css';
import React from 'react';

// import {  Link, Route, Routes, Router} from 'react-router-dom';
// 이건 안돼

import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
//  이건 돼

import Header from './Pages/Header';
import Main from './Pages/Main'
import Home from './Pages/Home';
import About from './Pages/About';
import Example3Page from './Pages/Example3Page';

function App() {

  return (  
    //     {/* <TopHeader/> */}
    //     <Header/>
    //     <hr></hr>
    //     {/* <Route exact path = "/" component={} />
    //     <Route path="/about" component={About} />
    //     <Route path*/}
        
    //     {/* <Main/>  */}

    //     <div>
    //       <Route exact path="/" component={Home}/>
    //       <Route path="/about" component={About}/>

    //       {/* <Route path="/03page" component={Example3Page}/> */}
    //     </div>
    // </Router>

      <Router> 
        <Header/>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route exact path="/" element={<Home/>}/>
          <Route path="/about" element={<About/>}/>
          <Route path="/03page" element={<Example3Page/>}/>
        </Routes>
      </Router> 

          // {/* <Route exact path="/" component={Home}/> */}
          // {/* <Switch>
          //     <Route path="/about/:name" component={About}/>
          //     <Route path="/about" component={About}/>
          // </Switch> */}
          // {/* <Route path="/about/:name" component={About}/>
          // <Route path="/about" component={About}/> */}

  );
}

export default App;

코드를 다 적어두고 싶지만.. 뭐 어떻게 jsx 파일 하나하나 다 올려둘 수도 없고.. 혹시 코드가 궁금하신 분들은

깃헙에서 찾아보시면 됩니다!

https://github.com/jwseo4074

0개의 댓글