[๐ŸŽ์ฝ”๋”ฉ์• ํ”Œ ๊ฐ•์˜์š”์•ฝ] ๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ ์…‹ํŒ…์ด๋ž‘ ๊ธฐ๋ณธ ๋ผ์šฐํŒ… ๐Ÿš€

๐ŸŒˆ KJยท2025๋…„ 6์›” 3์ผ

codingapple

๋ชฉ๋ก ๋ณด๊ธฐ
18/23
post-thumbnail

๋ฆฌ์•กํŠธ ๋ผ์šฐํ„ฐ 1 : ์…‹ํŒ…์ด๋ž‘ ๊ธฐ๋ณธ ๋ผ์šฐํŒ… ๐Ÿš€

์˜ค๋Š˜์˜ ์ˆ™์ œ ๐Ÿ“

/detail๋กœ ์ ‘์†ํ•˜๋ฉด ๋ณด์—ฌ์ค„ ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ๋งŒ๋“ค์–ด์˜ค์‹ญ์‹œ์˜ค.
์ค‘์š”: ์ปดํฌ๋„ŒํŠธ์šฉ ํŒŒ์ผ์€ .js ๋ง๊ณ  .jsx ํ™•์žฅ์ž๋กœ ์ง€์–ด์•ผ Vite ํ™˜๊ฒฝ์—์„œ ์ž˜๋ฉ๋‹ˆ๋‹ค! โš ๏ธ

React์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋‚˜๋ˆ„๋Š” ๋ฐฉ๋ฒ• ๐Ÿ“„

์ผ๋ฐ˜ ์›น์‚ฌ์ดํŠธ vs React

  • ์ผ๋ฐ˜ HTML ์‚ฌ์ดํŠธ: HTML ํŒŒ์ผ ์—ฌ๋Ÿฌ ๊ฐœ = ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€
  • React: HTML ํŒŒ์ผ ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉ, <div> ๋‚ด์šฉ์„ ๊ฐˆ์•„์น˜์›Œ์„œ ํŽ˜์ด์ง€ ์ „ํ™˜

React์—์„œ๋Š” ์ง์ ‘ ์ฝ”๋“œ ์งœ๊ธฐ ๊ท€์ฐฎ์œผ๋‹ˆ react-router-dom ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค! ๐Ÿ’ก

react-router-dom ์„ค์น˜ ๋ฐ ์…‹ํŒ… ๐Ÿ”ง

1๋‹จ๊ณ„: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด ์ž…๋ ฅ:

npm install react-router-dom@6

2๋‹จ๊ณ„: ๊ธฐ๋ณธ ์…‹ํŒ…

index.js (๋˜๋Š” main.jsx) ํŒŒ์ผ ์ˆ˜์ •:

import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

์…‹ํŒ… ์™„๋ฃŒ! ๐Ÿ“ฆ
1. BrowserRouter importํ•˜๊ธฐ
2. <BrowserRouter>๋กœ <App/> ๊ฐ์‹ธ๊ธฐ

๋ผ์šฐํ„ฐ๋กœ ํŽ˜์ด์ง€ ๋‚˜๋ˆ„๋Š” ๋ฒ• ๐Ÿ”€

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

์›น์‚ฌ์ดํŠธ URL ๊ฒฝ๋กœ๋งˆ๋‹ค ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ:

// App.js
import { Routes, Route, Link } from 'react-router-dom'

function App(){
  return (
    // ์ƒ๋žต
    <Routes>
      <Route path="/detail" element={ <div>์ƒ์„ธํŽ˜์ด์ง€์ž„</div> } />
      <Route path="/about" element={ <div>์–ด๋ฐ”์›ƒํŽ˜์ด์ง€์ž„</div> } />
    </Routes>
  )
}

