싱글페이지앱(Single Page App)

miniminion·2022년 12월 26일
0

리액트

목록 보기
1/2
post-thumbnail

싱글페이지앱이란 문자그대로 단일페이지로 이루어진 앱을 의미한다. 페이지를 이동할 때 anchor 태그를 활용해 새로운 html을 불러오는 게 아니라 index.html 하위의 DOM을 갈아 끼우면서 다른 페이지를 보여주는 방식이다. 전체 페이지를 다시 렌더링하지 않고 변경되는 부분만을 갱신하므로 새로고침이 발생하지 않는다는 장점이 있다.

리액트는 이러한 싱글페이지앱 제작을 가능하게 하며, 그 과정에서 라우터 라이브러리를 사용한다. 가장 많이 사용하는 라우터 컴포넌트에는 BrowserRouter와 HashRouter가 있다.

BrowserRouter

HashRouter

이 중에서 BrowserRouter에 대해 더 알아보자.

아래와 같이 BrowserRouter가 인식하는 브라우저의 주소 체계에서
https://movie.daum.net/moviedb/main?movieId=62708
뒷 부분의 숫자가 바뀌면 다른 페이지가 보여진다. 예를 들면 지금은 [아바타] 영화 설명페이지이고 '62708'을 '115401'으로 바꾸면 [영웅] 영화 설명페이지로 바뀐다.

이렇게 페이지의 주소체계에 대해 이해했으므로 이것을 어떻게 리액트로 코딩하는지 알아보자.

예시로 다음과 같은 싱글페이지앱 형태의 영화페이지를 제작해보려고 한다.
메인 페이지 > 영화 목록 페이지 > 영화 상세 페이지

먼저 라우터를 설치해준다.

npm install react-router-dom

그 후 App.js 상단에서 BrowserRouter를 import 해준다.

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

일단 아래와 같이 작성하여 메인페이지(/)에 Home 컴포넌트를 연결해주었다. 그 후 하위 페이지 주소로 영화 목록 페이지(/movie), 영화 상세 페이지(/movie/detail/:id)를 작성하고 각각의 컴포넌트와 연결해 주었다.

import Home from "./Home";
import Movie from "./Movie";
import Detail from "./Detail";

function App() {
 
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />  
        <Route path="/movie" element={<Movie />} />
        <Route path="/movie/detail/:id" element={<Detail />} />
      </Routes>
    </Router>
  );
}

Home.js에서는 다음과 같이 Link 컴포넌트를 이용하여 /movie 페이지와 연결해주었다.

import { Link } from "react-router-dom";

function Home() {
  return (
    <div>
      <Link to="/movie">
        go to movie page
      </Link>      
    </div>
  );
}

Movie.js에서는 다음과 같이 Link 컴포넌트를 이용하여 /movie/detail/:id 페이지와 연결해주었다. /movie 페이지에서는 각각의 영화에 해당하는 figure를 클릭하면 해당 영화의 id를 Link 컴포넌트의 to 속성에 받아와서 주소를 만들고 연결된다.

import { Link } from "react-router-dom";

function Home() { ... 

return (
   
    <Link to={`/movie/detail/${id}`}>
      <figure className={styles.figure}>
       ... 
      </figure>
    </Link>

  );}

위 코드에서 id는 주소의 파라미터 역할을 하며, App.js에서 라우트 컴포넌트 작성시 아래와 같이 파라미터 앞에 :를 붙여준다.

<Route path="/movie/detail/:id" element={<Detail />}/>

마지막으로 Detail.js에서 다음과 같이 useParams을 사용하여 Movie.js의 id를 받아오면 된다.

import { useParams } from "react-router-dom";

function Detail() {
  const { id } = useParams();
  const URL = `https://yts.mx/api/v2/movie_details.json?movie_id=${id}`;

위의 예시에서는 영화 별로 상세페이지가 나타나게 하였지만, 만약 영화에 상관없이 하나의 페이지로 연결되게 하고 싶다면 주소 뒤에 /* 을 붙여 주면 된다. 또한, 정의하지 않은 경로 접속시에 NotFound 컴포넌트를 출력하고 싶다면 주소에 *만 적어주면 된다.

function App() {
 
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />  
        <Route path="/movie" element={<Movie />} />
        <Route path="/movie/Detail/*" element={<Product />}></Route>
        <Route path="*" element={<NotFound />}></Route>
      </Routes>
    </Router>
  );
}

💡 '라우팅'과 'a태그'의 차이

라우팅: 페이지의 주소만 바뀔 뿐 새로고침 되지는 않는다.
a 태그: 페이지의 주소가 바뀜과 동시에 새로고침된다.
리액트 특성 상 새로고침 될 때 마다. 페이지를 구성하는 무성한 변수를 가지는 컴포넌트의 값들이 지워지고 새로 계산되기 때문에 페이지 주소가 바뀔 때마다 새로고침이 된다면 속도가 저하될 수 밖에 없다. 따라서 새로고침이 필수적인 상황이 아닌 이상 a 태그가 아닌 라우팅을 사용하여야 한다.

0개의 댓글