SPA : Single Page Application. 한 개의 페이지로 이루어진 애플리케이션.
기존에는 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아 오고, 페이지를 로딩할 때 마다 서버에서 리소스를 전달받아 해석한 뒤 화면에 보여주었다. 이렇게 사용자에게 보이는 화면은 서버 측에서 준비했다. 사전에 html 파일을 만들어서 제공하거나, 데이터에 따라 유동적인 html을 생성해주는 템플릿 엔진을 사용함.
하지만 웹에서 제공하는 정보가 많아짐에 따라 새로운 화면을 보여주어야 할 때마다 서버측에서 모든 뷰를 준비하게 되면 성능상의 문제가 발생한다. 트래픽이 너무 많이 나오고, 사용자가 몰려 서버에 높은 부하가 쉽게 걸릴 수도 있다. 애플리케이션 내에서 화면 전환이 일어날 때마다 html을 계속 서버에 새로 요청하면 사용자의 인터페이스에서 사용화고 있는 상태를 유지하는 것도 번거롭고, 바뀌지 않은 부분까지 새로 불러와서 보여주어야 함으로 비효율적.
리액트 같은 라이브러리나 다른 프레임워크를 사용하여 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고, 우선 애플리케이션을 브라우저에 불러와서 실행시킨 후에 사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트를 해준다. 새로운 데이터가 필요하다면 서버 api를 호출하여 필요한 데이터만 새로 불러와 애플리케이션에서 사용할 수 있다.
SPA의 경우 서버에서 사용자에게 제공하는 페이지는 한 종류이지만, 해당 페이지에서 로딩된 자바스크립트와 현재 사용자 브라우저의 주소 상태에 따라 다양한 화면을 보여 줄 수 있다.
SPA의 단점
앱의 규모가 커지면 자바스크립트의 파일이 너무 커진다는 것. 페이지 로딩 시 사용자가 실제로 방문하지 않을 수도 있는 페이지의 스크립트도 불러오기 때문. 이는 코드 스플리팅을 사용하면 라우트별로 파일들을 나누어서 트랙픽과 로딩 속도를 개선할 수 있다.
라우팅
다른 주소에 다른 화면을 보여주는 것.
리액트 라이브러리 자체에 이 기능이 내장되어 있지 않다. 그 대신 브라우저의 api를 직접 사용하여 이를 관리하거나, 라이브러리를 사용하여 이 작업을 더욱 쉽게 구현가능. 그래서 리액트 라우터를 사용하는 것. 이외에도 Next.js 도 있음. 리액트 라우터는 클라이언트 사이드에서 이루어지는 라우팅을 아주 간단하게 구현할 수 있도록 해준다. 리액트 라우터처럼 브라우저에서 자바스크립트를 사용하여 라우팅을 관리하는 것은 자바스크립트를 실행하지 않은 일반 크롤러에서는 페이지의 정보를 제대로 수집해 가지 못한다는 잠재적인 단점이 따른다. 이러한 문제는 서버 사이드 렌더링을 통해 해결 할 수 있다. 나중에 공부할 것.
reat-router-dom 설치
yarn add react-router-dom
#프로젝트에 라우터 적용.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import './index.css';
import App from './App';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Link 컴포넌트.
기존에는 a태그를 사용했으나, 리액트에서는 사용하면 안된다. a태그는 이 페이지를 전환하는데, 페이지를 새로 불러오기 때문. 그렇게 되면 애플리케이션이 들고 있던 상태를 모두 날려 버리게 됩니다. 렌더링된 컴포넌트들도 모두 사라지고 다시 처음부터 렌더링하게 된다.
반면에 link 컴포넌트를 사용하면 페이지를 전환하면, 페이지를 새로 불러오지 않고 애플리케이션은 그대로 유지한 상태서 HTML History API를 사용하여 페이지의 주소만 변경해준다. link 컴포넌트 자체는 a 태그로 이루어져있지만, 페이지 전환을 방지하는 기능이 내장되어 있다.
<Link to="주소"></Link>
쿼리는 location 객체에 들어 있는 search값에서 조회할 수 있습니다. location 객체는 라우트로 사용된 컴포넌트에게 props로 전달되며, 웹 애플리케이션의 현재 주소에 대한 정보를 가지고 있다.
import React from "react";
import qs from "qs";
const About = ({ location }) => {
const query = qs.parse(location.search, {
ignoreQueryPrefix: true
})
const showDetail = query.detail === 'true';
return (
<div>
<h1> 소개 </h1>
<p> 이 프로젝트 리액트 라우터 기초를 실습해 보는 예제 프로젝트이다. </p>
{showDetail && <p>detail 값을 true로 설정하셨군요! </p>}
</div>
);
};
export default About;
서브 라우트는 라우트 내부에 또 라우트를 정의하는 것을 의미한다. 라우트로 사용되고 있는 컴포넌트의 내부에 Route 컴포넌트를 또 사용하면 된다.
import React from "react";
import { Link, Route } from "react-router-dom";
import Profile from "./Profile";
const Profiles = () => {
return (
<div>
<h3>사용자 목록 : </h3>
<ul>
<li>
<Link to="/profiles/mia">Mia</Link>
</li>
<li>
<Link to="/profiles/jun">Jun</Link>
</li>
</ul>
<Route path="/profiles" exact render={() => <div> 사용자를 선택해주세요</div>}></Route>
<Route path="/profiles/:username" component={Profile} />
</div>
);
};
export default Profiles;