본문 바로가기

Frontend Study

[FE_Bootcamp] 28일차_React SPA

어제(목요일)은 알고리즘 스터디가 있던 날이었는데, 스터디 끝나고 진행한 회의가 생각보다 길어져 끝나자마자 침대에 눕고 말았다,..,,.

다행히 오늘 진행한 과제에서 어제 내용이 함께 나왔으니.,,.,.복습 겸 글을 작성해 보자.


1. SPA란?

네이버 스포츠 해외축구 페이지

 

내가 하루에도 수십번씩 들락거리는 네이버 스포츠 해외축구 페이지이다. 

지난 시간에 배웠던 컴포넌트를 이용해 이 페이지 구성을 살펴보자

 

해외축구 페이지

 

 

이 컴포넌트중에는, 다른 페이지로 넘어가면 내용이 바뀌는 컴포넌트가 있고, 그렇지 않은 컴포넌트가 있다.

이번엔 한번 해외야구 페이지로 넘어가서 각각 어떤 컴포넌트인지 확인해 보자

 

해외야구 페이지

 

두 페이지를 자세히 본 사람은 금방 알아차릴 것이다.

메뉴, 뉴스, 동영상 컴포넌트로 구성된 것은 동일하지만, 뉴스 컴포넌트와 동영상 컴포넌트는 페이지에 따라 내용이 달라진다.

반면 '메뉴' 컴포넌트는 아무런 변화가 없는 것을 확인할 수 있다.

 

이처럼 모든 컴포넌트를 변화시키지 않고, 특정 컴포넌트만을 업데이트 하는 방식을 'SPA' 방식이라고 한다.


2. SPA의 등장배경

SPA는 Single Page Application의 준말로, 한 페이지 전체를 불러오는 것이 아닌 필요한 부분만 업데이트 하는 방식을 말한다.

 

기존의 웹 사이트에서는, 사이트 내의 다른 페이지로 이동하기 위해선 하나의 HTML 문서를 통째로 불러오는 방식을 사용했었다.

하지만 웹 개발 기술이 점점 발전하면서, 한 페이지에는 다양한 기능과 UI들이 추가되어 매우 복잡해졌고, 이 복잡한 페이지를 매번 받아오는 것은 서버 트래픽을 증가시켜 속도를 느려지게 만들거나, 메모리 과부하 등의 문제를 발생시켰다.

 

이러한 불편함을 해소하고자 HTML 문서 전체가 아닌, 필요한 부분의 데이터만 받아와 동적으로 HTML 요소를 생성해 해당 부분에 적용 시키는 SPA 방식이 개발되었다.

문서 전체를 받아오는 것이 아니기 때문에 속도가 매우 빠르고, 반응성이 좋다. 또한 페이지 전체를 업데이트 하는것이 아니라 상호작용을 할 때마다 새로고침이 될 우려도 없다.

 

기존 방식과 SPA 방식의 차이

 

다만, 간단한 HTML에 비해 SPA를 구현하는 JS 파일의 크기가 커지고, 이 JS 파일을 로딩하는데 시간이 오래 걸린다는 단점은 있다.

그리고 HTML 태그나 링크를 분석해 검색 결과를 도출해내는 검색 엔진 최적화에도 문제가 생길 수 있다. 

HTML 파일에는 정말 기본적인 뼈대만 들어있고, 대부분의 페이지 렌더링은 JS에서 실행하기 때문에, 검색 엔진이 HTML 문서를 읽어도 태그나 링크를 제대로 가져올 수 없기 때문이다. 


3. React Router

리액트에서는, 이런 SPA를 구현하기 위해 'React Router'라는 라이브러리를 사용한다.

React Router(이하 리액트 라우터)는 HTML의 <a> 태그와 비슷한 역할로, 원하는 페이지로 이동하는 기능을 가지고 있다.

다만, <a> 태그와는 다르게 '직접 이동'이 아닌 '컴포넌트 렌더링'만 하기 때문에 페이지 전체 새로고침은 일어나지 않는다.

 

리액트 라우터는 다음과 같은 기능을 가져야 한다

  • 어떠한 요소를 클릭하면, 그에 맞는 컴포넌트를 렌더링 해야 한다
  • 각 컴포넌트와 요소를 이어야 한다

이 기능들을 구현하기 위해, 리액트 라우터에서 필요한 것들을 가져온다.

 

npm install react-router-dom@^6.3.0

 

라우터는 라이브러리이므로, 따로 npm 설치를 해주어야 한다. 

설치가 완료되었다면, 라우팅에 쓰이는 주요 기능들을 불러온다.

이때, 구조 분해 할당을 통해 불러올 수 있다.

 

import {BrowserRouter, Routes, Route, Link} from 'react-router-dom'

 

  • BrouserRouter : 라우터(컴포넌트간 연결의 중계) 역할
  • Route : 각 컴포넌트와 경로(주소.com/mypage)를 매칭하는 역할
  • Routes : Route들을 한데 모음
  • Link : 이벤트 발생시 경로를 각 컴포넌트로 변경

