3. Router

1. RouterProvider

RouterProvider

React Router ๋ฒ„์ „ 6.4๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š”, ๋ผ์šฐํ„ฐ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์„œ ์“ฐ๋Š” ๋ฐฉ๋ฒ• ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๋ผ์šฐํ„ฐ ๊ฐœ์ฒด๋Š” ์ด ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ „๋‹ฌ๋˜์–ด ์•ฑ์„ ๋ Œ๋”๋งํ•˜๊ณ  ๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ API๋ฅผ ํ™œ์„ฑํ™”

โœ๏ธ ์กฐ๊ฐ๊ธ€

React Router๊ฐ€ Context API๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๋Š” ๊ฒƒ์ด ๋ฌผ์”ฌ ๋А๊ปด์ง€๋Š” ํŒŒํŠธ์˜€๋‹ค. Context API๋ฅผ ์‚ฌ์šฉํ•ด๋ณธ ์ ์ด ๋งŽ์ง€ ์•Š์•„์„œ ๊ทธ๋Ÿฐ์ง€, '๊ตณ์ด RouterProvider๋ฅผ ์‚ฌ์šฉํ•ด ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•ด์•ผ ํ• ๊นŒ?'๋ผ๋Š” ์˜๋ฌธ์ด ๋“ ๋‹ค. 2๊ฐ•์—์„œ ๋ฐฐ์› ๋˜ ๊ธฐ์กด์˜ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์–ด๋А ์ˆœ๊ฐ„ ๋ถˆํŽธํ•ด์ง€๋Š” ์ผ์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์ผ๊นŒ? ํŽ˜์ด์ง€๊ฐ€ ๋งŽ์ด ๋‚˜์˜ค์ง€ ์•Š๋Š” ์ž‘์€ ํ”„๋กœ์ ํŠธ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ๊ทธ๋ƒฅ ์ด์ „ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ์—ˆ๋Š”๋ฐ, ์—ฐ์Šต ์ฐจ์›์—์„œ RouterProvider๋„ ์‚ฌ์šฉํ•ด ๋ด์•ผ๊ฒ ๋‹ค.

2. createBrowserRouter

createBrowserRouter

React Router ์›น ํ”„๋กœ์ ํŠธ์— ๊ถŒ์žฅ๋˜๋Š” ๋ผ์šฐํ„ฐ DOM History API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ URL์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๊ธฐ๋ก ์Šคํƒ์„ ๊ด€๋ฆฌ loaders, actions, fetchers ๋“ฑ๊ณผ ๊ฐ™์€ v6.4 ๋ฐ์ดํ„ฐ API๋ฅผ ํ™œ์„ฑํ™”

routes

children ํ”„๋กœํผํ‹ฐ์— ์ค‘์ฒฉ๋œ ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋Š” Route ๊ฐ์ฒด์˜ ๋ฐฐ์—ด

createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "events/:id",
        element: <Event />,
        loader: eventLoader,
      },
    ],
  },
]);

3. ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

๐Ÿ”— ์‹ค์Šต ๋งํฌ

๐Ÿ“‹ App.tsx๊ฐ€ ํ•˜๋Š” ์ผ

  1. ์ „์ฒด์ ์ธ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์„ฑ

  2. ๋ผ์šฐํŒ… ๊ตฌ์„ฑ

๋ผ์šฐํŒ… ์ •๋ณด ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ ๋ถ„๋ฆฌ

์ปดํฌ๋„ŒํŠธ ๋ ˆ์ด์•„์›ƒ ์žก๊ธฐ

// src/components/Layout.tsx

import Header from './Header';
import Footer from './Footer';

import { Outlet } from 'react-router-dom';
 
export default function Layout() {
    return (
        <div>
            <Header/>
            <Outlet/>
            <Footer/>
        </div>
    );
}

๋ ˆ์ด์•„์›ƒ ์ ์šฉ

๐Ÿ’ก ํ…Œ์ŠคํŠธ์—์„œ๋„ routes ์ •๋ณด๋ฅผ ํ•„์š”๋กœ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ…Œ์ŠคํŠธ๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

// src/routes.tsx

import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';

import Layout from './components/Layout';

const routes = [
    {
        element: <Layout/>,
        children: [
            {path: '/', element: <HomePage/>},
            {path: '/about', element: <AboutPage/>},
        ],
    },
];

export default routes;

App.tsx์—์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

๐Ÿšจ RouterProvider์™€ BrowserRouter๋ฅผ ๋™์‹œ์— ์“ธ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€

caught Error: You cannot render a <Router> inside another <Router>. You should never have more than one in your app.

// src/App.tsx

import {createBrowserRouter, RouterProvider} from 'react-router-dom';
import routes from './routes';

const router = createBrowserRouter(routes);

export default function App() {
    return (
        <RouterProvider router={router}/>
    );
}

๐Ÿ’ก App ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ๋ธŒ๋ผ์šฐ์ € ๋ผ์šฐํ„ฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋จ

// src/main.tsx

import {createBrowserRouter, RouterProvider} from 'react-router-dom';

import routes from './routes';

const router = createBrowserRouter(routes);

root.render((
    <React.StrictMode>
        <RouterProvider router={router}/>
    </React.StrictMode>
));

4. createMemoryRouter

createMemoryRouter

App.tsx๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์—, routes.test.tsx๋กœ ๋ณ€๊ฒฝ routes๊ฐ€ ๋ผ์šฐํŒ… ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Œ

createMemoryRouter๋Š” ๋ธŒ๋ผ์šฐ์ €์˜ ๊ธฐ๋ก์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ๋ฉ”๋ชจ๋ฆฌ ๋ผ์šฐํ„ฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ž์ฒด ๊ธฐ๋ก ์Šคํƒ์„ ๊ด€๋ฆฌ Storybook๊ณผ ๊ฐ™์€ ํ…Œ์ŠคํŠธ ๋ฐ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ๋„๊ตฌ์— ์ฃผ๋กœ ์œ ์šฉํ•˜์ง€๋งŒ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹Œ ๋ชจ๋“  ํ™˜๊ฒฝ์—์„œ React Router๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

๋ฉ”๋ชจ๋ฆฌ ๋ผ์šฐํ„ฐ ๋งŒ๋“ค์–ด์„œ ํ…Œ์ŠคํŠธ

describe('routes', () => {
    function renderRouter(path: string) {
        const router = createMemoryRouter(routes, {initialEntries: [path]});
        render(<RouterProvider router={router}/>);
    }
    
    context('when the current path is โ€œ/โ€', () => {
        it('renders the home page', () => {
            renderRouter('/');
            
            screen.getByText(/Hello/);
        });
    });
    
    context('when the current path is โ€œ/aboutโ€', () => {
        it('renders the about page', () => {
            renderRouter('/about');
            
            screen.getByText(/About/);
        });
    });
});

Last updated