[React] SPA와 라우팅

유진·2023년 10월 29일

리액트

목록 보기
6/8

📝 SPA란?

SPA(Single Page Application)은 하나의 페이지 요청으로 전체 웹앱을 사용하는 방식이다.


❓ 그렇다면 MPA는 무엇일까

MPA(Multi Page Application)은 서버에 미리 여러 페이지를 두고, 유저가 네비게이션 시 요청에 적합한 페이지를 전달하는 방식이다. 서버에 라우팅을 처리하는 기능이 있고, 서버에서 여러 페이지를 관리한다. 이러한 방식은 페이지 요청마다 모든 리소스를 다시 받아오므로, 페이지 간 데이터를 재활용하기 힘들다는 단점이 있다.



🎯 SPA의 특징

• 유저는 웹페이지를 사용하며 모바일 앱 같은 경험을 느낄 수 있다. ex) Instargram, Twitter
• Client-side routing 기술을 활용하여 페이지 진입 시 리로드없이 라우팅한다.
• AJAX 기술을 활용, 페이지 이동 시 서버에 데이터만 요청하여 자바스크립트로 페이지를 만든다.
• MPA와 다르게, 여러 페이지를 하나의 앱의 구성요소로 보고 여러 페이지 간의 스타일, 컴포넌트를 재활용하는 방향으로 구현한다.
• 자바스크립트만을 활용해 전체 페이지를 만들기에, 첫 요청 시 빈 페이지를 받게 된다.



📈 SPA의 장점

• 서버에서 페이지를 만들 필요가 없으므로 CDN에 캐싱이 가능하다.

콘텐츠 전송 네트워크(CDN)

  • 콘텐츠 전송 네트워크(CDN)는 데이터 사용량이 많은 애플리케이션의 웹 페이지 로드 속도를 높이는 상호 연결된 서버 네트워크이다.
  • CDN의 주 목적은 대기 시간을 줄이거나 네트워크 설계로 인해 발생하는 통신 지연을 줄이는 것이다.
  • CDN을 작동하는 방식으로 캐싱, 동적 가속 및 엣지 로직 계산의 원리 등이 있다.
  • 캐싱이란 더 빠른 데이터 액세스를 위해 동일한 데이터의 여러 복사본을 저장하는 프로세스이다.

• 매번 페이지 요청을 할 필요가 없어 네트워크 요청이 줄어든다. 또한 데이터 요청 등을 캐싱하여 재사용하는 등 제약 조건이 줄어든다.
• 웹사이트를 개별 페이지보다는 하나의 앱으로 보는 설계로 고도의 소프트웨어 설계와 패턴을 적용할 수 있다.
• 사용자가 페이지를 이동할 때 빈 화면 없이 바로바로 이동하는 것처럼 보이기 때문에 페이지의 잔존율이 높고 사용자 경험이 좋다.
• 모바일에서도 반응형으로 제작 시 하나의 앱처럼 사용이 가능하기 때문에 모바일 친화적이다.



📉 SPA의 단점

• MPA방식 보다는 Search Engine Optimization(검색 엔진 최적화)에 불리하다. 자바스크립트가 전부 실행되어야 요소가 가득 차고 검색엔진이 페이지를 검색하게 되면 비어있는 페이지로 인식 하기 때문에 SEO 최적화에 어려움이 생기게 된다.
• 하나의 자바스크립트 앱이 지속하므로, 메모리 관리와 성능, 데이터 활용 등이 중요하다.
• 여러 페이지를 전송받는 것 보다, 하나의 거대한 자바스크립트 앱을 전송받아야 하므로 코드가 많아질수록 로드 속도가 느려진다. 즉, 사용자의 컴퓨터 성능에 따라 로딩 속도에 영향을 준다.






🧏‍♂️ react-router 소개

• React의 JSX를 이용하거나, History API를 사용하여 라우팅을 구현 할 수 있다.
• 웹에서는 react-router-dom을 사용한다.
• 적용 시, 서버의 모든 path에서 같은 앱을 서빙하도록 해야 한다.

react-router-dom이란?
• React로 생성된 SPA 내부에서 페이지 이동이 가능하도록 만들어주는 라이브러리이다.
• 사용자의 url 경로에 따라서 해당 컴포넌트를 바꿔가면서 렌더링할 수 있게 해준다.