์ž‘์„ฑ ์ˆœ์„œ ๐Ÿ“‹

  1. ์ƒ๋‹จ์—์„œ Routes, Route, Link ์ปดํฌ๋„ŒํŠธ import
  2. <Routes> ๋งŒ๋“ค๊ณ  ๊ทธ ์•ˆ์— <Route> ์ž‘์„ฑ
  3. <Route path="/url๊ฒฝ๋กœ" element={ <๋ณด์—ฌ์ค„html> } /> ํ˜•ํƒœ๋กœ ์ž‘์„ฑ

๋ฉ”์ธํŽ˜์ด์ง€ ์„ค์ •

<Route path="/" element={ <div>๋ฉ”์ธํŽ˜์ด์ง€์—์„œ ๋ณด์—ฌ์ค„๊ฑฐ</div> } />

path="/"๋Š” ๋ฉ”์ธํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ 

๋ฉ”์ธํŽ˜์ด์ง€์—๋งŒ ์ƒํ’ˆ๋ชฉ๋ก ํ‘œ์‹œํ•˜๊ธฐ

<Route path="/" element={ 
  <>
    <div className="main-bg"></div>
    <div className="container">
      <div className="row">
        {shoes.map((a, i) => {
          return <Card shoes={shoes[i]} i={i}></Card>
        })}
      </div>
    </div> 
  </>
} />

๊ฒฐ๊ณผ:

  • ๋ฉ”์ธํŽ˜์ด์ง€(/) ์ ‘์† ์‹œ์—๋งŒ ์ƒํ’ˆ๋ชฉ๋ก ํ‘œ์‹œ
  • /detail, /about ํŽ˜์ด์ง€์—์„œ๋Š” ์ƒํ’ˆ๋ชฉ๋ก ์ˆจ๊น€

ํŽ˜์ด์ง€ ์ด๋™ ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ ๐Ÿ”—

์œ ์ €๋“ค์€ ์ฃผ์†Œ์ฐฝ ์ž…๋ ฅ์ด ์•„๋‹Œ ๋งํฌ๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค:

<Link to="/">ํ™ˆ</Link>
<Link to="/detail">์ƒ์„ธํŽ˜์ด์ง€</Link>

ํŠน์ง•:

  • <Link to="๊ฒฝ๋กœ">ํ…์ŠคํŠธ</Link> ํ˜•ํƒœ
  • ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น URL ๊ฒฝ๋กœ๋กœ ์ด๋™
  • ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ ์—†์ด ๋ถ€๋“œ๋Ÿฌ์šด ์ „ํ™˜

๋ณด์ถฉ ์„ค๋ช… ๐Ÿ’ก

SPA (Single Page Application) ๊ฐœ๋… ๐ŸŒ

๊ธฐ์กด ๋ฐฉ์‹ (MPA - Multi Page Application):

ํŽ˜์ด์ง€ ์ด๋™ โ†’ ์„œ๋ฒ„ ์š”์ฒญ โ†’ ์ƒˆ HTML ๋ฐ›๊ธฐ โ†’ ์ „์ฒด ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ

React ๋ฐฉ์‹ (SPA):

ํŽ˜์ด์ง€ ์ด๋™ โ†’ JS๋กœ ์ปดํฌ๋„ŒํŠธ ๊ต์ฒด โ†’ ๋น ๋ฅธ ํ™”๋ฉด ์ „ํ™˜

SPA์˜ ์žฅ์ :

  • ๋น ๋ฅธ ํŽ˜์ด์ง€ ์ „ํ™˜ (์ƒˆ๋กœ๊ณ ์นจ ์—†์Œ)
  • ๋ถ€๋“œ๋Ÿฌ์šด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜
  • ์„œ๋ฒ„ ๋ถ€ํ•˜ ๊ฐ์†Œ

๋ผ์šฐํ„ฐ ์ข…๋ฅ˜์™€ ์ฐจ์ด์  ๐Ÿ”

1. BrowserRouter vs HashRouter

// BrowserRouter (๊ถŒ์žฅ)
// URL: https://mysite.com/about
<BrowserRouter>
  <App />