각 기능들을 불러왔으면, 이제 Route와 Link를 통해 컴포넌트를 이어주면 된다.


4. Router 구현

 

버튼을 누르면 화면이 바뀐다

 

다음과 같은 페이지를 만들어보자. 버튼을 누르면 각 악기별 멤버 이름이 나올도로록 해야한다.

리액트 라우터를 구현하기 위해서는, 연결할 요소들과 렌더링할 컴포넌트들을 만들어줘야 한다.

 

연결할 요소와 렌더링할 컴포넌트

 

렌더링 할 컴포넌트들을 먼저 만들어보자.

컴포넌트는 함수 형식으로 만들 수 있었고, 이를 메인 컴포넌트에 붙이면 렌더링 되는 방식이었다.

 

import './App.css';
import React from 'react'
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Main() {
  return <h1>Red Hot Chili Peppers</h1>
}

function Vocal() {
  return <h1>Anthony Kiedis</h1>;
}

function Guitar() {
  return <h1>John Frusciante</h1>;
}

function Bass() {
  return <h1>Flea</h1>;
}

function Drum() {
  return <h1>Chad Smith</h1>;
}

function App () {
  return (
    <div>
      <h1>내가 좋아하는 밴드!</h1>
      <Main />
      <Vocal />
      <Guitar />
      <Bass />
      <Drum />
    </div>
  )
}

export default App;

 

컴포넌트들을 렌더링

 

그 다음은, 연결할 요소들인 버튼을 만들어보자.

 

function App () {
  return (
    <div>
      <h1>내가 좋아하는 밴드!</h1>
      <div>
       <button>Main</button>
        <button>Vocal</button>
       <button>Guitar</button>
        <button>Bass</button>
        <button>Drum</button>
      </div>
      <div>
        <Main />
        <Vocal />
        <Guitar />
        <Bass />
        <Drum />
      </div>
    </div>
  )
}

 

버튼까지 달아주었다

 

버튼이 생성되었고, 컴포넌트들도 잘 렌더링 되었다. 

그럼 이제, 각 버튼들과 컴포넌트들을 연결해서 버튼을 누를 때 마다 해당 버튼에 맞는 컴포넌트가 렌더링 되게 해보자.

 

'내가 좋아하는 밴드!'라는 문장은 변하지 않기 때문에, 라우터를 사용할 필요가 없다.

따라서, 버튼을 담고 있는 div와 컴포넌트를 담고 있는 div만 BrowserRouter로 감싸준다.

그리고 각 컴포넌트에 경로를 매칭해 주어야 한다.

경로는 Route로 매칭할 수 있고, 이 Route들은 Routes 안에 넣어준다.

 

<Route path='/경로' element={<연결할 컴포넌트 />}></Route>

 

위와 같은 형식으로 각 컴포넌트에 경로를 매칭한 뒤, Routes에 담아준다.

참고로, 기본(메인) 페이지는 경로에 아무것도 쓰지 않아도 된다.

즉, path='/' 상태로 두면 된다.

 

function App () {
  return (
    <div>
      <h1>내가 좋아하는 밴드!</h1>
      <BrowserRouter>
        <div>
          <button>Main</button>
          <button>Vocal</button>
          <button>Guitar</button>
          <button>Bass</button>
          <button>Drum</button>
        </div>
        <div>
          <Routes>
            <Route path='/' element={<Main />}></Route>
            <Route path='/vocal' element={<Vocal />}></Route>
            <Route path='/guitar' element={<Guitar />}></Route>
            <Route path='/bass' element={<Bass />}></Route>
            <Route path='/drum' element={<Drum />}></Route>
          </Routes>
        </div>
      </BrowserRouter>
    </div>
  )
}

 

메인 페이지

 

메인 페이지에서는 <Main> 컴포넌트만이 렌더링 되는 것을 볼 수 있다.

하지만 아직 버튼을 눌러도 다른 컴포넌트들이 렌더링 되지 않는다.

이를 위해 우리는 각 버튼과 컴포넌트들을 연결시켜 주어야 한다.

 

<Link to='/경로'>연결할 요소</Link>

 

위 Route에서 설정한 경로를 Link의 to 프로퍼티에 넣어준다.

이 Link가 달린 요소를 클릭하게 되면, Link 안에 적인 path로 페이지를 이동하게 된다.

해당 페이지에서는 path를 가진 컴포넌트만이 렌더링 된다.

 

왜이리 느려~

 

버튼을 누를 때 마다 렌더링 되는 컴포넌트가 달라지고, 페이지 주소도 계속 달라지는 것을 확인할 수 있다.


리액트를 배운지는 얼마 안됐지만, SPA에 대해서는 꽤나 자세히 알 수 있게 된 것 같다.

물론 다른 사람들에 비하면 새발의 피의 적혈구겠지만,.,..,.,.,,.,

주말에는 오늘 배웠던 props와 state에 대해 적어볼 예정이다.

쓸수 있을까,..,,.싶다가도 내일 일정을 생각하면,..,
그거라도 해야,..,,.,.

암튼!