본문 바로가기

개발인생다반사/TIL(Today i learned)

TIL 210812 - React SPA(Single Page App)

고차함수까지는 기본적인 내용이라면

React 부터는 실전에서 진짜로 사용하는 것들이다.

멈추어서는 안된다.

 

egaging booster!! 부릉부릉

 

자 SPA 시작!

 

React SPA

Achievement Goals

  • SPA(Single-Page Application) 개념을 이해하고 설명할 수 있다.
  • SPA의 장, 단점에 대해 이해하고 설명할 수 있다.
  • 와이어프레임을 보고 어느 부분을 컴포넌트로 구분할 지 스스로 정할 수 있다.

 

전통적인 페이지는 사용자가 다른 웹페이지로 이동하면

이동할 때마다 HTML 파일 전체를 불러와서 보여줘야 했다.

 

전통적인 웹사이트는 페이지 전체를 로딩하고

SPA 사이트는 Menu나 Footer와 같은 중복되는 부분은

불러오지 않는다.

 

전통적인 웹사이트는 매번 HTML을 새로 불러와야 하기 때문에

불필요한 트래픽을 발생시킨다.

 

사용자 입장에서는 웹사이트가 느리게 반응하는 불편함이 있다.

 

 

그래서 SPA가 등장

업데이트에 필요한 데이터만 서버에서 전달받아 이 데이터를 J

avaScript가 동적으로 HTML 요소를 생성해서 화면에 보여주는 방식이 개발되어 사용

 

단점은

1. js 양이 많아서 첫로딩에 시간이 많이 걸린다. 

2. 검색엔진 최적화에 좋지 않다.

구글, 네이버는 HTML 파일에 있는 자료를 수집, 분석하여 

그 결과값에 인덱스를 만들어 보관하고 있다가 

사용자가 검색어를 입력하면 보관하던 인덱스에서 

검색어와 가장 연관성이 높은 웹페이지 부터 보여준다.

SPA는 HTML에 정보가 별로 없기 때문에 검색 엔진에

제대로 작동을 하지 않는다.

 

더보기

검색엔진 최적화란 구글이나 네이버같은 검색엔진이 자료를 수집하기 좋도록 웹 페이지를 구성하는 것

 

SPA는 검색 노출을 위한 대응책을 따로 마련해야 한다.

브라우저의 앞으로 가기 /뒤로 가기 등의 상태 관리도 해야 하기 때문에

개발의 복잡도가 늘어남.

 

다만 최근에 SPA도 검색 엔진이 수집할 수 있도록

검색엔진이 발전하고 있어서 이 단점도 나중에는 사라질 수 있다.

 

자 SPA 끝!

 

 

Wireframe : 디자인에 들어가기 전 wire를 이용해 윤곽(frame)을 잡는 것

개발자는 디자인 컨셉과 기능에 대한 이해도를 높일 수 있다.

 

Mockup : 데스크톱이나 스마트폰 프레임을 씌워 직관적으로 이해하게 하는 것

 

그래서 페이지를 개발하기 전

컴포넌트를 먼저 만들고 조립한다.

 

고차원의 React 개발자라면, 어플리케이션 안에서 다뤄지는 데이터를

컴포넌트들끼리 보다 유기적으로 주고 받을 수 있도록 설계해야 한다.

 

 

얼른 얼른 진행하자! go faster!

 

React Router

Achievement Goals

  • React에서 npm으로 React Router DOM을 설치(npm install react-router-dom)하고 이용할 수 있다.
  • React Router DOM를 이용하여 SPA를 구현할 수 있다.
  • 라우팅 구조를 짤 수 있어야 하고, 이에 필요한 기초 문법들을 사용할 수 있어야 한다.

하나의 웹사이트를 만들어도 그 안에 무수히 많은 사이트가 있으면

사이트마다 주소도 모두 다르다.

 

다른 주소에 따라 다른 뷰를 보여주는 과정을

"경로에 따라 변경한다."라는 의미로 라우팅(Routing) 이라고 한다.

 

리액트에 라우팅 기능이 없어서

리액트 라우팅 라이브러리를 사용한다.

 

 

 

라우터 역할을 하는 BrowserRouter,

경로를 매칭해주는 Switch 와 Route,

그리고 경로를 변경하는 역할을 하는 Link

이 컴포넌트들을 사용하기 위해서는

React Router 라이브러리에서 따로 불러와야 한다.

 

 

 

4. 주소에 따라 페이지 뷰 다르게 만들기

  • 이제 위에서 만든 3개의 컴포넌트를 "주소"에 따라 다르게 만듭니다.
    • Home 페이지의 주소 "/"
    • MyPage 페이지의 주소 "/mypage"
    • Dashboard 페이지의 주소 "/dashboard"
  • App.js 에 라우팅을 하기 위한 React Router DOM 주요 컴포넌트를 세팅합니다. 이 컴포넌트를 이용해서 우리가 원하는 "주소에 따른 다른 페이지"를 구현할 수 있습니다. 앞선 슬라이드에서 학습한 개념들을 간단히 정리해 보겠습니다.

BrowserRouter

BrowserRouter는 웹 애플리케이션에서 HTML5의 History API를 사용해 페이지를 새로고침하지 않고도 주소를 변경할 수 있는 역할을 해줍니다. 아래와 같이 ReactDOM의 렌더 단계인 index.js 에 넣어서 활용할 수도 있습니다. BrowserRouter가 상위에 작성되어 있어야 Route 컴포넌트를 사용할 수 있습니다.

