# 기본 라우팅

## React Router 모듈

```javascript
import { 
  BrowserRouter as Router, 
  // 또는 HashRouter as Router, 
  Switch,
  Route, 
  Link,
  NavLink,
  Redirect
} from 'react-router-dom';
```

## Router 컴포넌트

#### BrowserRouter 컴포넌트

* HTML5 History API를 사용해 URL과 매칭되는 UI를 렌더링한다. (예: `/lectures`)
* 해시값 없이 `pathName`을 사용해서 이동한다.&#x20;
* IE10+ 부터 사용 가능하다.&#x20;

#### HashRouter 컴포넌트

* URL 해시(`#`)를 사용해 URL과 UI를 매칭한다. (예: `/#/lectures`)
* 검색 엔진이 읽지 못한다.&#x20;
* URL 해시를 사용하기 때문에 브라우저나 웹 서버에 제한 없이 사용할 수 있다.&#x20;

```javascript
// 예시 
example.com/#/messages/messages
```

```javascript
<HashRouter hashType="hashbang">
```

{% hint style="info" %}
[GitHub Pages](https://pages.github.com/)에 React 앱을 배포할 경우, HashRouter를 사용해야 한다. \
참고 → [HashRouter과 BrowserRouter의 차이](https://wonit.tistory.com/299)&#x20;
{% endhint %}

### 라우터 설정

일반적으로 라우터는 App 컴포넌트에 추가한다. 라우터 내부에는 각 라우트 경로와 연결 될 컴포넌트를 설정하고, 각 페이지를 탐색하게 하는 내비게이션으로 구성된다. &#x20;

```javascript
const App = () => (
  <Router>
    {/* 내비게이션: <Link>, <NavLink> 사용 */}
    {/* 라우트: <Swtich>, <Router>, <Redirect> 사용 */}
  </Router>
)
```

또는 ReactDOM 렌더링 과정에서 `<Router>`로 `<App>`을 래핑할 수 있다. &#x20;

```javascript
ReactDOM.render(<Router><App/></Router>, document.getElementById('reactApp'));
```

## React Router 컴포넌트 종류

React 웹 앱 제작에 자주 사용되는 컴포넌트&#x20;

| 컴포넌트 종류                                                                                                                                                                                                         | 설명                                  |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| `<BrowserRouter>` / `<HashRouter>`                                                                                                                                                                              | 라우터(Router) 컴포넌트                    |
| [`<Route>`](https://reacttraining.com/react-router/web/api/Route)/  [`<Switch>`](https://reacttraining.com/react-router/web/api/Switch)                                                                         | 라우트 경로(Route Path) 매처(matcher) 컴포넌트 |
| [`<Link>`](https://reacttraining.com/react-router/web/api/Link)/ [`<NavLink>`](https://reacttraining.com/react-router/web/api/NavLink)/ [`<Redirect>`](https://reacttraining.com/react-router/web/api/Redirect) | 라우트를 변경하는 내비게이션(Navigation) 컴포넌트    |

## Route 컴포넌트

[Route ](https://reacttraining.com/react-router/web/api/Route)컴포넌트는 설정된 `path`와 매칭되는 컴포넌트를 찾아 일부 UI를 렌더링 한다. 일반적으로 라우트는 `path`, `component` 속성을 사용해 표시 할 URL과 컴포넌트를 설정한다. &#x20;

### path / component 속성 &#x20;

`path` 속성의 값과 매치되는 경로로 이동한다. 이때 `path="/"` 경우 `exact` 키워드를 같이 사용해야한다. `exact`는 정확하게 검사한다는 의미로 이를 설정하지 않으면 `/lecture` 페이지에서 `/`(Home) 페이지의 콘텐츠도 같이 보이는 오류가 발생한다. &#x20;

```javascript
import Home from './views/Home'
import Lecture from './views/Lecture'
import Lab from './views/Lab'

<BrowserRouter>
  <Route path="/" exact component={Home} />
  <Route path="/lecture" component={Lecture} />
  <Route path="/lab" component={Lab} />
</BrowserRouter>
```

`component` 속성을 사용하지 않으면 아래와 같이 작성한다.&#x20;

```javascript
<BrowserRouter>
  <Route path="/" exact>
    <Home />
  <Route>
  <Route path="/lecture">
    <Lecture />
  <Route>
  <Route path="/lab">
    <Lab />
  <Route>
</BrowserRouter>
```

### Route 컴포넌트 렌더링 방법

`<Route>` 컴포넌트를 사용해 렌더링 하는 방법은 다음의 3가지 이다.&#x20;

| 렌더링 방법                                                                                      | 설명                             |
| ------------------------------------------------------------------------------------------- | ------------------------------ |
| [`<Route component>`](https://reacttraining.com/react-router/web/api/Route/component)       | URL과 매칭되는 컴포너트를 렌더링 한다.        |
| [`<Route render>` 함수](https://reacttraining.com/react-router/web/api/Route/render-func)     | 인라인 렌더링 또는 래핑 렌더링 시에 사용한다.     |
| [`<Route children>` 함수](https://reacttraining.com/react-router/web/api/Route/children-func) | 매칭될 경우, 자식 컴포넌트를 렌더링 할 때 사용한다. |

#### **component** 렌더링

위에서 본 component  속성을 사용해서 렌더링 하는 방식이다.&#x20;

```javascript
<Route 
  path="/" 
  component={Home} 
/>
```

#### **render** 함수 렌더링

* 인라인 렌더링 → render 함수의 반환 값으로 컴포넌트를 내보내는 방식이다. 단, 개발자 도구에서 확인이 불가능하다. (권장 X)&#x20;
* render가 전달 받는 인자는 Route 컴포넌트가 전달 받은 props(match, location, history)를 전달 받는다.&#x20;

```javascript
// 인라인 렌더링
<Route 
  path="/" 
  exact 
  render={() => <div className="Home">홈</div>} 
/>

// 래핑 렌더링
const FadeInRoute = (({component: Component, ...rest}) => {
  return (
    <Route 
      {...rest}
      // render의 routeProps는 Route컴포넌트에 전달된 ...rest를 전달 받는다.
      render={(routeProps) => (
        <FadeIn>
          <Component {...routeProps} />
        </FadeIn>
      )}
    />
  )
}

<FadeInRoute path="/lab" component={Lab} />
```

**children** 함수 렌더링

**children** 함수 렌더링 방식은 RouteGuard와 같이 애니메이션 라우트를 만들 때 사용할 수 있다. 그래서 path속성을 사용한 일반적인 라우트에서는 사용하지 않는다.&#x20;

```javascript
<Route
  children={({ match, ...rest }) => (
    {/* Animate는 항상 렌더링되므로 라이프 사이클 훅을 사용하여 
        자식(child) 컴포넌트를 애니메이션 할 수 있습니다. */}
    <Animate>
      {match && <SubPage {...rest}/>}
    </Animate>
  )}
/>
```

{% hint style="info" %}
React에서 애니메이션 기능을 구현하기 위해서 [React Spring](https://www.react-spring.io/)과 같은 애니메이션 전용 라이브러리를 사용할 수 있다.&#x20;
{% endhint %}

## Route 컴포넌트의 Props

* [match](https://reacttraining.com/react-router/web/api/match)
* [location](https://reacttraining.com/react-router/web/api/location)
* [history](https://reacttraining.com/react-router/web/api/history)

#### Route 컴포넌트 props 전달

Route 컴포넌트에 props를 전달 할 때는 render 속성을 사용해서 props를 전달한다.&#x20;

Categorise 컴포넌트에 sortBy 속성을 전달하기 위해 1번 코드와 같이 작성하면 match, location, history는 Categorise 컴포넌트에 전달 되지 않는다.&#x20;

```javascript
/*   1   */
<Route 
  path="/categories" 
  render={(props) => <Categories sortBy="createdAt" />} 
/>
```

하지만 아래와 같이 컴포넌트에 전달 받은 props를 전개해서 전달해 주면 해당 컴포넌트는 sortBy 속성을 포함한 match, location, history 속성도 모두 전달 받는다.&#x20;

```javascript
/*   2   */
<Route 
  path="/categories" 
  render={(props) => <Categories sortBy="createdAt" {...props} />} 
/>
```

### 정확한 라우팅 설정

홈 링크 패스 `/`는 항상 활성화 상태이다. 모든 패스에 `/`가 있기 때문이다. 그래서 다른 링크를 클릭해도 홈 UI는 항상 표시된다.  홈 링크에 `exact` 속성을 추가해 정확(exact)하게 패스가 일치할 때만 표시되도록 설정한다.&#x20;

```javascript
<NavLive to="/" exact>홈</NavLive>

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

{% hint style="info" %}
홈 링크를 설정할 땐 항상 exact를 설정하자!&#x20;
{% endhint %}

### 엄격한 경로 구분 설정

`strict` 속성이 설정된 경우, 현재 URL과 일치하는지 여부를 결정할 때 URL의 후미 슬래시를 고려한다.&#x20;

```javascript
<Route path="/one" exact strict>
  <Product />
</Route>
```

| 경로     | 경로 이름      | 매칭  |
| ------ | ---------- | --- |
| `/one` | `/one`     | 일치  |
| `/one` | `/one/`    | 불일치 |
| `/one` | `/one/two` | 불일치 |

#### 대소문자 구분 설정 <a href="#undefined" id="undefined"></a>

경로(path) 이름의 대소문자를 민감하게 구분하고자 한다면 `sesitive` 속성을 추가한다. &#x20;

```javascript
<Route path="/one" sensitive>
  <Product />
</Route>
```

| 경로     | 경로 이름  | 구분    | 매칭  |
| ------ | ------ | ----- | --- |
| `/one` | `/one` | true  | 일치  |
| `/One` | `/one` | true  | 불일치 |
| `/One` | `/one` | false | 일치  |

## Switch 컴포넌트&#x20;

자식 컴포넌트 중에 to나 path 값이 일치하면 그 곳에서 멈추고 들어간다. &#x20;

{% hint style="info" %}
Route 컴포넌트와 항상 같이 사용한다고 생각하기&#x20;
{% endhint %}

```javascript
<Switch> 
  <Route path="/about" component={About} />
  <Route path="/:user" component={User} />
  <Route path="*" component={NoMatch} />
</Switch>
```

## Link 컴포넌트

[Link](https://reacttraining.com/react-router/web/api/Link) 컴포넌트는 애플리케이션을 탐색하는 기능을 제공한다. `to` 속성 값으로 경로(path) 문자 값 또는 객체를 설정 할 수 있다. 네비게이션 처럼 클릭 했을 때 해당 패스로 이동하는 링크를 만드는 컴포넌트이다. to값과 일치하는 path로 이동한다.&#x20;

to 속성에 들어가는 값을 유형&#x20;

* string → 간단한 pathName일 때 사용한다.
* object → 객체 형식으로 path, search 등을 설정할 때 사용한다.&#x20;
* function → 중간에 source를 인터챕터(interchapter)하여 설정한다.&#x20;

#### Link 컴포넌트를 사용해서 props 내보내기&#x20;

to 속성에 객체 형식으로 담에서 보낼 수 있다.&#x20;

{% tabs %}
{% tab title="App.js" %}

```javascript
<Link
  to={{
    pathname: "/login",
    search: "?user=hanna&mento=yamoo",
    hash: "#router",
    state: {
      message: "로그인 링크를 통해 전달된 메세지",
      isAuthed: true
    }
  }}
>
```

{% endtab %}

{% tab title="SignInPage.js" %}

```javascript
export function SignInPage(props) {
  const { message, isAuthed } = props.location.state;
  console.log(message, isAuthed);
  return (
    <div>
      <p children={message}></p>
      <p
        children={
          isAuthed ? "로그인 사용자입니다." : "로그인 사용자가 아닙니다."
        }
      ></p>
    </div>
  );
}
```

{% endtab %}
{% endtabs %}

## NavLink 컴포넌트

* Link 컴포넌트에 스타일을 줄 수 있다.&#x20;
* 일반 Link와 다르게 aria-current 와 calss 속성이 추가 된다.&#x20;

즉, 활성화 된 상태 클래스 `active`가 자동으로 설정, 스타일링이 가능하다. Link 컴포넌트를 사용할 예정이라면 NavLink를 사용하는 것이 좋겠다.&#x20;

#### innerRef 설정 <a href="#innerref" id="innerref"></a>

React 앱(16+)에 React Router 5.1을 사용할 경우, 참조(ref)를 기본으로 `<a>`에 전달 하므로 [forwardRef](https://ko.reactjs.org/docs/forwarding-refs.html)를 별도로 설정할 필요가 없다. 일반 `ref` 속성을 사용하면 된다. &#x20;

```javascript
<Link
  to="/"
  innerRef={node => {
    // `node`는 마운트 된(mounted) DOM 요소를 참조하고,
    // 마운트가 해제 된 경우(unmount)는 null 입니다.
  }}
/>

<Link
  to="/"
  innerRef={node => { node.addEventListener('click', () => {node.style.color = '#a6cfff'})
  }}
/>
```

```javascript
class LinkRefDemo extends React.Component {
  
  anchorRef = React.createRef()

  render() {
    return (
      <Link to="/" innerRef={anchorRef} />
    )
  }

}
```

### 정확한 경로에서만 활성화

`exact` 속성은 경로가 정확히 일치할 때만 활성화 하도록 설정할 때 사용한다. 아래 코드 예시와 같이 `exact` 속성을 설정해야 `/lecture/chapter/*` 페이지에서 `/lecture` 경로의 내비게이션 링크가 활성화 되지 않는다.&#x20;

```javascript
<NavLink to="/lecture" exact>강의</NavLink>
<NavLink to="/lecture/chapter/1">1장</NavLink>
```

## Redirect 컴포넌트

여러 개의 Route를 설정 했으나 사용자가 사용자가 입력한 path와 일치하는 Route가 없다면 Redirect 컴포넌트에 설정된 to 속성 값으로 이동한다.&#x20;

아래의 예시 처럼 Redirect 컴포넌트를 사용할 수 있다. 페이지를 찾을 수 없다는 Route를 만들어 두고 알 수 없는 경로를 입력했을 때 사용자가 해당 페이지로 이동하여 오류임을 알 수 있도록 한다.&#x20;

사용자 경험을 위해 홈페이지로 이동할 수 있는 링크를 설정해준다.&#x20;

```javascript
<Route
  path="/page-not-found"
  render={() => {
    return (
      <div>
        <h1 lang="ko">페이지를 찾을 수 없습니다. 404</h1>
        <ZanzanNavLink to="/">홈 페이지로 돌아가기</ZanzanNavLink>
      </div>
    );
  }}
/>
<Redirect to="/page-not-found" />
```

#### from 속성&#x20;

Redirect의 from 속성의 값을 path로 검색했을 때 to에 설정된 path 값으로 이동한다.&#x20;

```javascript
// from : 문자열 설정
// url에 / 입력 시 /home으로 이동 
<Redirect exact from="/" to="/home" />
// url에 /users/:id 입력 시 /users/profile/:id으로 이동 
<Redirect from="/users/:id" to="/users/profile/:id" />
```

### example&#x20;

```javascript
// to : 문자열 설정
<Redirect to="/dashboard"/>

// to : 객체 설정
<Redirect to={{
  pathname: '/login',
  search: '?utm=your+file',
  state: {
    referrer: currentLocation
  }
}}/>

// push : 현재 history 항목을 바꾸지 않고, 새 항목 추가
<Redirect to="/dashboard" push />

// from : 문자열 설정
<Redirect from="/admin" to="/dashboard" />
<Redirect from="/users/:id" to="/users/profile/:id" />

// exact : 정확한 URL 매칭 설정
<Redirect exact from="/" to="/home" />

// strict : 엄격한 URL 매칭 설정
<Redirect strict from="/one/" to="/home" />

// sensitive : 대소문자  URL 매칭 설정
<Redirect sesitive from="/One/" to="/one" />
```

## Conclusion

{% tabs %}
{% tab title="index.js " %}
index.js(rootElement)에 라우터 설정  → Browser/HashRouter

```javascript
import { BrowserRouter as Router } from "react-router-dom";
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Router>
    <App />
  </Router>
);

```

{% endtab %}

{% tab title="App.js " %}

### 1. 모듈 불러오기&#x20;

* react-router-dom에서 사용할 컴포넌트를 불러 온다. → `Route`, `Redirect`&#x20;
* 페이지 모듈을 불러 온다.  → `HomePage`, `SignInPage`

```javascript
import React from "react";
import { Route, Redirect } from "react-router-dom";
import ZanzanNavLink from "./components/ZanzanNavLink";
import {
  // BrowsePage,
  HomePage,
  // ManageProfilePage,
  SignInPage
  // WatchPage
} from "./pages";

```

### 2.&#x20;

* NavLink 컴포넌트 사용자 정의 커스텀 사용 → ZanZanNavLink&#x20;
* NavLink 컴포넌트의 to 속성으로 경로 설정&#x20;

```javascript

export default function App() {

  return (
    <div className="App">
      <nav>
        <ZanzanNavLink exact to="/">
          홈
        </ZanzanNavLink>
      </nav>
      <Switch>
        <Route path="/" component={Home} exact /> 
        <Route path="/about" component={About} exact strict />
        <Route path="/:user" component={User} exact strict />
        <Route
          path="/page-not-found"
          render={() => <h1 lang="ko">페이지를 찾을 수 없습니다. 404</h1> }
        />
        <Redirect to="/page-not-found" />
      </Switch>
    </div>
  );
}
 
```

{% endtab %}

{% tab title="ZanzanNavLink.js" %}

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shhn0509.gitbook.io/react/react-router/basic-routing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
