React SPA (Single Page Application
)SPA
의 등장 배경과 개념전통적인 웹사이트에서는 사용자가 웹사이트 내의 다른 페이지로 이동하면, 브라우저가 페이지를 보여주기 위해 매번 HTML 파일로 된 "페이지 전체"를 불러와야만 했다.
웹사이트가 보다 복잡해지고 애플리케이션의 형태를 가지게 되면서, 사용자와 서비스 사이에 더욱 많은 상호작용이 일어나게 되었다.
하지만 이때마다 Header나 Navigation Bar 등과 같이 중복되는 요소들을 매번 불러오는 것이 서버와의 불필요한 트래픽을 발생시켰다.
한편, 사용자 입장에서는 매번 모든 페이지를 불러옴에 따라 더 느린 반응성을 갖게 되었고, 이는 애플리케이션과 같은 사용자 경험을 제공하기 어렵게 만들었다.
SPA
의 등장1990년대 후반에 HTML 문서 전체가 아닌, 업데이트에 필요한 데이터만 서버에서 전달받아 이 데이터를 JavaScript가 동적으로 HTML 요소를 생성해서 화면에 보여주는 방식이 개발되어 사용되기 시작하였다.
2000년대 중반부터 이러한 개발 방식을 이용한 웹 애플리케이션이 보편화되었으며,
이것이 우리가 지금 배우고 있는 싱글 페이지 애플리케이션, 즉 SPA
이다.
SPA
의 등장배경과 개념서버로부터 완전히 새로운 페이지를 불러오지 않고 페이지 갱신에 필요한 데이터만 받아 그 정보를 기준으로 현재의 페이지를 업데이트함으로써 사용자와 소통하는 웹 어플리케이션이나 웹 사이트.
SPA
의 장점전체 페이지가 아니라 필요한 부분의 데이터만 받아서 화면을 업데이트하면 되기 때문에 사용자와의 Interaction에 빠르게 반응한다.
서버에서는 요청 받은 데이터만 넘겨주면 되기 때문에 서버 과부하 문제가 현저하게 줄어든다.
전체 페이지를 렌더링 할 필요가 없기 때문에 더 나은 유저경험을 제공한다.
예시로는 유뷰트
, 페이스북
, 지메일
, 에어비앤비
, 넷플릭스
등이 있다.
SPA
의 단점브라우저는 첫 화면 로딩 시에 HTML 파일을 읽어들인 후 그 안의 script 요안에 있는 JavaScript 파일을 다시 받아오는 과정을 거친다.
이때 첫 화면 로딩 시 읽어들인 HTML 파일은 거의 비어있고, 대부분의 코드는 JavaScript 파일 안에 들어있다 보니 자연스럽게 JavaScript 파일이 무거워진다.
때문에 이 JavaScript 파일을 기다리는 시간으로 인해 첫 화면의 로딩 시간이 길어진다.
검색엔진 최적화
란 구글이나 네이버 같은 검색엔진이 자료를 수집하기 좋도록 웹 페이지를 구성하는 것을 뜻한다.✅검색 엔진의 작동 방식을 알아보면,
검색 로봇이 웹 페이지에 있는 정보를 수집하고 분석해서,
그 결괏값에 인덱스를 만들어 보관하고 있다가 사용자가 검색어를 입력하면,
보관하고 있던 인덱스에서 검색어와 가장 연관성이 높은 웹 페이지들을 순서대로 보여주는 방식으로 작동한다.
검색 로봇은 자료를 수집할 때에 웹 페이지의 URL은 물론이고 HTML 문서 내의 각종 태그나 링크 등을 분석합니다.
SPA는 HTML이 거의 비어있다 보니 검색 로봇이 충분한 자료를 수집하지 못한다.
이 때문에 검색 노출이 중요한 웹 애플리케이션은 검색 엔진 최적화에 대한 대응책을 따로 마련해야 하고,
더불어 앱 안에서 브라우저의 앞으로 가기/뒤로 가기 등의 상태 관리도 해야 하기 때문에 개발의 복잡도가 더욱 늘어난다.
다만 SPA에서도 검색 엔진 최적화에 대응할 수 있도록 검색 엔진이 발전하고 있어서, 점차 이 단점은 사라지고 있는 추세이다.
Wireframe
Wireframe
과Mockup
Wireframe
: 디자인에 들어가기 전 단계로 선(wire)를 이용해 윤곽선(frame)을 잡는 것.
- 이 작업을 통해 개발자는 디자인 컨셉과 사이트 기능에 대한 이해를 할 수 있다.
목업(mockup)
: 데스크톱, 스마트폰의 프레임을 덧씌워 직관적으로 이해하기 쉽게 디자인한 것
Header
라는 컴포넌트가 있고, 그의 자식으로 Search
와 Setting
이라는 컴포넌트를 만들기로 하자. Header
컴포넌트는 애플리케이션 내의 어떤 페이지에 가더라도 늘 상단에 위치하니 이 부분을 감안해서 설계 로직을 작성하자.ContentsList
라는 컴포넌트가 있고, Content라는 컴포넌트를 한 번만 만들어 재사용
하기로 하였다.컴포넌트들끼리 보다 유기적으로 주고받을 수 있도록 설계
해야 한다.React Router
SPA & Routing
"주소"
도 달라진다.라우팅
(Routing)이라고 한다.React Router?
React Router
라는 라이브러리를 가장 많이 사용한다.React Router
주요 컴포넌트BrowserRouter
Routes
와 Route
Link
React Router
라이브러리에서 따로 불러와야 한다.React Router
사용 환경 세팅1. react-router 라이브러리 설치
2. App.js로 react-router 컴포넌트 꺼내오기
Getting Started
npx create-react-app@latest simpleroute
cd simpleroute
npm start
npm install react-router-dom@^6.3.0
// # 이번 스프린트에서는 6.3.0 버전을 사용합니다
import React from 'react'
import { BrowserRouter, Routes, Route, Link } from "react-router-dom"; // 이 구문을 넣어주세요
페이지를 표시하는 컴포넌트 Home, MyPage, Dashboard를 만들어봅시다.
// Home 컴포넌트
function Home() {
return <h1>Home</h1>;
}
// MyPage 컴포넌트
function MyPage() {
return <h1>MyPage</h1>;
}
// Dashboard 컴포넌트
function Dashboard() {
return <h1>Dashboard</h1>;
}
페이지를 표시하는 컴포넌트를 만들었고, 각 컴포넌트로 이동할 메뉴를 제작합니다.
메뉴 제작을 위해 <ul>
요소와 <li>
요소를 이용합니다.
function App () {
return (
<div>
<nav>
<ul>
<li>
Home
</li>
<li>
MyPage
</li>
<li>
Dashboard
</li>
</ul>
</nav>
</div>
)
}
export default App;
BrowserRouter
<BrowserRouter>
컴포넌트는 웹 애플리케이션에서 HTML5의 History API를 사용해 페이지를 새로고침하지 않고도 주소를 변경할 수 있게 해 줍니다. 또한 <BrowserRouter>
가 상위에 작성되어 있어야 React Router의 컴포넌트들을 사용할 수 있습니다.
function App () {
return (
<BrowserRouter>
<div>
<nav>
<ul>
<li>
Home
</li>
<li>
MyPage
</li>
<li>
Dashboard
</li>
</ul>
</nav>
</div>
</BrowserRouter>
)
}
export default App;
아래와 같이 ReactDOM의 렌더 단계인 index.js 에 <BrowserRouter>
를 넣어서 활용할 수도 있습니다.
Routes, Route
경로를 매칭해 주는 역할을 하는 컴포넌트입니다.
<Routes>
컴포넌트는 여러 <Route>
컴포넌트를 감싸서 그중 경로가 일치하는 단 하나의 라우터만 렌더링을 시켜주는 역할을 합니다. <Routes>
를 사용하지 않으면 매칭되는 모든 요소를 렌더링합니다.<Route>
컴포넌트는 path
속성을 지정하여 해당 path
에서 어떤 컴포넌트를 보여줄지 정합니다. 아래에서 배울 <Link>
컴포넌트가 정해주는 URL 경로와 일치하는 경우에만 작동됩니다.이제 <Routes>
컴포넌트와 <Route>
컴포넌트들을 작성해 봅시다.
이제 <Routes>
컴포넌트와 <Route>
컴포넌트들을 작성해 봅시다.
<Route>
의 path
속성을 이용하여 경로를 작성합니다. 경로와 컴포넌트 이름이 동일해야 헷갈리지 않겠죠? <Route>
태그 안에 element
속성으로 연결하고자 하는 컴포넌트를 넣어줍니다.function App () {
return (
<BrowserRouter>
<div>
<nav>
<ul>
<li>
Home
</li>
<li>
MyPage
</li>
<li>
Dashboard
</li>
</ul>
</nav>
{/* 주소 경로와 아까 만든 3개의 컴포넌트를 연결해 줍니다. */}
{/* Routes 컴포넌트는 Route 컴포넌트들을 감싸고 있어야 합니다. */}
<Routes>
{/* 경로는 path로 컴포넌트는 element로 연결해 줍니다. */}
<Route path="/" element={<Home />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</div>
</BrowserRouter>
)
}
export default App;
팁❗
만약 사용자가 지정된 주소인“/"
,“/mypage”
,“/dashboard”
이외의 주소로 접근하게 되면 의도한 화면이 보이지 않을 수 있습니다. 이럴 때 사용할 수 있는 속성이path=”*”
입니다. 지정되지 않은 주소로 접근할 시에는 이 속성이 설정되어 있는 컴포넌트를 보여주게 됩니다.
Link
<Link>
컴포넌트는 <a>
요소로 바뀌는 모습을 볼 수 있습니다.React Router에서
<a>
요소가 아닌<Link>
를 사용하는 이유가 있나요?<a>
요소는 페이지를 전환하는 과정에서 페이지를 불러오기 때문에 다시 처음부터 렌더링을 시킵니다.
즉, 새로고침 현상이 일어나게 되죠.
하지만<Link>
컴포넌트는 페이지 전환을 방지하는 기능이 내장되어 있기 때문에 SPA를 구현할 수 있습니다.
이어서 <Link>
컴포넌트도 작성해 봅시다.
<Link>
의 to
속성을 활용하여 <Route>
컴포넌트에 설정해 준 path
주소를 연결해 줍니다.
function App() {
return (
<BrowserRouter>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
{/* Link 컴포넌트를 이용하여 경로를 연결합니다 */}
</li>
<li>
<Link to="/mypage">MyPage</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
{/* 경로는 path로 컴포넌트는 element로 연결해 줍니다. */}
<Route path="/mypage" element={<MyPage />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</div>
</BrowserRouter>
);
}
function Home() {
return <h1>Home</h1>;
}
function MyPage() {
return <h1>MyPage</h1>;
}
function Dashboard() {
return <h1>Dashboard</h1>;
}
export default App;
npm run start
를 통해 실제로 Create React App
프로젝트 환경에서 React Router
를 통해 SPA가 구현되었는지 확인해 봅시다.