Day +28

비트·2023년 5월 19일
0

CodeStates

목록 보기
29/54
post-thumbnail

React SPA (Single Page Application)

SPA의 등장 배경과 개념

전통적인 웹사이트에서는 사용자가 웹사이트 내의 다른 페이지로 이동하면, 브라우저가 페이지를 보여주기 위해 매번 HTML 파일로 된 "페이지 전체"를 불러와야만 했다.

  • 전통적인 웹사이트에서는 이와 같이 "페이지 전체를 불러오는 행위"를 보통 깜빡인다고 표현한다.


  • SPA는 Menu와 Footer와 같이 페이지 전환 전후에 중복되는 부분은 새로 불러오지 않는다.
    • 다시 말해, SPA는 업데이트가 필요한 부분만 새로 불러온다.

전통적인 웹사이트의 한계와 단점

웹사이트가 보다 복잡해지고 애플리케이션의 형태를 가지게 되면서, 사용자와 서비스 사이에 더욱 많은 상호작용이 일어나게 되었다.

  • 하지만 이때마다 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

WireframeMockup

  • Wireframe : 디자인에 들어가기 전 단계로 선(wire)를 이용해 윤곽선(frame)을 잡는 것.
    • 이 작업을 통해 개발자는 디자인 컨셉과 사이트 기능에 대한 이해를 할 수 있다.
  • 목업(mockup) : 데스크톱, 스마트폰의 프레임을 덧씌워 직관적으로 이해하기 쉽게 디자인한 것

  • 컴포넌트 기반 개발 방법
    • 페이지를 먼저 만들기보다는 어떤 컴포넌트를 만들고 이들을 조합할지부터 구상할 계획.

  • 먼저 화면 상단의 경우,
    • 상단 전체를 아우르는 Header라는 컴포넌트가 있고, 그의 자식으로 SearchSetting이라는 컴포넌트를 만들기로 하자.
    • Header 컴포넌트는 애플리케이션 내의 어떤 페이지에 가더라도 늘 상단에 위치하니 이 부분을 감안해서 설계 로직을 작성하자.

  • 화면 중앙에는,
    • 크리에이터들이 올린 영상을 담고 있는 ContentsList라는 컴포넌트가 있고,
    • 그 안에는 동일한 형태를 가진 영상물들이 반복적인 형태로 화면을 구성하고 있기 때문에 Content라는 컴포넌트를 한 번만 만들어 재사용하기로 하였다.

  • 과연 이게 정말 끝일까요?

  • 가장 작은 단위의 컴포넌트를 한번 분석해보자.
  • Content 컴포넌트는 상단에는 썸네일, 중앙에는 아바타와 영상 소개 글, 하단에는 채널 이름과 조회 수, 업로드한 날짜가 기재되어 있다.
  • Content 컴포넌트는 영상과 관련된 데이터를 입력받아, UI에 맞게 화면에 출력해 준다.
    • 더불어 눈에 보이지는 않지만 클릭 시 해당 영상을 재생해 주는 기능도 가지고 있다.
  • 뿐만 아니라, 이 데이터는 영상이 대기 목록에 있을 때도, 혹은 재생 중일 때도 동일한 내용이 화면에 출력된다.
    • 어떤 상태로 있느냐에 따라 출력되는 위치만 조금씩 달라질 뿐이다.
  • 애플리케이션 안에서 다뤄지는 데이터를 컴포넌트들끼리 보다 유기적으로 주고받을 수 있도록 설계해야 한다.

React Router

SPA & Routing

  • SPA는 하나의 페이지를 가지고 있지만 사실 한 종류의 화면만 사용하지 않는다.
  • 예를 들어 Twittler와 같은 SPA를 만들 때, 메인 트윗 모음 페이지, 알림 페이지, 마이 트윗 페이지 등의 화면이 필요할 수 있다.

  • 또한 이 화면에 따라 "주소"도 달라진다.
    • 이렇게 다른 주소에 따라 다른 뷰를 보여주는 과정을 "경로에 따라 변경한다."라는 의미라우팅(Routing)이라고 한다.
    • 하지만 React 자체에는 이 기능이 내장되어 있지 않아서, 직접 주소마다 다른 뷰를 보여줘야 한다.

