티스토리 뷰


Single Page Application에 왜 url을 쓰나요?

Url을 넣는다는 것 자체가 싱글페이지가 아니지 않나요?

 

: Url을 사용하면 하나의 페이지 안에서도 필요한 항목을 사용자가 북마크 처리 하거나, 사용중에 뒤로가기를 눌렀을 때 그 전 url로 이동할 수 있게 해 줍니다. 그렇지 않고 하나의 url을 이용한다면 기록도, 뒤로가기도 할 수 없는 불편한 상황이 오겠죠?


리액트 라우터 설치

리액트 라우터 공식 웹사이트

 

우선 기본 리액트 앱을 만들었다고 가정하겠다(CRA 이용). 해당 폴더에 아래와 같이 입력해 라우터를 설치하자.

npm install react-router-dom

리액트 라우터 기초

BrowserRouter

우선 BrowserRouter를 import 시킨다. 그 옆에 필요한 도구들을 계속 import 할 예정이다.

BrowserRouter은 SPA의 장점인 브라우저가 깜빡이지 않고 다른 페이지로 이동할 수 있게 만들어준다.

 

그리고 App 컴포넌트를 BrowserRouter 컴포넌트로 감싸준다.

 

App.js 기본 셋팅

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom'

function Home(){
  return(
    <div>
      <h2>Home</h2>
      Home...
    </div>
  )
}
function Topics(){
  return(
    <div>
      <h2>Topics</h2>
      Topics...
    </div>
  )
}
function Contact(){
  return(
    <div>
      <h2>Contact</h2>
      Contact...
    </div>
  )
}

function App(){
  return (
    <div>
      <h1>React Router Dom example</h1>
      <ul>
        <li>Home</li>
        <li>Topics</li>
        <li>Contact</li>
      </ul>
      <Home/>
      <Topics/>
      <Contact/>
    </div>
  )
}

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);

Route

Route가 url 주소 이름을 커스터마이징 할 수 있게 한다.

사용법은 아주 간단하게 라우트 하고 싶은 컴포넌트를 Route 컴포넌트로 감싸주면 된다.

 

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

...

function App(){
  return (
    <div>
      <h1>React Router Dom example</h1>
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/topics">Topics</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
      <Route path="/"><Home/></Route>
      <Route path="/topics"><Topics/></Route>
      <Route path="/contact"><Contact/></Route>
    </div>
  )
}

예를 들어, localhost:3000/ 는 Home 컴포넌트가, localhost:3000/topics는 Topics 컴포넌트가 나오는 것이다.

하지만 여기서 문제가 생긴다.

순서대로 Home, Topics, Contact

보다시피, Home 으로 통하는 버튼을 누르면 정상적으로 Home 만 나오는데, Topics와 Contact를 누르면 Home이 함께 뜬다.

이유는, Home은 마지막이 /로 끝나는데 Topics와 Contact는 슬래시를 포함 하기 때문이다.

 

이를 수정하기 위해 아래의 방법을 쓰자.

 

Exact

exact라는 불리언 값을 넣으면 정확히 지정된 루트는 해당 값만 적용되게 한다.

아래와 같이 이용하자.

function App(){
	...

	<Route exact path="/"><Home/></Route>
        <Route path="/topics"><Topics/></Route>
        <Route path="/contact"><Contact/></Route>
      
    ...
}

이렇게 적용한 상태로 다시 버튼을 눌러보면 잘 작동하는 것 을 볼 수 있다.

 

모든 라우트들에 exact 효과를 넣고 싶다면?

 

Switch

switch 컴포넌트는 라우트를 직렬적으로 변형시킨다.

switch를 사용하기 위해서는 아래와 같이 쓴다.

import {BrowserRouter, Route, Switch} from 'react-router-dom'

function App(){
...

      <Switch>
      	<Route path="/"><Home/></Route>
      	<Route path="/topics"><Topics/></Route>
      	<Route path="/contact"><Contact/></Route>
      </Switch>
      ...
      
}

위에서부터 아래로 내려오면서 첫번째 path가 a 라면 이후에 오는 a path는 무시당하는 것이다.

때문에, 이를 이용하면 /인 Home에 의해 다음의 것들은 무시 돼, Home만 나오게 될 것이다.

 

이를 해결하기 위해서는 Home에 exact를 붙이거나 Home 라인을 Contact 아래로 내리면 된다.

 

Link

Link 컴포넌트는 a태그의 속성인 페이지 새로고침을 막는다.

여태까지는 a링크의 새로고침 속성 때문에 굳이 SPA가 아니라도 충분히 구현할 수 있는 기능이었다.

 

import {BrowserRouter, Route, Switch, Link} from 'react-router-dom'

function App(){
  return (
    <div>
      <h1>React Router Dom example</h1>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/topics">Topics</Link></li>
        <li><Link to="/contact">Contact</Link></li>
      </ul>
      <Switch>
      	<Route exact path="/"><Home/></Route>
      	<Route path="/topics"><Topics/></Route>
      	<Route path="/contact"><Contact/></Route>
      </Switch>
    </div>
  )
}

 

Hash Router

hash router는 browser router와 필요에 의해 선택해서 사용한다.

hash router를 사용하면 url이 localhost:5000/#/topics 처럼 중간에 해시가 들어간다. 이는 서버사이드가 해시 이후는 읽을 수 없게 처리해 가벼운 애플리케이션을 라우팅할때 사용된다.

 

그래서 서버가 필요하지 않은 가벼운 애플리케이션은 hash router를, 그렇지 않은 경우는 browser router를 사용한다.

 

이 외에도, hash router는 어찌 됐던 서버사이드 까지 렌더링이 되는 것은 루트 url이기 때문에, 어떤 페이지에 들어가도 루트 페이지의 서비스를 이용할 수 있다면 hash router이 아닌 browser router를 사용한다.

그것이 힘들다면 어떤 url을 써도 # 이후는 무시되는 hash router를 써서 루트 페이지의 서비스를 이용할 수 있다.

import {HashRouter, Route, Switch, Link} from 'react-router-dom';

...

ReactDOM.render(
  <HashRouter>
    <App />
  </HashRouter>,
  document.getElementById('root')
);

url에 #가 포함됨

 

NavLink

Link 와 다르게 사용자가 있는 현재 router에 active라는 class를 자동으로 붙여준다.

이를 이용해서 active 클래스의 css를 설정하는 식으로 조건을 걸 수 있을 것이다.

 

import {HashRouter, Route, Switch, Link, NavLink} from 'react-router-dom';

...

function App(){
  return (
    ...
      <ul>
        <li><NavLink to="/">Home</NavLink></li>
        <li><NavLink to="/topics">Topics</NavLink></li>
        <li><NavLink to="/contact">Contact</NavLink></li>
      </ul>
      ...
  )
}

하지만 이것도 경로를 특정지어야 하기 때문에 exact를 이용하면 좋다.


파라미터는 따로 게시글을 제작할 예정이다.

이렇게 보니 백엔드에서 쓰는 라우팅과 리액트의 라우팅은 어떤 차이가 있는지 궁금해진다. 하지만 리액트 라우터가 매우 편리한 기술임은 알 수 있겠다.


참고:

생활코딩 React Router

반응형
댓글