react-router의 기능

• React 컴포넌트를 특정 path와 연결하면, 해당하는 path로 진입 시 컴포넌트를 렌더링하게 한다.
• query, path variable 등 URL parameter를 얻어 활용한다.
• 조건에 맞지 않을 경우 redirect 한다.
• 페이지 이동 시, 이벤트 핸들러를 등록한다.
• /posts/my-post-1 등의 nested route를 구현한다.



react-router 사용법

** 2021년 말부터 v5에서 v6로 버전 업데이트가 이루어지면서 새로운 기능 추가 및 변경된 점이 있다.

<V5>

<BrowserRouter> 로 감싸 Router Context를 제공해야 함.
• Route로 path를 정의하고, 그 안에 렌더링하고자 하는 컴포넌트를 넣음.
• Link로 특정 페이지로 이동 시, 리로드 없이 페이지가 이동함.
• Switch로, 매칭되는 라우트 하나를 렌더링하게 함.

import { BrowserRouter, Route, Switch } from 'react-router-dom'
export function App() {
  return (
    <BrowserRouter>
      <Switch>
        <Route path="/about"><AboutPage /></Route>
        <Route path="/contact"><ContactPage /></Route>
        <Route path="/"><HomePage /></Route>
      </Switch>
    </BrowserRouter>
  )
}

1) BrowserRouter

• HTML5의 History API를 사용하여, UI와 URL의 싱크를 맞추는 역할이다.
• 최상위 컴포넌트에 사용되며, 라우팅을 위한 컨텍스트를 제공한다.
• 모든 URL에 대해 동작하게 하기 위해서는 서버 설정 필요하다.
• 모든 path 앞의 basename을 지정할 수 있다. ex) basename="/ko"
• forceRefresh로, 페이지 이동 시 리프레시할 것인지 지정할 수 있다.

2) Switch

• 여러 Route 중 매치되는 Route 위에서부터 하나 선택하여 렌더링한다.
• 매칭되는 Route가 없으면 아무것도 보여주지 않는다. fallback용으로 404 Not Found Page를 추가한다.
• path="/"의 경우 모든 path에 매칭되므로 exact 키워드를 추가하거나 가장 아래로 내린다.

3) Route

• path와 컴포넌트를 매칭한다.
• 매칭되는 컴포넌트는 children으로 넣어주거나
component prop으로 넘긴다.

React 컴포넌트에서 children이란, <Component>{children}</Component>과 같이
태그 안에 넣을 수 있는 값을 가리키는 것이다.

• exact 키워드로 정확하게 매칭하는 path를 설정한다.
• Route로 렌더링 되는 최상위 컴포넌트는 match, location, history를 prop으로 받는다.
• render prop으로, 매칭되었을 때 실제 어떤 컴포넌트를 렌더링할지 통제한다.

4) Redirect

• Link와 비슷하나, 렌더링되면 to prop으로 지정한 path로 이동한다.
• Switch 안에서 쓰일 경우, from, to를 받아 이동하게 만든다. ex) from="/" to="/login"

• to prop을 특정 URL로 받아, 클릭 시 네비게이션이 된다.
• anchor tag를 래핑한다.
• NavLink의 경우, 매칭 시 어떤 스타일을 가질지 등의
추가 기능이 있다.
• to에 location object나 함수를 받을 수 있다.

<V6>

1) Switch 대신 Routes 사용

  • Router > Routes > Route 구조
  • 컴포넌트 샌드위치 구조, component props 대신 element props 사용
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Portfolio />} />
        <Route path="/login" element={<LoginForm />} />
        <Route path="/register" element={<RegisterForm />} />
      </Routes>
    </Router>
  );
}

2) useHistory 대신 useNavigate 사용

// v5
const history = useHistory()

history.push("/login")
history.replace("/login")

// v6
const navigate = useNavigate() 	// useNavigate 훅 사용

navigate("/login") 				// 로그인 페이지로 이동
navigate("/login", {replace: true})

3) Redirect 대신 path="*"사용

<Router>
    <Routes>
        <Route path="/" element={<Portfolio />} />
        <Route path="/login" element={<LoginForm />} />
        <Route path="/register" element={<RegisterForm />} />
        <Route path="*" element={<NotFound />} />
    </Routes>
</Router>



참고자료

profile
도라에몽 암기빵

0개의 댓글