라우팅이란?
웹 애플리케이션에서 라우팅이라는 개념은 사용자가 요청한 URL에 따라 알맞는 페이지를 보여주는 것을 의미합니다. 웹 애플리케이션을 만들 떄 프로젝트를 하나의 페이지로 구성할 수도 있고, 여러 페이지를 구성할 수도 있겠지요
우리가 블로그를 만든다고 가정해봅시다. 블로그 애플리케이션은 주로 여러 페이지로 구성이 되어있습니다. 어떤 페이지가 필요한지, 한번 생각해 봅시다.
- 글쓰기 페이지 : 새로운 포스트를 작성하는 페이지입니다.
- 포스트 목록 페이지 : 블로그에 작성된 여러 포스트들의 목록을 보여주는 페이지입니다.
- 포스트 읽기 페이지 : 하나의 포스트를 보여주는 페이지 입니다.
라우팅 관련 기능을 리액트 라이브러리에서 공식적으로 지원하는 것이 아니라 써드 파티로서 제공되기 때문에 , 이 외에도 react-location, rakkas등의 프로젝트 들이 존재합니다.
싱글 페이지 애플리케이션이란?
싱글 페이지 애플리케이션이란, 한 개의 페이지로 이루어진 애플리케이션이라는 의미입니다. 리액트 라우터를 사용하여 여러 페이지로 구성된 프로젝트를 만들 수 있다고 했었는데 왜 싱글 페이지 애플리케이션이라고 불리는지 의문이 들 수 있습니다.
이를 이해하기 위해서는, 싱글 페이지 애플리케이션이란 개념이 생기기 전에 사용되던 멀티 페이지 애플리케이션은 어떻게 작동하는지 살펴볼 필요가 있습니다.
멀티 페이지 애플리케이션에서는 사용자가 다른 페이지로 이동할 때마다 새로운 html을 받아오고, 페이지를 로딩할 때마다 서버에서 CSS, JS, 이미지 파일 등의 리소스를 전달받아 브라우저 화면에 보여 주었습니다. 각 페이지마다 다른 html 파일을 만들어서 제공을 하거나, 데이터에 따라 유동적인 html을 생성해 주는 템플릿 엔진을 사용하기도 했죠.
사용자 인터랙션이 별로 없는 정적인 페이지들은 기존의 방식이 적합하지만, 사용자 인터랙션이 많고 다양한 정보를 제공하는 모던 웹 애플리케이션은 이 방식이 적합하지 않았습니다. 새로운 페이지를 보여주어야 할 때마다 서버 측에서 모든 준비를 한다면 그만큼 서버의 자원을 사용하는 것이고, 트래픽도 더 많이 나올 수 있기 때문이죠.
그래서, 리액트 같은 라이브러리를 사용해서 뷰 렌더링을 사용자의 브라우저가 담당하도록 하고, 우선 웹 애플리케이션을 브라우저에 불러와서 실행시킨 후에 사용자와의 인터랙션이 발생하면 필요한 부분만 자바스크립트를 사용하여 업데이트하는 방식을 사용하게 됐습니다. 만약 새로운 데이터가 필요하다면 서버 API를 호출하여 필요한 데이터만 새로 불러와 애플리케이션에서 사용할 수 있게 됐죠.
이렇게 html은 한번만 받아와서 웹 애플리케이션을 실행시킨 후에 그 이후에는 필요한 데이터만 받아와서 화면에 업데이트 해주는 것이 싱글 페이지 애플리케이션입니다.
싱글 페이지 애플리케이션은 기술적으로는 한 페이지만 존재하는 것이지만, 사용자가 경험하기에는 여러 페이지가 존재하는 것 처럼 느낄 수 있습니다. 리액트 라우터와 같은 라우팅 시스템은 사용자의 브라우저 주소창의 경로에 따라 알맞는 페이지를 보여주는데요, 이후 링크를 눌러서 다른 페이지로 이동하게 될 때 서버에 다른 페이지의 html을 새로 요청하는 것이 아니라, 브라우저의 History API를 사용하여 브라우저의 주소창의 값만 변경하고 기존에 페이지에 띄웠던 웹 애플리케이션을 그대로 유지하면서 라우팅 설정에 따라 또 다른 페이지를 보여주게 됩니다.
프로젝트에 라우터 적용
react-router-dom에 내장되어 있는 BrowserRouter라는 컴포넌트를 사용하여 감싸면 됩니다. 이 컴포넌트는 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로 불러오지 않고도 주소를 변경하고 현재 주소의 경로에 관련된 정보를 리액트 컴포넌트에서 사용할 수 있도록 해 줍니다.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
페이지 컴포넌트 만들기
각 페이지에서 사용할 컴포넌트를 만들 차례입니다. 사용자가 웹 사이트에 들어오게 됐을 떄 가장 먼저 보여지게 될 Home페이지 컴포넌트와 웹 사이트를 소개하는 About페이지 컴포넌트를 만들어 봅시다.
src/pages/Home.js
import React from "react";
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
</div>
);
};
export default Home;
src/pages/About.js
import React from "react";
const About = () => {
return (
<div>
<h1>소개</h1>
<p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
</div>
);
};
export default About;
Route 컴포넌트로 특정 경로에 원하는 컴포넌트 보여주기
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
export default App;
Link 컴포넌트를 사용하여 다른 페이지로 이동하는 링크 보여주기
웹 페이지에서는 원래 링크를 보여줄 때 a태그를 사용하는데요, 리액트 라우터를 사용하는 프로젝트에서 a태그를 사용하면 안됩니다. 왜냐하면, a태그를 클릭하여 페이지를 이동할 떄 브라우저에서는 페이지를 새로 불러오게 되기 때문입니다.
Link컴포넌트 역시 a태그를 사용하긴 하지만, 페이지를 새로 불러오는 것을 막고 History API를 통해 브라우저 주소의 경로만 바꾸는 기능이 내장되어 있습니다.
src/pages/Home.js
import React from "react";
import { Link } from "react-router-dom";
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
<Link to="/about">소개</Link>
</div>
);
};
export default Home;
URL 파라미터
src/pages/Profile.js
import React from "react";
import { useParams } from "react-router-dom";
const data = {
hyunseo: {
name: "이현서",
description: "리액트를 더 좋아하는 개발자",
},
velopert: {
name: "김민준",
description: "리액트를 좋아하는 개발자",
},
};
const Profile = () => {
const params = useParams();
const profile = data[params.username];
return (
<div>
<h1>사용자 프로필</h1>
{profile ? (
<div>
<h2>{profile.name}</h2>
<p>{profile.description}</p>
</div>
) : (
<p>존재하지 않는 프로필입니다.</p>
)}
</div>
);
};
export default Profile;
URL파라미터는 useParams라는 Hook을 사용하여 객체 형태로 조회할 수 있습니다. URL파라미터의 이름은 라우트 설정을 할 때 Route컴포넌트의 path props를 통하여 설정합니다.
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />}></Route>
</Routes>
);
}
export default App;
Profile 페이지로 이동을 할 수 있도록 Home페이지에 Link를 더 만들어 보았습니다. 링크가 여러 개 이기 때문에, ul태그를 사용하여 리스트 형태로 보여주었습니다.
src/pages/Home.js
import React from "react";
import { Link } from "react-router-dom";
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
<ul>
<li>
<Link to="/about">소개</Link>
</li>
<li>
<Link to="/profiles/hyunseo">hyunseo의 프로필</Link>
</li>
<li>
<Link to="/profiles/velopert">velopert의 프로필</Link>
</li>
<li>
<Link to="/profiles/void">존재하지 않는 프로필</Link>
</li>
</ul>
</div>
);
};
export default Home;
쿼리 스트링
이번에는 라우트에서 쿼리스트링을 사용하는 법입니다. 쿼리스트링을 사용할 때는 URL파라미터와 달리 Route컴포넌트를 사용할 때 별도로 설정해야 되는 것은 없습니다.
src/pages/About.js
import React from "react";
import { useLocation } from "react-router-dom";
const About = () => {
const location = useLocation();
return (
<div>
<h1>소개</h1>
<p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
<p>쿼리스트링: {location.search}</p>
</div>
);
};
export default About;
useLocation이라는 Hook은 location객체를 반환하며 이 객체는 현재 사용자가 보고있는 페이지의 정보를 지니고 있습니다. 이 객체에는 다음과 같은 값들이 있습니다.
- pathname: 현재 주소의 경로 (쿼리스트링 제외)
- search: 맨 앞의 ? 문자 포함한 쿼리스트링의 값
- hash: 주소의 #문자열 뒤의 값(주로 History API가 지원되지 않는 구형 브라우저에서 클라이언트 라우팅을 사용할 때 쓰는 해시 라우터에서 사용됩니다.)
- state: 페이지로 이동할때 임의로 넣을 수 있는 상태값
- key: location객체의 고유 값, 초기에는 default이며 페이지가 변경될때마다 고유의 값이 생성됨
또한 react-router v6애서 부터 useSearchParams라는 Hook을 통해서 쿼리스트링을 더욱 쉽게 다룰 수 있게 되었습니다.
src/pages/About.js
import React from "react";
import { useSearchParams } from "react-router-dom";
const About = () => {
const [searchParams, setSearchParams] = useSearchParams();
const name = searchParams.get("name");
const detail = searchParams.get("detail");
const onToggleDetail = () => {
setSearchParams({ name, detail: detail === "true" ? false : true });
};
return (
<div>
<h1>소개</h1>
<p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
<p>detail: {detail}</p>
<p>name: {name}</p>
<button onClick={onToggleDetail}>Toggle detail</button>
</div>
);
};
export default About;
useSearchParams는 배열 타입의 값을 반환하며, 첫번째 원소는 쿼리파라미터를 조회하거나 수정하는 메서드들이 담긴 객체릅 반환합니다. get메서드를 통해 특정 파라미터를 조회할 수 있고, set메서드를 통해 특정 쿼리파라미터를 업데이트할 수 있습니다.
중첩된 라우트
src/pages/Articles.js
import React from "react";
import { Link } from "react-router-dom";
const Articles = () => {
return (
<ul>
<li>
<Link to="/article/1">게시글 1</Link>
</li>
<li>
<Link to="/article/2">게시글 2</Link>
</li>
<li>
<Link to="/article/3">게시글 3</Link>
</li>
</ul>
);
};
export default Articles;
src/pages/Article.js
import React from "react";
import { useParams } from "react-router-dom";
const Article = () => {
const { id } = useParams();
return (
<div>
<h2>게시글 {id}</h2>
</div>
);
};
export default Article;
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
<Route path="/articles" element={<Articles />} />
<Route path="/article/:id" element={<Article />} />
</Routes>
);
}
export default App;
게시글 목록 페이지에서 게시글을 열었을 떄, 게시글의 하단에 목록을 보여줘야 한다면 어떨까요
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
</Routes>
);
}
export default App;
src/pages/Articles.js
import React from "react";
import { Link, Outlet } from "react-router-dom";
const Articles = () => {
return (
<div>
<Outlet />
<ul>
<li>
<Link to="/articles/1">게시글 1</Link>
</li>
<li>
<Link to="/articles/2">게시글 2</Link>
</li>
<li>
<Link to="/articles/3">게시글 3</Link>
</li>
</ul>
</div>
);
};
export default Articles;
공통 레이아웃 컴포넌트
중첩된 라우트와 Outlet은 페이지끼리 공통적으로 보여줘야 하는 레이아웃이 있을때도 유용하게 사용할 수 있습니다.
예를 들어서, Home, About, Profile 페이지에서 상단에 헤더를 보여줘야 하는 상황을 가정해봅시다. Header컴포넌트를 만들어 두고 재사용하는 방법도 있을 겁니다. 하지만 방금 본 중첩된 라우트와 Outlet을 활용하여 구현할 수도 있습니다. 중첩된 라우트를 사용하는 방식을 사용하면 컴포넌트를 한번만 사용해도 된다는 장점이 있습니다.
src/Layout.js
import React from "react";
import { Outlet } from "react-router-dom";
const Layout = () => {
return (
<div>
<header style={{ background: "lightgray", padding: 16, fontSize: 24 }}>
Header
</header>
<main>
<Outlet />
</main>
</div>
);
};
export default Layout;
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
import Layout from "./Layout";
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
</Route>
</Routes>
);
}
export default App;
index props
Route 컴포넌트에는 index라는 props도 있습니다. 이 props는 path="/"와 동일한 의미를 가집니다.
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
import Layout from "./Layout";
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
</Route>
</Routes>
);
}
export default App;
index props는 상위 라우트의 경로와 일치하지만, 그 이후의 경로가 주어지지 않았을때 보여지는 라우트를 설정할때 사용합니다.
useNavigate
리액트 라우터에는 웹 애플리케이션에서 라우팅에 관련된 작업을 할 때 사용할 수 있는 유용한 API들을 제공합니다.
useNavigate는 Link컴포넌트를 사용하지 않고 다른 페이지로 이동을 해야 하는 상황에서 사용하는 Hook입니다.
src/Layout.js
import React from "react";
import { Outlet, useNavigate } from "react-router-dom";
const Layout = () => {
const navigate = useNavigate();
const goBack = () => {
// 이전 페이지로 이동
navigate(-1);
};
const goArticles = () => {
// articles 경로로 이동
navigate("/articles");
};
return (
<div>
<header style={{ background: "lightgray", padding: 16, fontSize: 24 }}>
<button onClick={goBack}>뒤로가기</button>
<button onClick={goArticles}>게시글 목록</button>
</header>
<main>
<Outlet />
</main>
</div>
);
};
export default Layout;
navigate함수를 사용할 때 파라미터가 숫자 타입이라면 앞으로 가고나, 뒤로 갑니다. 예를 들어서 navigate(-1)을 하면 한 번 뒤로가고, navigate(-2)를 하면 두 번 뒤로갑니다. 반대로 navigate(1)을 하면 앞으로 한 번 갑니다. 물론, 뒤로가기를 한번 한 상태여야 합니다.
다른 페이지로 이동을 할 때 replace라는 옵션이 있습니다. 이 옵션을 사용하면 페이지를 이동할 때 현재 페이지를 페이지 기록에 남기지 않습니다.
방금 작성했던 goArticles함수를 다음과 같이 수정해 봅시다.
src/Layout.js - goArticles
const goArticles = () => {
// articles 경로로 이동
navigate("/articles", { replace: true });
};
그 다음에 / 경로로 들어가서 Home페이지를 띄운 뒤에, 소개 링크를 눌러 About페이지로 이동해 보세요, 그리고 상단의 게시글 목록 페이지를 눌러보세요.
그 상태에서 브라우저의 뒤로가기 버튼을 눌러 이전 페이지로 이동해 보세요. 만약 {replace: true}설정이 없었더라면 직전에 봤던 페이지인 About페이지가 나타나야 하지만, 이 옵션이 활성화되어있기 때문에, 그 전의 페이지인 Home페이지가 나타나게 됩니다.
NavLink
이 컴포넌트를 사용할 때 style또는 className을 설정할 때 { isActive: boolean }을 파라미터로 전달받는 함수 타입의 값을 전달합니다.
src/pages/Articles.js
import React from "react";
import { NavLink, Outlet } from "react-router-dom";
const Articles = () => {
const activeStyle = {
color: "green",
fontSize: 21,
};
return (
<div>
<Outlet />
<ul>
<li>
<NavLink
to="/articles/1"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
게시글 1
</NavLink>
</li>
<li>
<NavLink
to="/articles/2"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
게시글 2
</NavLink>
</li>
<li>
<NavLink
to="/articles/3"
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
게시글 3
</NavLink>
</li>
</ul>
</div>
);
};
export default Articles;
또한 반복되는 작업이 너무 많으므로 아래와 같이 리팩토링 하는 작업을 해 주는것이 좋습니다.
src/pages/Articles.js
import React from "react";
import { NavLink, Outlet } from "react-router-dom";
const Articles = () => {
return (
<div>
<Outlet />
<ul>
<ArticleItem id={1} />
<ArticleItem id={2} />
<ArticleItem id={3} />
</ul>
</div>
);
};
const ArticleItem = ({ id }) => {
const activeStyle = {
color: "green",
fontSize: 21,
};
return (
<li>
<NavLink
to={`/articles/${id}`}
style={({ isActive }) => (isActive ? activeStyle : undefined)}
>
개사글 {id}
</NavLink>
</li>
);
};
export default Articles;
NotFound페이지 만들기
사전에 정의되지 않은 경로에 사용자가 진입했을 떄 보여주는 페이지를 만들어 봅시다.
src/pages/NotFound.js
import React from "react";
const NotFound = () => {
return (
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
fontSize: 64,
position: "absolute",
width: "100%",
height: "100%",
}}
>
404
</div>
);
};
export default NotFound;
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
import Layout from "./Layout";
import NotFound from "./pages/NotFound";
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
</Route>
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
);
}
export default App;
Navigate 컴포넌트
Navigate컴포넌트는 컴포넌트를 화면에 보여주는 순간 다른 페이지로 이동을 하고 싶을 때 사용하는 컴포넌트 입니다. 즉, 페이지를 리다이렉트하고 싶을 때 사용합니다. 예를 들어서, 사용자의 로그인이 필요한 페이지인데 로그인을 안했다면 로그인 페이지를 보여주어야겠죠? 그러한 상황에 사용할 수 있습니다.
src/pages/Login.js
import React from "react";
const Login = () => {
return <div>로그인 페이지</div>;
};
export default Login;
src/pages/MyPage.js
import React from "react";
import { Navigate } from "react-router-dom";
const MyPage = () => {
const isLoggedIn = false;
if (!isLoggedIn) {
return <Navigate to="/login" replace={true} />;
}
return <div>마이 페이지</div>;
};
export default MyPage;
여기서 isLoggedIn은 현재 false라는 고정값을 가지고 있지만, 이 값이 로그인 상태에 따라 true or false를 가리킨다고 가정해 봅시다.
위 컴포넌트에서는 만약 이 값이 false라면 Navigate컴포넌트를 통해 /login 경로로 이동합니다. 여기서 replace props는 useNavigate에서 설명한 것과 동일합니다. 페이지를 이동할 떄 현재 페이지를 기록에 남기지 않기 때문에 이동 후 뒤로가기를 눌렀을 때 2페이지 전의 페이지로 이동합니다.
src/App.js
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Articles from "./pages/Articles";
import Article from "./pages/Article";
import Layout from "./Layout";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import MyPage from "./pages/MyPage";
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
</Route>
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
);
}
export default App;
그 다음에 브라우저에서 /mypage경로로 이동하게 되면, 페이지가 로딩되는 순간 바로 Login페이지로 이동이 됩니다.
정리
한가지 문제가 있다면 바로 웹 브라우저에서 사용할 컴포넌트, 상태 관리를 하는 로직, 그 외 여러 기능을 구현하는 함수들이 점점 쌓이면서 최종 결과물인 자바스크립트 파일의 크기가 매우 커진다는 것입니다.
예를 들어 방금 만든 프로젝트는 About페이지에 사용자가 들어왔을 때 당장 필요하지 않은 Profile, Articles등의 컴포넌트의 코드까지 함께 불러옵니다. 라우터에 따라 필요한 컴포넌트만 불러오고, 다른 컴포넌트는 다른 페이지로 이동하게 되어 필요한 시점에 불러오면 더 효율적일 것입니다. 이는 코드스플리팅으로 해결할 수 있는 문제입니다!
심심해서 Code Splitting
src/App.js
import * as React from "react";
import { Route, Routes } from "react-router-dom";
import About from "./pages/About";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
import Loading from "./pages/Loading";
import Layout from "./Layout";
import NotFound from "./pages/NotFound";
import Login from "./pages/Login";
import MyPage from "./pages/MyPage";
const Articles = React.lazy(() => import("./pages/Articles"));
const Article = React.lazy(() => import("./pages/Article"));
function App() {
return (
<React.Suspense fallback={<Loading />}>
<Routes>
<Route element={<Layout />}>
<Route index element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/profiles/:username" element={<Profile />} />
</Route>
<Route path="/articles" element={<Articles />}>
<Route path=":id" element={<Article />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="*" element={<NotFound />} />
</Routes>
</React.Suspense>
);
}
export default App;
src/pages/Loading.js
import React from "react";
const Loading = () => {
return <div>Loading...</div>;
};
export default Loading;
Articles 컴포넌트만 code splitting이 제대로 된 것을 볼 수 있습니다.
'React > ReactJs' 카테고리의 다른 글
React - FrontEnd Project - 5 (0) | 2022.03.20 |
---|---|
React - FrontEnd Project - 4 (0) | 2022.03.20 |
React - FrontEnd Project - 3 (0) | 2022.03.17 |
React - FrontEnd project - 2 (0) | 2022.03.15 |
React - FrontEnd Project - 1 (0) | 2022.03.15 |