React 입문(8) : React-Router(1) (last update: 2020.12.24.)

devpark·2020년 12월 24일
0

React.js & JavaScript

목록 보기
8/11

1. React-Router

0. References

react-router :: 1장. 리액트 라우터 사용해보기 - velopert.log
SPA (Single-page application) - MDN web docs


1. Introduction

실무에서 작성한 React 컴포넌트 및 페이지와 서버 측을 연결할 때가 왔다. 따라서 React-Router에 대한 개인 학습 및 일주일 내로 라우터 구축을 완료할 것을 새로운 업무로 받았다. Routing이라는 개념 자체는 생소하고, 한 번도 직접 구현해 본 적 없지만, 이는 그동안 react 관련 실무를 수행하고 리서칭을 진행하는 과정에서 정말 많이 들어본 단어이기도 하다. 예를 들어 Code Splitting에 관한 글 등을 읽을 때도 빠지지 않고 등장하는 단어가 바로 이 React-Router였고, 아직은 건드릴 파이가 너무 크다는 생각에 덮어뒀었다. 하지만 드디어 때가 왔다. 정말 중요한 개념일 거란 생각이 든다. 집중하고, 기초 이론부터 차근차근 시작해 실무에도 직접 적용해 보자.


Notion의 Theory & Technique : React.js 페이지 바로가기


2. Theory

2-1. Theory : SPA(Single Page Application) & Routing

전통적인 웹 어플리케이션의 구조는 여러 페이지로 구성되어 있었다. 이는 유저가 요청할 때마다 페이지가 새로 고침되며, 페이지를 로딩할 때마다 서버로부터 리소스를 전달받아 해석 후 렌더링을 했고, 어플리케이션의 뷰가 어떻게 보여질 지 또한 HTML 파일 혹은 템플릿 엔진 등을 사용해 서버에서 담당했다.

하지만 현대에서는 웹에서 제공되는 정보가 정말 많기 때문에 속도 면에서 문제가 있었고, 이를 해소하기 위하여 캐싱과 압축을 하여 서비스를 제공한다. 하지만 이는 사용자와 상호 작용이 많은 모던 웹 어플리케이션에서는 충분하지 않을 수도 있다. 렌더링 하는 것을 서버 쪽에서 담당한다는 것은 그 만큼 렌더링을 위한 서버 자원이 사용되는 것이고, 불필요한 트래픽도 낭비되는 것이므로.

그래서 우리는 React와 같은 라이브러리 혹은 프레임워크를 사용해서 뷰의 렌더링을 사용자의 브라우저가 담당하도록 하고, 먼저 어플리케이션을 브라우저에 불러온 다음 정말 필요한 데이터만 전달받아 노출한다. 이 때, 페이지가 1개인 어플리케이션을 바로 SPA라 하고, 이는 Single Page Application의 약자이다.

단, 싱글 페이지라고 해서 한 종류의 화면만 존재하는 것은 아니다. 예를 들어 블로그 플랫폼이 존재한다고 할 때, 메인 화면, 포스트 목록, 포스트, 글쓰기 등의 화면이 존재할 것이고 각 화면에 따라 별개의 주소를 만들어주어야 한다. 주소가 분리되어야 사용자들이 북마킹도 할 수 있고, 서비스에 구글 검색 등을 통해 유입될 수 있기 때문이다. 이렇게 다른 주소에 따라 다른 뷰를 보여주는 것을 바로 Routing이라고 한다. 리액트 자체에는 이 기능이 내장되어 있지 않기 때문에, 직접 브라우저의 API를 사용하고 상태를 설정하여 다른 뷰를 노출할 수 있도록 해야 한다.

이 때 사용할 수 있는 third party 라이브러리가 react-router이다. 공식은 아니지만 Routing을 위해 가장 많이 사용되고 있는 라이브러리이며 Client Side에서 이루어지는 routing을 간단하게 처리할 수 있게 해 준다. 또한, Server Side Rendering을 도와주는 tool들도 함께 사용이 가능해 진다. 참고로 이는 React Native(어플리케이션 제작을 위해 사용하는 React 프레임워크)에서도 사용이 가능하다.

결론적으로, 여러 화면으로 구성된 웹 어플리케이션 제작에서 react-router는 필수이다.

단, SPA(Single Page Application)의 단점은: 어플리케이션의 규모가 커지면 자바스크립트 파일의 사이즈도 함께 커진다는 것이다. 유저가 실제로 방문하지 않을 수도 있는 페이지와 연관된 렌더링 관련 스크립트도 불러오기 때문이다. 하지만 이는 Code Splitting을 통해 route 별로 파일을 나눠 트래픽 및 로딩 속도를 개선할 수 있다.


3. Tutorial

3-1. Type commands : create-react-app for react router tutorial

// create new react application for react router tutorial
$ create-react-app react-router-tutorial
// install react-router
$ yarn add react-router-dom
$ yarn add cross-env --dev


이 중, 설치할 react-router에 관한 설명은 다음과 같다:

`react-router-dom` : 브라우저에서 사용되는 React Router

`cross-env` : 프로젝트에서 NODE_PATH를 사용하여 절대 경로로 파일을 불러오기 위해 환경 변수를 설정할 때, 다른 방식의 운영 체제들도 공통적인 방법의 설정이 가능하게 만들어주는 라이브러리

