article thumbnail image
Published 2021. 9. 16. 19:30

React SPA

학습 목표

* SPA(Single-Page Application)의 개념
* SPA의 장, 단점
* 와이어프레임을 보고 컴포넌트 구분하기

SPA(Single-Page Application)

SPA의 등장 배경, 개념, 장단점

SPA의 등장 배경과 개념

전통적인 웹사이트에서는 사용자가 웹사이트 내 다른 페이지 이동시 브라우저가 매번 “페이지 전체”를 불러옴
→ 페이지 전체를 불러오는 행위: 깜빡인다
→ 중복되는 요소들도 매번 로딩해서 불필요한 트래픽 발생시키고 느리게 함
→ 웹사이트가 복잡해지고 애플리케이션 형태로 되며 사용자와 서비스 사이의 상호작용이 증가하며 이 방식의 한계점

 
SPA의 경우 Menu, Footer와 같이 페이지 전환 후 중복되는 부분은 새로 로딩하지 않는다
→ 업데이트가 필요한 부분(데이터)만 새로 불러온다
→ 2000년대 중반부터 이러한 개발 방식을 이용한 웹 애플리케이션이 보편화됨(SPA)
 
정리하면 SPA란 서버로부터 완전히 새로운 페이지를 불러오는 것이 아니라, 화면을 업데이트하기 위해 필요한 데이터만 서버에서 전달 받아 브라우저에서 해당하는 부분만 업데이트하는 방식으로 작동하는 웹 애플리케이션이나 웹 사이트

SPA의 장점

* 사용자와의 빠른 상호작용:
전체 페이지가 아니라 필요한 부분의 데이터만 받아 화면에 업데이트하므로

* 서버 과부하 감소:
서버에는 요청받은 데이터만 넘겨주면 되기 때문에 과부하 문제가 감소

* 더 나은 사용자 경험:
전체 페이지를 새로 렌더링할 필요가 없기 때문

 
SPA방식 서비스의 대표적인 예: 유튜브, facebook, Gmail, 넷플릭스 등 많은 서비스 등

SPA의 단점

* 긴 첫 화면 로딩 시간:

SPA의 경우 JavaScript 파일의 크기가 큰데, 이 때문에 이 JavaScript 파일을 기다리는 시간으로 인해 첫 로딩 시간이 김

 브라우저는 첫 화면 로딩 시 HTML 파일을 읽고 그 안에 script tag의 JavaScript 파일을 다시 받아오는 과정을 거침.
→ SPA의 경우 html 파일은 거의 비어 있고 대부분의 코드가 JavaScript 파일에 들어 있다
이를 기다리는 시간 때문에 첫 로딩이 길어짐

* 검색 엔진 최적화가 좋지 않음:

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

검색 엔진은 자료 수집 시 HTML 파일에 있는 자료를 분석하는 방식으로 동작함
→ SPA는 html 파일이 거의 비어 있기 때문에 검색 엔진이 적절히 동작 못함
→ SPA에서도 검색 엔진 최적화에 대응할 수 있도록 검색 엔진이 발전하고 있어서 단점이 사라지는 추세

Wireframe

컴포넌트를 어떻게 나눌지 고민하는 과정
→ 어떤 컴포넌트를 생성하고 어떻게 조합 할지에 대한 구상

유튜브 만들기의 예

화면 상단

검색 창을 구현
 

상단 전체에 <Header />
그 자식 컴포넌트 <Search /> 와 <Setting />

 
<Header />는 애플리케이션 내의 어떤 페이지에 가더라도 늘 상단에 위치
→ 모든 페이지마다 따로 만들 것이 아니라 한번만 만들어서 모든 페이지에서 사용할 수 있도록 로직 구상

화면 중앙

영상 리스트가 나오는 곳

 

<ContentList />        // 크리에이터들이 올린 영상들을 담고 있음

    <Content />        // 각 영상들의 정보

 
컨텐츠 리스트 안에 컨텐츠 컴포넌트가 들어가 있는 구조인데, 동일한 형태를 가진 영상물들이 반복적인 형태로 화면을 구성
<Content /> 를 한번만 만들어서 재사용
→ 나열되는 영상 정보들은 디테일은 달라도 기능과 layout이 동일하기 때문

