React Router


React Router란?


Client Side Rendering을 하는 React에서 주소값 변경에 따라 유의미한 변화를 보여주기 위해 사용되는 라이브러리입니다.

-> 특정 주소로 유저가 접근했을때, 그 URL에 맞는 작업을 Client Side에서 할 수 있도록 해주는 라이브러리


추가적으로 React Router는 공식으로 지원하는 라이브러리는 아닙니다.

하지만 현재 Router 관련 라이브러리들중에서는 가장 많은 사용자를 보유하고 있습니다.




React Router V4


이번 포스팅에서는 React Router V4 에 대해 포스팅 하겠습니다.


React Router V4는 React Router의 최신버전으로, V3를 포함한 그 이전 버전들과는


철학도 다르고 API도 다르게 만들어진 버전입니다.

( 하지만 아직도 V3버전은 계속해서 유지보수가 진행중입니다.)


대부분의 동작이 React Component로 이루어진 것이 특징입니다.




바로 사용해보도록 하겠습니다.


CRA로 프로젝트를 만들고 기본 폴더들을 생성해주세요.




우선 가장 간단하게 사용해 보겠습니다.


App.tsx 파일에 react-router-dom 을 import 해주세요.


import { BrowserRouter as Router, Route } from 'react-router-dom';


저는 as 를 이용하여 BrowserRouter 를 Router로 쓰겠다고 명시하였습니다.


App Class 에 Router 를 사용해보겠습니다.


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

import { BrowserRouter as Router, Route } from 'react-router-dom';

const logo = require('./logo.svg');

class App extends React.Component<{}, {}> {
render() {
return (
<Router>
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<Route path="/" render={() => <h1>Home</h1>} />
<Route path="/About" render={() => <h1>About</h1>} />
</div>
</Router>
);
}
}

export default App;


react-router 를 쓰기 위해서는


우선 써야하는 위치의 최상단에 BrowserRouter 를 명시해주어야 사용이 가능합니다

( 위와 같은 경우에는 App 위치 어디서든 react-router를 사용할수 있습니다.)

( 저는 as 를 이용하여 Router 라고 쓰도록 하겠습니다.)


저는 우선 무든 부분에서 사용 가능하도록 전체를 Router로 감싸보았습니다.


그리고 Route를 사용해보겠습니다.


path 는 주소를 의미합니다.


첫번째 경우에는 localhost:3000/ 주소를 의미하고

두번째 경우에는 localhost:3000/About 주소를 의미합니다.


그다음 그 주소를 요청하였을때 나타내는 뷰를 지정하는 것인데,


여러가지 방법중 우선 render를 이용한 방법을 사용하였습니다.


즉 위의 코드는 / 주소로 접속하면 Home 이라는 글자를 h1 태그를 이용하여 보여주고,

/About 주소로 접속하면 About 이라는 글자를 h1태그를 이용하여 보여줄것이라고 예상됩니다.


실행하여 보겠습니다.


localhost:3000


localhost:3000/About


Home 은 제대로 나오는듯 하지만


About에서 뭔가 이상한것을 느낄수 있습니다.  Home이 같이 렌더링이 되어버렸습니다.


이 현상은 Route 를 사용할때 path 부분에서 path="/" 를 사용하였는데


About path 에도 "/" 가 포함되어 있기 때문에 react-router 는 모두 렌더링 해버린 현상입니다.


이 문제를 해결하기 위해서는 


<Route path="/" render={() => <h1>Home</h1>} />


에서 exact 를 추가해주면 해결할수 있습니다.


<Route exact={true} path="/" render={() => <h1>Home</h1>} />


exact값을 true로 준다면, path가 정확히 "/" 와 일치할 경우에만 Home을 렌더링 하게 됩니다.


다시 한번 실행해보겠습니다.


localhost:3000/About


정상적으로 렌더링 되는것을 확인하였습니다.


이번에는 Link를 사용해보도록 하겠습니다.


class App extends React.Component<{}, {}> {
render() {
return (
<Router>
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/About">About</Link>
</li>
</ul>
</nav>
<Route exact={true} path="/" render={() => <h1>Home</h1>} />
<Route path="/About" render={() => <h1>About</h1>} />
</div>
</Router>
);
}
}


Link를 사용하는 방법은 간단합니다.


위에 react-router-dom 을 import하는 부분에 Link를 추가하고 사용해주세요.


to 는 Link를 눌렀을때 이동할 Path 입니다.


실행하여 확인해보겠습니다.



제대로 작동함을 확인할수 있습니다.


그런데 왜 a태그를 사용하지 않고 다른 방식으로 사용하는 것일까요?


우선 개발자 창으로 한번 살펴보겠습니다.


< chrome 에서 확장 프로그램으로 react development tool 을 사용하여 살펴보겠습니다.

 Component로 확인이 가능하고 props, state및 여러 값들도 확인 할 수 있어 매우 유용하니 사용해보시는것을 권장합니다.>




 Link 도 결국 a태그로 작동이 된다고 볼수 있습니다.


그렇다면 그냥 a태그를 쓰면 되지 않을까?? 라는 생각이 드는데요,


한번 a태그를 사용하여 해보겠습니다.


