Home [REACT] 페이지 라우팅
Post
Cancel

[REACT] 페이지 라우팅

1. 페이지 라우팅

  1. 페이지 라우팅이란?
    • 경로에 따라 알맞은 페이지를 렌더링하는 과정
    • Multi Page Application (MPA)
    • 서버가 여러개의 페이지를 갖고있는 것
      • 브라우저가 특정 주소를 갖고있는 페이지를 요청하게 되면 서버가 요청에 맞는 페이지를 찾아 페이지를 그대로 반환하여 브라우저는 페이지를 그대로 화면에 렌더링함
    • 많은 서비스가 이용하는 전통적인 방식
    • MPA방식에서 브라우저가 새로운 페이지를 요청했을때 서버 측에서 미리 완성해둔 HTML파일을 보내주어 브라우저는 그대로 렌더링 하는 방식을 SSR(Server Side Rendering) 이라고 함
    • 중요! MPA와 SSR이 같다?
      • MPA와 SSR은 다르다.
        • MPA: 서버가 모든 페이지를 갖고 있는 것
        • SSR: 브라우저가 페이지를 요청했을때 미리 완성해둔 페이지를 응답하는 것
    • 즉, 대다수의 전통적인 웹서비스들은 MPA 방식으로 서버가 다수의 페이지를 보유하고있고, 브라우저가 요청을 보내면 SSR 방식으로 미리 만들어준 페이지를 응답한다.
    • 단점
      • 페이지 이동이 매끄럽지 않고, 비효율적임
      • 요청이 많아질 경우 서버의 처리량이 많아지기 때문에 서버의 부하가 심해짐
  2. Single Page Application
    • React는 Single Page Application (SPA) 방식을 사용
    • 페이지 이동이 매끄럽고 효율적
    • 다수의 사용자가 접속해도 큰 상관 없음

Image

  • SPA 방식으로 구동되는 리액트 웹서버는 페이지를 단 한개만 갖고있음.
  • 그리고 추가로 만든 리액트 컴포넌트, 기타 기능들이 작성된 js 파일들을 하나로 묶어 브라우저에 전달해줌.
    • 이 하나로 묶는 행위를 Bundling 이라고 함.
    • 번들링되어 브라우저에게 전달되는 자바스크립트 파일은 Bundle File 이라고 부름.
      • 이 번들링 과정은 Vite가 담당해줌.
      • 이 번들 파일엔 작성한 모든 리액트 컴포넌트들이 하나의 파일로 묶여있는 자바스크립트 파일이기 때문에, 이 파일을 리액트 앱 이라고 부를 수 있음.
  • 브라우저는 전달받은 번들파일을 직접 실행하여 main.jsx파일이 브라우저에서 가장 먼저 실행하며, 해당 파일에 있는 render 메서드가 호출되며 App 컴포넌트를 화면에 실제로 랜더링함.
  • 이와 같이 브라우저가 직접 자바스크립트 파일을 실행하여 직접 렌더링하는 방식을 Client Side Rendering (CSR) 이라고 함.

2. 라우팅 설정하기

  1. 리액트 라우터
    • npmjs.com에 등록된 라이브러리
    • 대다수의 리액트 앱이 사용하는 대표 라이브러리
    • 터미널에 npm i react-router-dom 입력
  2. main.jsx
1
2
3
4
5
6
7
8
9
10
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
import "./index.css";
import { BrowserRouter } from "react-router-dom";

createRoot(document.getElementById("root")).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);
  • BrowserRouter는 브라우저의 현재 주소를 저장하고 감지하는 역할.
  • App 컴포넌트를 브라우저 라우터로 감싸면 리액트 앱의 모든 컴포넌트들이 페이지 라우팅과 관련한 모든 데이터를 공급받아 사용할 수 있게 됨.
  1. App.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import "./App.css";
import { Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import Diary from "./pages/Diary";
import New from "./pages/New";
import Edit from "./pages/Edit";
import Notfound from "./pages/Notfound";

// 1. "/" : 모든 일기를 조회하는 Home 페이지
// 2. "/new" : 새로운 일기를 작성하는 New 페이지
// 3. "/diary" : 일기를 상세히 조회하는 Diary 페이지
function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/new" element={<New />} />
      <Route path="/diary" element={<Diary />} />
      <Route path="/edit" element={<Edit />} />
      <Route path="*" element={<Notfound />} />
    </Routes>
  );
}

export default App;
  • Routes
    • 여러개의 Route를 감싸는 Route Container
    • 내부 Route에 path prop을 갖는 컴포넌트를 찾아 렌더링
  • Route
    • 각각의 컴포넌트의 path를 정의하는 컴포넌트
    • prop
      • path: 주소
      • element: 요청 주소가 path일때 렌더링할 컴포넌트
  • 주의!
    • Routes 에는 Route 컴포넌트만 들어갈 수 있음. div나 다른 컴포넌트를 넣으면 에러가 발생함.
    • Routes 바깥에 배치된 요소는 페이지 라우팅과 관계없이 모든 페이지에 동일하게 렌더링됨.