index.jsimport React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; ReactDOM.render(<BrowserRouter><App/></BrowserRouter>, document.querySelector('#root'));
Switch, Route

경로를 매칭해주는 역할을 하는 컴포넌트입니다.

  • <Switch> 컴포넌트는 여러 <Route>를 감싸서 그 중 경로가 일치하는 단 하나의 라우터만 렌더링을 시켜주는 역할을 합니다. <Switch> 를 사용하지 않으면 매칭되는 모든 요소를 렌더링합니다.
  • <Route> 컴포넌트는 path 속성을 지정하여 해당 path에 어떤 컴포넌트를 보여줄지 정합니다. 아래에서 배울 Link 컴포넌트가 정해주는 URL 경로와 일치하는 경우에만 작동됩니다.

Link

경로를 연결해주는 역할을 하는 컴포넌트입니다. 페이지 전환을 통해 페이지를 새로 불러오지 않고 애플리케이션을 그대로 유지하여 HTML5 History API 를 이용해 페이지의 주소만 변경해 줍니다.

ReactDOM으로 렌더를 시키게 되면 <Link> 컴포넌트는 <a> 태그로 바뀌는 모습을 볼 수 있습니다.

React Router 에서 <a> 태그가 아닌 <Link>를 사용하는 이유가 있나요? <a>태그는 페이지를 전환하는 과정에서 페이지를 불러오기 때문에 다시 처음부터 렌더링을 시킵니다. 즉, 새로고침 현상이 일어나게 되죠. 하지만 <Link> 컴포넌트는 페이지 전환을 방지하는 기능이 내장되어있기 때문에 SPA를 구현할 수 있습니다.


개념에 대해 이해를 하였다면 본격적으로 코드 구성을 진행하겠습니다.

  • <BrowserRouter> 로 <Route> 컴포넌트를 이용하기 위한 환경을 세팅합니다.

function App () { return ( {/* Route 를 사용하기 위한 설정을 진행합니다 */} <BrowserRouter> <div> <nav> <ul> <li> Home </li> <li> MyPage </li> <li> Dashboard </li> </ul> </nav> </div> </BrowserRouter> ) } export default App;

  • <Switch> 와 <Route> 로 주소 경로와 아까 만든 3개의 컴포넌트를 연결해줍니다.
    • <Route>의 path 속성을 이용하여 경로를 작성합니다. 경로와 컴포넌트 이름이 동일해야 헷갈리지 않겠죠? <Route> 태그 안에 연결하고자 하는 컴포넌트를 넣어줍니다.

function App () { return ( <BrowserRouter> <div> <nav> <ul> <li> Home </li> <li> MyPage </li> <li> Dashboard </li> </ul> </nav> {/* 주소경로와 우리가 아까 만든 3개의 컴포넌트를 연결해줍니다. */} <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/about"> {/* 경로를 설정하고 */} <MyPage /> {/* 컴포넌트를 연결합니다. */} </Route> <Route path="/dashboard"> <Dashboard /> </Route> </Switch> </div> </BrowserRouter> ) } export default App;

1. Home 컴포넌트 Route 에만 존재하는 exact 라는 것을 보았습니다, 언제 쓰는건가요? React router의 특성상 exact속성이 없으면 해당 경로(예시의 "/")로 시작하는 중복된 <Route> 컴포넌트를 모두 보여줍니다. exact는 주어진 경로와 정확히 일치해야만 설정한 <Route> 컴포넌트를 보여주는 역할을 합니다.

pathlocation.pathnameexactmatches?

/one /one/two true no
/one /one/two false yes

[표] exact 속성의 유무에 따른 라우팅 분기

2. exact 속성을 쓰지 않고도 페이지가 전환되는 것을 봤습니다. 왜 그런건가요? <Switch> 를 사용하여 exact 역할을 대신 해주는 경우입니다. 하지만 <Switch>는 순서와 위치가 중요합니다. 위에서 아래로 경로를 하나씩 검사하면서 해당 경로에 해당하는 라우트를 실행시키기 때문입니다. 이런 경우, 비교할 라우트를 더 상단에 작성해야 합니다. 하지만 만약 위의 예제처럼 Home을 위에 둔 상태에서 exact없이 활용한다면 어떻게 될까요? 중복되는 경로로 인해 다른 라우트로의 이동이 불가능한 것을 확인하실 수 있습니다. 이를 해결하는 방법으로 exact를 사용할 수 있습니다.

 

  • <Link> 의 to 속성을 활용하여 Route 컴포넌트에 설정해준 path 주소를 연결해줍니다.

function App() { return ( <BrowserRouter> <div> <nav> <ul> <li> <Link to="/">Home</Link>{/* Link 컴포넌트를 이용하여 경로를 연결합니다 */} </li> <li> <Link to="/about">MyPage</Link> </li> <li> <Link to="/dashboard">Dashboard</Link> </li> </ul> </nav> <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/about"> <MyPage /> </Route> <Route path="/dashboard"> <Dashboard /> </Route> </Switch> </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 DOM을 통해 SPA가 구현되었는지 확인해 봅시다. 아래와 같이 작동한다면 코드가 올바르게 작성된 겁니다.

 

 

Achievement Goals

  • npm 을 이용해 react-router-dom을 설치할 수 있다.
  • 컴포넌트 단위로 Client-side routing 을 할 수 있다.
  • react-router-dom 를 활용하여 Twittler SPA를 구현할 수 있다