<li>
<a href="/">a태그</a>
</li>


그리고 실행하여 확인해보겠습니다.


About을 눌렀다가 Link 를 눌러보고, a태그도 눌러보세요.


다른점을 느끼셨나요?


Link를 사용하지 않고 그냥 a태그를 사용하게 되면, 페이지 새로고침이 일어나는것을 확인하셨을거라 생각됩니다.


즉 Link를 사용하지 않는것은 페이지 새로고침을 하지 않고 뷰를 렌더하기 위해 사용하는 것으로


성능상의 이점 가질수있습니다.


자 그럼 기본적인것은 해보았으니 다른것을 한번 해보도록 하겠습니다.


이번에는 Route에서 render가 아닌 Component를 이용하여 렌더링 해보도록 하겠습니다.


comtainers폴더에  Home.tsx 파일과 About.tsx 파일을 생성하고


함수형 컴포넌트를 만들어주세요.


그리고 index.tsx 파일에 추가하는것도 해주세요.


Home.tsx

import * as React from 'react';

const Home = () => {
return (
<h1>Home - func Component</h1>
);
};

export default Home;


About.tsx

import * as React from 'react';

const About = () => {
return (
<h1>About - func Component</h1>
);
};

export default About;



App.tsx.에 import 해주세요.


import { Home, About } from '.';


그리고 이전에 Route에서 사용한 render를 지우고 component를 넣어주겠습니다.


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


실행시켜보겠습니다.




제대로 동작되는것을 확인할수 있습니다.


그렇다면 또다른 렌더링 방식인 child는 어떻게 사용하는것일까요?


이곳을 참조하여 생각해보았습니다.

https://medium.com/@pshrmn/a-simple-react-router-v4-tutorial-7f23ff27adf


child로 prop를 받아 상황에 따라 렌더링 하는 방식에 사용하면 좋겠다는 생각이 들었습니다.


예를들어

<Route path="/page" children={(props) => (props.match ? <h1>/page 주소입니다</h1> : <h1>/page 주소가 아닙니다</h1>)}/>

이러한 코드를 추가한뒤 Link도 추가해서 실행해보겠습니다.



저는 코드에서 prop를 받아 match 값을 확인하여 주소가 맞으면 주소가 맞다고 렌더링 하고

다르다면 다른것을 렌더링 하도록 하였습니다. 아마 이렇게 활용하는것이라 생각이 됩니다...

(만일 다른 좋은 예제를 알고계신분은 알려주시기 바랍니다. )



- 추가적으로 혹시 그럼 render를 이용할때도 prop를 받아서 하면 되지 않을까? 라는 생각이 들어 한번 해보았습니다.

<Route path="/page2" render={(props) => (props.match ? <h1>/page2 주소입니다</h1> : <h1>/page2 주소가 아닙니다</h1>)}/>


결과는...



주소가 일치할때만 렌더링이 되고,


그 외의 주소에서는 react development tool로 확인결과


렌더링 되는것이 null인것을 확인하였습니다.


이 부분에 대해서는 좀더 공부가 필요한듯 싶습니다.




정리입니다.

* BrowserRouter

- 다른 라우팅 컴포넌트를 사용하기 위해 기본적으로 감싸주어야 합니다.

- 오직 하나의 자식만을 가질수 있습니다.

- 'window.history.pushState()' 로 동작하는 라우터입니다.

-  이것과 비슷한 HashRouter 는 Hash(#/)로 동작하는 Router 입니다.


* Route

- path 속성으로 경로를 지정합니다.

- render, component, children 으로 렌더링을 실시합니다.

- 실제 경로와 완벽하게 일치 하지 않더라도 포함되는 경우에 렌더링을 실행합니다.

 - 정확히 매칭될때만 렌더링을 하고싶다면, exact 속성을 true로 지정해주세요.

- 컴포넌트에 match, history, location 이라는 객체를 넘겨줍니다.


* Link

- a 태그로 렌더링 되며 사용법도 비슷하지만, 실제 동작은 조금 다릅니다.

- a 태그는 페이지 전체를 리로드 하여 렌더링 하는 반면에, Link는 페이지 전체를 리로드 하지 않고 필요한 부분만 리로드하게 됩니다.


이번 포스팅에서는 React-Router 에 대해 간단하게 살펴보았습니다.


다음 포스팅에서는 React-Router 에 대해 포스팅을 이어나가도록 하겠습니다.

( props, 중첩라우팅, 리다이렉트, switch 등등..)


소스코드 주소입니다.


https://github.com/JaroInside/tistory-react-typescript-study/tree/12.react-router-part1


clone 하신뒤 브런치를 checkout 하시기 바랍니다.


감사합니다.



참고 슬라이드 - http://slides.com/hyunseob/react-router#/

참고 동영상 - https://www.youtube.com/playlist?list=PLV6pYUAZ-ZoHx0OjUduzaFSZ4_cUqXLm0



블로그 이미지

Jaro

대한민국 , 인천 , 남자 , 기혼 , 개발자 jaro0116@gmail.com , https://github.com/JaroInside https://www.linkedin.com/in/seong-eon-park-16a97b113/

,