React Router?

  • React SPA에서는 라우팅을 위해 React Router라는 라이브러리를 가장 많이 사용한다.


React Router 주요 컴포넌트

  • React Router의 주요 컴포넌트는 크게 3가지로 나눌 수 있다.
    • 라우터 역할을 하는 BrowserRouter
    • 경로를 매칭해주는 RoutesRoute
    • 경로를 변경하는 역할을 하는 Link
  • 이 컴포넌트들을 사용하기 위해서는 React Router 라이브러리에서 따로 불러와야 한다.
  • 아래 명령어를 통해 사용할 수 있습니다.
  • Import는 필요한 모듈을 불러오는 역할로 비구조화 할당(destructuring assignment)과 비슷하게 이용할 수 있다.



React Router 사용 환경 세팅


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

  • React Intro에서 배운 create-react-app으로 React 프로젝트 환경을 만들 수 있다.
  • 그 환경에 React Router 라이브러리도 설치할 수 있다.
  • npm 명령어를 통해 간단하게 설치할 수 있다.

2. App.js로 react-router 컴포넌트 꺼내오기

  • 컴포넌트를 꺼내오기 위한 import 구문도 작성하자.

Getting Started

1. 개발 환경 구축하기

  • 터미널을 열고 다음 명령어를 실행하여 simpleroute 디렉토리에 React 프로젝트를 생성합니다.
  • 실행 후 npm start를 통해 실행 결과가 잘 나오는지 확인해 주세요.
    • npx create-react-app@latest simpleroute
      cd simpleroute
      npm start
  • Create React App 프로젝트가 잘 생성되었다면 이제 React Router를 설치할 차례.
  • 아래 명령어를 실행합니다.
    • npm install react-router-dom@^6.3.0
       // # 이번 스프린트에서는 6.3.0 버전을 사용합니다
  • 라이브러리가 잘 설치되었다면, package.json 파일의 dependencies 항목에 react-router-dom이라는 라이브러리가 등록된 것을 확인하실 수 있다.
    • 업로드중..
  • 이제 App.js 파일로 가서 최상단에 React Router 라이브러리가 제공하는 컴포넌트들을 사용하기 위한 세팅을 진행합니다.
  • React Router 슬라이드에서 어떻게 이 컴포넌트들을 사용할 수 있는지 배웠습니다!
    • import React from 'react'
      import { BrowserRouter, Routes, Route, Link } from "react-router-dom"; // 이 구문을 넣어주세요

2. 라우트 준비하기

  • 페이지를 표시하는 컴포넌트 Home, MyPage, Dashboard를 만들어봅시다.

    •   // Home 컴포넌트
      function Home() {
        return <h1>Home</h1>;
      }
      
        // MyPage 컴포넌트
      function MyPage() {
        return <h1>MyPage</h1>;
      }
      
        // Dashboard 컴포넌트
      function Dashboard() {
        return <h1>Dashboard</h1>;
      }

3. 메뉴 만들기

  • 페이지를 표시하는 컴포넌트를 만들었고, 각 컴포넌트로 이동할 메뉴를 제작합니다.

  • 메뉴 제작을 위해 <ul> 요소와 <li> 요소를 이용합니다.

    • function App () {
        return (
            <div>
              <nav>
                <ul>
                  <li>
                    Home
                  </li>
                  <li>
                    MyPage
                  </li>
                  <li>
                    Dashboard
                  </li>
                </ul>
              </nav>
            </div>
          )
        }
      
        export default App;

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

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

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=”*”입니다. 지정되지 않은 주소로 접근할 시에는 이 속성이 설정되어 있는 컴포넌트를 보여주게 됩니다.


  • 경로를 연결해 주는 역할을 하는 컴포넌트입니다.
  • 페이지 전환을 통해 페이지를 새로 불러오지 않고 애플리케이션을 그대로 유지하여 HTML5 History API를 이용해 페이지의 주소만 변경해 줍니다.
  • ReactDOM으로 렌더를 시키게 되면 <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가 구현되었는지 확인해 봅시다.
profile
Drop the Bit!

0개의 댓글