1. Router란?

쉽게 정리하면, React Router를 사용하면 보다 빠른 페이지 이동을 가능하도록 도와주는 기능

  • 기존에는 사용자가 링크를 클릭하면 새 페이지에 대한 프로세스가 시작.

    <프로세스>
    a. 브라우저는 웹 서버에서 문서 요청
    b. CSS 및 JS 내용을 다운로드
    c. 서버에서 보낸 HTML 렌더링

  • Router를 사용하면 클라이언트 측 라우팅을 통해 서버에 새로운 문서를 요청하거나, 다음 페이지를 위해 css 및 js를 재평가 할 필요가 없음.

  • 새 정보를 update하고 싶다면, 데이터 요청을 만들어 새 정보로 fetch 후 페이지 업데이트

  • 더 빠른 사용자 경험을 가능하도록 함.


2. Router 설치

 npm i react-router-dom@6.4 #latest
 npm i react-router-dom@5.3 #classic
 #5도 아직 많이 사용하기 때문에, 더 끌리는 버전으로 설치
 #이 포스팅에서는 6의 장점위주로 다룰 예정

3. React Router API _ createBrowserRouter

  • v5 : BrowserRouter -> v6: createBrowserRouter

    • v5버전에서는 BrowserRouter를 사용하며 function으로 표현함.

        ########################## v5_ Router.tsx #############################
      
        import {BrowserRouter, Route, Routes} from "react-router-dom";
        import Header from "./components/Header";
        import Mainpage from "./screens/Mainpage";
        import Subpage from "./screens/Subpage";
      
        function Router() {
        	return (
             <BrowserRouter>
              <Header />
              <Routes>
               <Route path="/" element={<Mainpage />} />
               <Route path="/subpage" element={<Subpage />} />
              </Routes>
             </BrowserRouter>
            )
        }
        export default Router;

    • v6버전에서는 createBrowserRouter가 나오면서, object화 시킬 수 있게 됨.

      • 부모와 자식을 나눠 사용할 수 있다는 점도 좋음.
      • v5와 v6 중 더 선호하는 방법을 쓰면 됨.
        ########################## v6_Router.tsx #################################
      
        import {BrowserRouter, Route, Routes} from "react-router-dom";
        import Header from "./components/Header";
        import Mainpage from "./screens/Mainpage";
        import Subpage from "./screens/Subpage";
        import Root from './Root'; // App.tsx를 Root.tsx로 이름 바꾼 상태
      
        const router = createBrowserRouter([
        {
        	//첫번째 route는 Mainpage가 아닌 전체 route들의 컨테이너가 될 것.
            //1. path 정하기
            //2. 유저가 해당 url로 이동하거나 location이 그 url과 일치하면
            //3. element를 render
            //4. '/'를 부모로, Mainpage, Subpage 등을 자식으로 생각하기
            path:"/",
            element: <Root />
            childrem: [
            {
            	path:"mainpage", //부모의 영향으로 '/about'을 의미함
                element: <Mainpage />
            },
            {
            	path:"subpage",
               	element: <Subpage />
            }
            ]
        ]}
        // 현재 위 상태로 돌리게 되면, root의 내용이 자식 주소에게도 보이게 됨.
        // 따라서, Root.tsx로 가서 <Outlet />을 적어줘야 함!
        )
        export default router;

    • 기존 App 대신 RouterProvider을 사용해 줌.

        ########################## v6_index.tsx #################################
      
        import React from "react";
        import ReactDOM from "react-dom/client";
        import {RouterProvider} from "react-router-dom; //App render 대신 RouterProvider를 render
        import router from "./Router";
      
        const root = ReactDOM.createRoot(
        	document.getElementById("root") as HTMLElement
        );
        root.render(
        	<React.StrictMode>
            	<RouterProvider router= {router} /> //router props를 가지는데, 이는 위에서 CreateBrowserRouter 함수를 통해 만들어 낸 것
            </React.StrictMode>
        );

    • Outlet에 자식이 매칭됨.

    
       ########################## v6_Root.tsx #################################
       import React from "react";
       import {Outlet} from "react-router-dom";
    
       function Root() {
       	return (
           	<div>
               	<Outlet />
               </div>
           )
       }

<Router 진행 순서>
1. Mainpage를 가고자 함
2. 먼저 Router.tsx의 path='/'에 매칭이 됨.
3. react router는 Root를 Render 하게 됨.
4. Root에게는 자식이 있는데, react router는 Outlet 컴포넌트를 통해 url을 확인
5. Root를 render하고, Mainpage도 render. (Outlet을 render 하고자 하는 route(ex. Mainpage)로 바꿔서 render 됨)
6. localhost:3000/mainpage로 들어가 보면 Root에 있는 내용 + Mainpage에 있는 내용이 출력됨.

ex.

########################## v6_Root.tsx #################################
 import React from "react";
 import {Outlet} from "react-router-dom";

 function Root() {
 	return (
     	<div>
         	<Header />
         	<Outlet /> // <Mainpage />를 가리킴
         </div>
     )
 }
 // Header 다음 Mainpage 내용이 출력

4. React Router API _ errorElement

  • errorElement (v5에는 없고, v6에는 있음)

    • 우리의 컴포넌트에 에러가 발생해서 충돌나거나, 컴포넌트의 위치를 찾지 못할 때 사용.
    • Root element path에도 에러를 추가할 수 있음.
    • 다른 컴포넌트들을 또 다른 컴포넌트에서 발생하는 문제로부터 보호해줌.
    • 하나의 컴포넌트에서 에러가 나도, 다른 페이지를 보는데 문제가 없게 됨!!!

    ex.

    ########################## v6_NotFound.tsx #################################
    	function NotFound(){
     	return <h1>404 NotFound!<h1>
     }
     export default NotFound;
    ########################## v6_Mainpage.tsx #################################
    	function NotFound(){
     	const errorArr = [];
     	return <h1>{errorArr[0].name}<h1>; // 없는 값을 줌. 컴포넌트 충돌
     }
     export default NotFound;
    ########################## v6_Root.tsx #################################
    	const router = createBrowserRouter([
     {
         path:"/",
         element: <Root />
         childrem: [
         {
         	path:"mainpage", //부모의 영향으로 '/mainpage'를 의미함
             element: <Mainpage />
             errorElement : <ErrorComponent /> //해당 자식(Mainpage)에서 컴포넌트 충돌(에러)이 나면 errorcomponent를 적용
         },
         errorElement: <NotFound /> //잘못된 페이지, 컴포넌트 충돌 등 에러가 발생하면 notfoundcomponent 적용
     ]}
  • errorElement가 없는 경우

    • 런타임에서 에러가 나 모든게 사라지고 빈 화면만 보이게 됨.

  • 자식에게 errorElement가 있는 경우

    • Mainpage(error있는 페이지)

      • 해당 자식만 에러가 띄워지고 다른 자식들은 사용하는데 문제가 없음.
      • header도 잘 작동해서 header 밑에 해당 errorElement가 뜸.

    • Subpage(정상 페이지)

      • header에 다른 링크로 가는게 있다면, 해당 리스트 클릭해도 잘 이동.

  • 자식에게 errorElement가 없고 부모에게만 있는 경우

    • header가 안뜨고 NotFound만 떠있음. 물론 링크 자체를 수정하면 잘 이동함.

참고문서

profile
좋은 사람들과 좋은 시간을 보내기 위한 프론트엔드 개발자

1개의 댓글

comment-user-thumbnail
2023년 10월 7일

감사합니다.. 선생님 덕분에 문제 해결했습니다...ㅠㅠ

답글 달기