</BrowserRouter>

// HashRouter  
// URL: https://mysite.com/#/about
<HashRouter>
  <App />
</HashRouter>

2. ์„œ๋ฒ„ ์„ค์ • ๊ณ ๋ ค์‚ฌํ•ญ

  • BrowserRouter: ์„œ๋ฒ„์—์„œ ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ index.html๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์„ค์ • ํ•„์š”
  • HashRouter: ์„œ๋ฒ„ ์„ค์ • ๋ถˆํ•„์š”, ํ•˜์ง€๋งŒ SEO์— ๋ถˆ๋ฆฌ

๊ณ ๊ธ‰ ๋ผ์šฐํŒ… ํŒจํ„ด ๐ŸŽฏ

1. ์ค‘์ฒฉ ๋ผ์šฐํŠธ (Nested Routes)

<Routes>
  <Route path="/shop" element={<ShopLayout />}>
    <Route path="products" element={<Products />} />
    <Route path="categories" element={<Categories />} />
  </Route>
</Routes>

2. ๋™์  ๋ผ์šฐํŠธ (Dynamic Routes)

<Routes>
  <Route path="/product/:id" element={<ProductDetail />} />
  <Route path="/user/:userId/posts/:postId" element={<PostDetail />} />
</Routes>

3. ์กฐ๊ฑด๋ถ€ ๋ผ์šฐํŒ…

function ProtectedRoute({ children }) {
  const isAuthenticated = useAuth();
  return isAuthenticated ? children : <Navigate to="/login" />;
}

<Route path="/dashboard" element={
  <ProtectedRoute>
    <Dashboard />
  </ProtectedRoute>
} />

๋ผ์šฐํ„ฐ ํ›… ํ™œ์šฉ ๐Ÿช

1. useNavigate - ํ”„๋กœ๊ทธ๋ž˜๋ฐ์  ๋„ค๋น„๊ฒŒ์ด์…˜

import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();
  
  const handleClick = () => {
    // ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ํŽ˜์ด์ง€ ์ด๋™
    if (isLoggedIn) {
      navigate('/dashboard');
    } else {
      navigate('/login');
    }
  };
}

2. useLocation - ํ˜„์žฌ ์œ„์น˜ ์ •๋ณด

import { useLocation } from 'react-router-dom';

function MyComponent() {
  const location = useLocation();
  
  // ํ˜„์žฌ ๊ฒฝ๋กœ์— ๋”ฐ๋ฅธ ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง
  const isHomePage = location.pathname === '/';
}

3. useParams - URL ํŒŒ๋ผ๋ฏธํ„ฐ ์ ‘๊ทผ

import { useParams } from 'react-router-dom';

function ProductDetail() {
  const { id } = useParams();
  
  // /product/123 ์ ‘์† ์‹œ id = "123"
}

์„ฑ๋Šฅ ์ตœ์ ํ™” โšก

1. ์ฝ”๋“œ ์Šคํ”Œ๋ฆฌํŒ… (Code Splitting)

import { lazy, Suspense } from 'react';

const About = lazy(() => import('./components/About'));
const Contact = lazy(() => import('./components/Contact'));

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={
        <Suspense fallback={<div>๋กœ๋”ฉ ์ค‘...</div>}>
          <About />
        </Suspense>
      } />
    </Routes>
  );
}

2. ๋ผ์šฐํŠธ ๊ธฐ๋ฐ˜ ์Šคํ”Œ๋ฆฌํŒ…

// ๊ฐ ํŽ˜์ด์ง€๋ฅผ ๋ณ„๋„ ์ฒญํฌ๋กœ ๋ถ„๋ฆฌ
const routes = [
  {
    path: '/products',
    component: lazy(() => import('./pages/Products'))
  },
  {
    path: '/orders', 
    component: lazy(() => import('./pages/Orders'))
  }
];

0๊ฐœ์˜ ๋Œ“๊ธ€