---


### 3-2. Initialize Project also Set up Structure

`delete files`

1. src/App.js
2. src/App.css
3. src/App.test.js
4. src/logo.svg

`generate directory`

1. src/components : Components를 위치시킬 디렉토리
2. src/pages : Routes를 위치시킬 디렉토리
3. src/client : 브라우저 측에서 사용할 최상위 컴포넌트. 클라이언트 사이드 렌더링을 구현할 때 라우터 설정할 디렉토리
4. src/server : 서버 측에서 사용할 리액트 관련 코드를 위치시킬 디렉토리
5. src/shared : 서버와 클라이언트에서 공용으로 사용되는 컴포넌트 App.js를 위치시킬 디렉토리
6. src/lib : 웹 연동을 구현할 때 사용할 API와 Code Splitting 할 때 필요한 코드들을 위치시킬 디렉토리

`Set up : NODE_ENV`

> ```json
"scripts": {
	"start": "cross-env NODE_PATH=src react-scripts start",
	"build": "cross-env NODE_PATH=src react-scripts build",
	"test": "react-scripts test --env=jsdom",
	"eject": "react-scripts eject"
}

코드들을 불러올 때 "../components/Something"과 같은 식으로 불러오지 않고, 'component/Something'의 형식으로 불러올 수 있도록 프로젝트의 루트 경로를 위와 같이 설정 해 준다. 이는 src/package.json에서 "scripts" 항목을 찾아서 수정하면 된다.


3-3. Prepare Components

src/shared/App.js

import React, { Component } from 'react';
class App extends Component{
	render(){
		return(
			<React.Fragment>
				Hello React-Router
			</React.Fragment>
		);
	}
}
extends default App;

우선 비어있는 컴포넌트를 shared 경로에 생성한다. 이후, 넘어온 주소에 따른 뷰를 정의하도록 한다.

src/client/Root.js

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import App from 'shared/App';
const Root =()=> (
	<BrowserRouter>
		<App/>
	</BrowserRouter>
);
export default Root;

그 다음, Root Component를 생성한다. 이 컴포넌트를 통해 웹 어플리케이션에 BrowserRouter를 적용하게 된다. 이후 Redux를 적용하게 될 때, 이 Root.js에서 Provider를 통해 프로젝트에 Redux를 연결하게 된다.

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Root from './client/Root'
// import registerServiceWorker from './registerServiceWorker';
import './index.css';
ReactDOM.render(<Root />, document.getElementbyId('root'));
// registerServiceWorker();

!! ISSUE !!
registerServiceWorker의 import문에서 해당 요소를 찾을 수 없기 때문에 compile이 불가하다는 에러가 발생했다. (MODULE NOT FOUND : Module not found: Can't resolve './registerServiceWorker' in 'C:\Workspaces\react-router-tutorial\src') 검색해 보니 이 문제가 발생하는 경우가 꽤 많은 모양이고, 버전이 업데이트 되면서 기본 module에서 빠졌을 가능성 등이 크다. 새로운 react app을 PowerShell의 커맨드를 통해 생성해 보았을 때도 해당 모듈이 존재하지 않았기 때문이다. registerServiceWorker가 어떤 역할을 하는 것인지 검색 해 보니, 이는 네트워크가 느리거나 오프라인 상태에서도 온라인인 것처럼 리소스를 캐싱해서 보여주는, 기본 모듈 중 하나라고 한다. 이 말은 요컨대, 필수 모듈은 아니라는 뜻이다. 따라서 예제에서 해당 구문은 주석처리 하였다.


3-4. Route & Parameter : Basic Route

src/pages.Home.js

import React from 'react';
const Home =()=>(
	return(
		<div>
			<h2>
				Home
			</h2>
		</div>
	);
);
export default Home;

첫 Route 예제로 Home을 생성한다.
이는 주소에 아무런 path도 주어지지 않았을 때 기본적으로 보여주는 route이다.

src/pages/About.js

import React from 'react';
const About =()=>{
	return(
		<div>
			<h2>About</h2>
		</div>	
	);
};
export default About;

같은 형식으로 About을 생성한다. 이 페이지는 /about 경로로 접속했을 때 노출할 페이지이다.

src/pages/index.js

export { default as Home } from './Home';
export { default as About } from './About';

라우트에 맞춰 컴포넌트를 노출할 수 있도록 App 컴포넌트를 위와 같이 수정한다.


3-5. Router Set up

rc/shared/App.js`

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Home, About } from 'pages';
class App extends Component{
	render(){
		return(
			<div>
				<Route exact path="/" component={ Home } />
				<Route path="/about" component={ About } />
			</div>
		);
	}
}
export default App;

라우트를 설정할 때는 Route 컴포넌트를 사용하고, 경로는 path 값으로 설정한다. 첫 번째 라우트 /의 경우에는 Home Component를 대입하고, 두 번째 라우트 /about에는 About 컴포넌트를 보여주게 했다. 단, 첫 번째 라우트의 경우에는 경로 설정 시에 exact를 추가로 선언하였는데, 이는 곧 주어진 경로와 정확히 맞아 떨어져야만 설정한 컴포넌트를 노출한다는 의미이다.

Result


profile
아! 응응애에요!

0개의 댓글