이게 끝?

가장 작은 단위의 컴포넌트인 를 분석해 보면 그 안에서도 다양한 정보가 있다
 

썸네일, Description, Channel name, Date, Views , …

 
→ 이렇게 애플리케이션 안에서 다뤄지는 데이터를 컴포넌트끼리 유기적으로 주고 받을 수 있도록 설계가 필요

 


React Router

학습 목표

* React Router DOM 설치: npm install react-router-dom

* React Router DOM을 이용한 SPA 구현

* 라우팅 구조 구현 및 이에 필요한 기초 문법

React Router

React Router를 이용한 React SPA 개발

SPA 와 Routing

SPA는 하나의 페이지를 가지고 있지만 사실 한 종류의 화면만 사용하진 않는다
→ 예를 들어 Twittler 같은 SPA 생성 시를 생각

메인 트윗 모음 페이지
알림 페이지
마이 트윗 페이지 등

이와 같은 다른 페이지들도 필요
→ 이 화면에 따라 주소도 달라진다
 

라우팅(Routing) : 이렇게 다른 주소에 따라 다른 뷰를 보여주는 과정을 말함. “경로에 따라 변경한다” 는 의미
→ React 자체에는 이 기능이 내장되어 있지 않으므로 React Router 라이브러리 사용

React Router 주요 컴포넌트

주요 컴포넌트는 크게 3가지로 나눈다
 

* router(라우터 역할): <BrowserRouter />

* route matchers(경로를 매칭): <Switch />, <Route />

* route changer(경로를 변경): <Link />

 
이 컴포넌트들을 사용하기 위해서는 명령어로 React Router 라이브러리에서 불러와야 함
 

import { BrowserRouter, Switch, Route, Link } from “react-router-dom”

React Router 사용 환경 세팅

1.react-router 라이브러리 설치
 

// 특정 폴더명(simpleroute)으로 React App 설치
> npx create-react-app simpleroute
> cd simpleroute

// react-router 라이브러리 설치
> npm install react-router-dom

 

2.App.js로 react-router 컴포넌트 꺼내오기(import)
 
컴포넌트를 꺼내오기 위한 import 구문 작성
 

import React from “react”;

import { BrowserRouter, Switch, Route, Link } from “react-router-dom”;    //react-router 컴포넌트를 import 해주는 구문을 추가

export default function App)(){
    return  (...)
}

React Router Hands-on 실습

React 웹 애플리케이션 목업을 통한 실습
 

<최소 조건>
* React Router DOM 의 주요 컴포넌트들을 이용해 주소에 따른 3가지 뷰(Home, MyPage, Dashboard) 제공
- Home 페이지의 주소 “/”
- MyPage 페이지의 주소 “/mypage”
- Dashboard 페이지의 주소 “/dashboard”

Route 준비

App.js 하단에 아래 코드 작성
 

// 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

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

Switch, Route

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

`<Switch>`: 여러 `<Route>`를 감싸서 그 중 경로가 일치하는 단 하나의 라우터만 렌더링 시켜주는 역할. `<Switch>`를 사용하지 않으면 매칭되는 모든 요소를 렌더링함

`<Route>`: path 속성을 지정하여 해당 path에 어떤 컴포넌트를 보여줄지를 정함. Link 컴포넌트가 정해주는 URL 경로와 일치하는 경우에만 작동

Link

경로를 연결 해 주는 역할을 하는 컴포넌트.
페이지 전환을 통해 페이지를 새로 불러오지 않고 애플리케이션을 그대로 유지하여 HTML5 History API를 이용해 페이지의 주소만 변경해 줌
 
→ ReactDOM으로 렌더를 시키면 <Link> 컴포넌트는 <a> 태그로 바뀌는 모습을 볼 수 있다

 

React Router 에서 <a> 태그가 아닌 <Link>를 사용하는 이유가 있나요?

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

본격적인 코드 구성 진행