3. 페이지 이동

  1. App.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import "./App.css";
import { Routes, Route, Link, useNavigate } from "react-router-dom";
import Home from "./pages/Home";
import Diary from "./pages/Diary";
import New from "./pages/New";
import Notfound from "./pages/Notfound";

// 1. "/" : 모든 일기를 조회하는 Home 페이지
// 2. "/new" : 새로운 일기를 작성하는 New 페이지
// 3. "/diary" : 일기를 상세히 조회하는 Diary 페이지
function App() {
  const nav = useNavigate();

  const onClickButton = () => {
    nav("/new");
  };

  return (
    <>
      <div>
        <Link to={"/"}>Home</Link>
        <Link to={"/new"}>new</Link>
        <Link to={"/Diary"}>Diary</Link>
      </div>
      <button onClick={onClickButton}>New 페이지로 이동</button>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/new" element={<New />} />
        <Route path="/diary" element={<Diary />} />
        <Route path="*" element={<Notfound />} />
      </Routes>
    </>
  );
}

export default App;
  • __ 태그__
    • 페이지 이동 시 현재 페이지를 완전히 새로고침하며 지정된 URL로 이동
    • 새로고침 과정에서 전체 HTML 문서가 다시 요청되며, 자바스크립트도 처음부터 다시 로드.
    • 단점
      • 전체 페이지 리로드
        • 브라우저는 매번 새로운 요청을 보내기 때문에 애플리케이션 상태가 초기화됨
        • SPA의 핵심인 빠른 상태 전환과 맞지 않음
  • Link
    • React Route 라이브러리가 제공하는 컴포넌트
    • 리액트에서 URL 이동을 최적화하기 위한 필수 도구
    • Link 컴포넌트 클릭 시, 브라우저가 새로고침 없이 URL을 변경하며 지정된 컴포넌트를 렌더링
    • 백엔드 요청 없이, 프론트엔드의 라우팅 로직을 통해 필요한 콘텐츠를 즉시 표시.
    • 장점
      • SPA 특화: 전체 페이지를 다시 로드하지 않고 필요한 부분만 업데이트하여 빠른 전환 제공
      • 상태 보존: 애플리케이션 상태(ex. 폼 데이터, 글로벌데이터)가 초기화되지 않음
  • useNavigate
    • 특정 이벤트가 실행됐을때 동작하거나 추가적인 로직이 필요한 경우 사용하는 Hook.
    • nav(String to, Object options)
      • to: 이동할 경로
      • options
        • replace: Boolean
          • true: 현재 URL을 히스토리에 추가, 뒤로가기 시 이전 페이지로 가능
          • false: 현재 URL을 새로운 URL로 변경, 뒤로가기 불가
        • relative: 상대경로 기준 지정
          • “route”: 이동하려는 경로를 현재 라우트 트리 기준
          • “path”: 이동하려는 경로를 현재 URL 기준

4. 동적 경로

  1. 동적경로: 동적인 데이터를 포함하는 경로
    • URL Parameter: / 뒤에 아이템의 id를 명시. (ex, …/product/1 )
    • 변경되지 않는 값을 주소로 명시하기 위해 사용 - Query String: ? 뒤에 변수명과 값 명시. (ex, …/product?id=1)
    • 검색어 등 자주 변경되는 값을 주소로 명시하기 위해 사용.
  2. 동적경로 설정
    • Query String
      • Home.jsx ```jsx import { useSearchParams } from “react-router-dom”;

const Home = () => { const [params, setParams] = useSearchParams(); console.log(params.get(“value”)); // http://localhost:5173/?value=hi라고 넣었다면 hi가 출력된다.

1
return <div>Home</div>;   };

export default Home; ```

  • useSearchParams Hook을 사용하여 가져올 수 있음

  • URL Parameter

    • App.jsx ```jsx import “./App.css”; import { Routes, Route, Link, useNavigate } from “react-router-dom”; import Home from “./pages/Home”; import Diary from “./pages/Diary”; import New from “./pages/New”; import Notfound from “./pages/Notfound”;

    function App() { const nav = useNavigate();

    const onClickButton = () => { nav(“/new”); };

    return ( <> <Route path="/" element={} /> <Route path="/new" element={} /> <Route path="/diary/:id" element={} /> <Route path="*" element={} /> </> ); }

    export default App;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    - Diary.jsx
    ```jsx
    import { useParams } from "react-router-dom";
    
    const Diary = () => {
      const params = useParams();
      console.log(params);
    
      return <div>{params.id}번 일기</div>;
    };
    
    export default Diary;
    
This post is licensed under CC BY 4.0 by the author.