1. 페이지 라우팅
- 페이지 라우팅이란?
- 경로에 따라 알맞은 페이지를 렌더링하는 과정
- Multi Page Application (MPA)
- 서버가 여러개의 페이지를 갖고있는 것
- 브라우저가 특정 주소를 갖고있는 페이지를 요청하게 되면 서버가 요청에 맞는 페이지를 찾아 페이지를 그대로 반환하여 브라우저는 페이지를 그대로 화면에 렌더링함
- 많은 서비스가 이용하는 전통적인 방식
- MPA방식에서 브라우저가 새로운 페이지를 요청했을때 서버 측에서 미리 완성해둔 HTML파일을 보내주어 브라우저는 그대로 렌더링 하는 방식을 SSR(Server Side Rendering) 이라고 함
- 중요! MPA와 SSR이 같다?
- MPA와 SSR은 다르다.
- MPA: 서버가 모든 페이지를 갖고 있는 것
- SSR: 브라우저가 페이지를 요청했을때 미리 완성해둔 페이지를 응답하는 것
- MPA와 SSR은 다르다.
- 즉, 대다수의 전통적인 웹서비스들은 MPA 방식으로 서버가 다수의 페이지를 보유하고있고, 브라우저가 요청을 보내면 SSR 방식으로 미리 만들어준 페이지를 응답한다.
- 단점
- 페이지 이동이 매끄럽지 않고, 비효율적임
- 요청이 많아질 경우 서버의 처리량이 많아지기 때문에 서버의 부하가 심해짐
- Single Page Application
- React는 Single Page Application (SPA) 방식을 사용
- 페이지 이동이 매끄럽고 효율적
- 다수의 사용자가 접속해도 큰 상관 없음
- SPA 방식으로 구동되는 리액트 웹서버는 페이지를 단 한개만 갖고있음.
- 그리고 추가로 만든 리액트 컴포넌트, 기타 기능들이 작성된 js 파일들을 하나로 묶어 브라우저에 전달해줌.
- 이 하나로 묶는 행위를 Bundling 이라고 함.
- 번들링되어 브라우저에게 전달되는 자바스크립트 파일은 Bundle File 이라고 부름.
- 이 번들링 과정은 Vite가 담당해줌.
- 이 번들 파일엔 작성한 모든 리액트 컴포넌트들이 하나의 파일로 묶여있는 자바스크립트 파일이기 때문에, 이 파일을 리액트 앱 이라고 부를 수 있음.
- 브라우저는 전달받은 번들파일을 직접 실행하여 main.jsx파일이 브라우저에서 가장 먼저 실행하며, 해당 파일에 있는 render 메서드가 호출되며 App 컴포넌트를 화면에 실제로 랜더링함.
- 이와 같이 브라우저가 직접 자바스크립트 파일을 실행하여 직접 렌더링하는 방식을 Client Side Rendering (CSR) 이라고 함.
2. 라우팅 설정하기
- 리액트 라우터
- npmjs.com에 등록된 라이브러리
- 대다수의 리액트 앱이 사용하는 대표 라이브러리
- 터미널에 npm i react-router-dom 입력
- 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 컴포넌트를 브라우저 라우터로 감싸면 리액트 앱의 모든 컴포넌트들이 페이지 라우팅과 관련한 모든 데이터를 공급받아 사용할 수 있게 됨.
- 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. 페이지 이동
- 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 기준
- replace: Boolean
4. 동적 경로
- 동적경로: 동적인 데이터를 포함하는 경로
- URL Parameter: / 뒤에 아이템의 id를 명시. (ex, …/product/1 )
- 변경되지 않는 값을 주소로 명시하기 위해 사용 - Query String: ? 뒤에 변수명과 값 명시. (ex, …/product?id=1)
- 검색어 등 자주 변경되는 값을 주소로 명시하기 위해 사용.
- 동적경로 설정
- Query String
- Home.jsx ```jsx import { useSearchParams } from “react-router-dom”;
- Query String
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;