1.<BrowserRouter><Route> 컴포넌트를 이용하기 위한 환경을 세팅

 
2.<Switch><Route> 로 주소 경로와 아까 만든 3개의 컴포넌트를 연결해 준다
 

  • Home 컴포넌트 Route 에만 존재하는 exact 라는 것을 보았습니다, 언제 쓰는건가요?

React router의 특성상 exact속성이 없으면 해당 경로(예시의 "/")로 시작하는 중복된 <Route> 컴포넌트를 모두 보여줍니다. exact는 주어진 경로와 정확히 일치해야만 설정한 <Route> 컴포넌트를 보여주는 역할을 합니다.

 

  • exact 속성을 쓰지 않고도 페이지가 전환되는 것을 봤습니다. 왜 그런건가요?

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

 

3.<Link> 의 to 속성을 활용하여 Route 컴포넌트에 설정해준 path 주소를 연결
 
전체 작성한 코드를 통해 확인 후 npm run start로 정상 구동 확인해보기
 

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;

 


React Twittler SPA

Advanced Challenge

App.js에 있는<BrowserRouter>를 index.js 로 옮겨보세요. 그리고 Router라는 이름을 붙여보세요.앞서 설명한 것처럼 위 컴포넌트를 index.js에서 활용할 수 있다고 했습니다. 그리고 as를 이용해서 별칭을 붙일 수 있습니다.

 

import { BrowserRouter as Router} from 'react-router-dom';

ReactDOM.render(<Router><App/></Router>, document.querySelector('#root'));

 

history 구현하기?

history 메소드를 작성한 파일에서 withRouter를 입혀줘야 한다!

 

ex) history 작성한 파일 내에서

import { withRouter } from "react-router";

…

export default withRouter(HistoryTest);

react-router-dom의 withRouter 컴포넌트를 사용하여 export로 내보내는 부분의 함수 명을 ()로 감싸준 뒤, 화살표 함수의 인자를 넣는 부분에 props를 넣으시면 props 객체로 history가 들어감을 확인을 할 수가 있습니다.
내가 history를 사용하고자 하는 컴포넌트만 withRouter로 감싸주시고 인자로 props를 주시면 충분히 컴포넌트 내에서 사용 가능합니다.
만일 의도했던 대로 동작이 되지 않으면 기동하고 있던 앱을 한 번 종료를 했다가 다시 기동을 해서 확인을 해주세요.
혹은 현재 내가 위치하고 있는 주소를 확인 해주시면 됩니다. (컴포넌트는 다 주소와 연결이 되어 있습니다)

 


zoom 강의 내용 정리

react-router 패키지는 선택 패키지이므로 기본적으로 내장되어 있지 않다
→ npm install react-router-dom 으로 설치해야 함
 
route는 주소를 지정 해주는 것이고
link는 지정된 주소로 가게 해주는 역할
 
import를 해서 가져올 땐 내보내는 쪽에서는 맨 하단에

export default 내보내는파일명    //으로 써줘야함

 

TODO : dummyTweets중 kimcoding 이 작성한 트윗 메세지만 있어야 합니다. 을 작성할때
 

<li className="tweet" id={filteredTweets[0].id}>
// 나중에 키로 쓴다면 key값을 지정을 반드시 해줘야 한다

 

<Switch>의 위치는 <Route>를 감싸는 구조로 위치하면 된다
 

import { Link } from 'react-router-dom';
// react-router-dom 패키지 안에는 메소드가 많이 있는데 이중에서 Link 하나만 가져올 때는
{}를 이용해 구조 분해 해서 특정 메소드만  가져오는 것이다

import Footer from "../Footer";
// 여기서는 Footer 안에 Footer 메소드 하나밖에 없으므로 이렇게 써도 된다

 


'SE Bootcamp 내용 정리' 카테고리의 다른 글

SECTION 1 회고  (0) 2021.09.30
React - 기초 - 3  (0) 2021.09.17
React – 기초  (0) 2021.09.15
js/node – 고차 함수  (0) 2021.09.15
js/browser - DOM -2  (0) 2021.09.13
복사했습니다!