1. Routerλ
- Route = κ²½λ‘ c.f. λ°μ : 루νΈ
- Router = κ²½λ‘μ°Ύλ κ² c.f. μκ΅λ°μ : 루ν°, λ―Έκ΅λ°μ : λΌμ°ν°
- c.f. μλ‘ λ€λ₯Έ λ€νΈμν¬λ₯Ό μ°κ²°ν΄μ£Όλ μ₯μΉλ₯Ό βλΌμ°ν°βλΌκ³ ν¨
- λΌμ°ν = μ¬μ©μκ° μμ²ν URLμ λ°λΌ μλ§λ νμ΄μ§λ₯Ό 보μ¬μ£Όλ κ²μ μλ―Έ
- React Router λΌμ΄λΈλ¬λ¦¬ μ’
λ₯
- React Router β Official WebsiteβοΈ
- React μ ν리μΌμ΄μ μμ λΌμ°ν μ ꡬνν λ κ°μ₯ μ λͺ ν λΌμ΄λΈλ¬λ¦¬
- μ½κ² μ±κΈ νμ΄μ§ μ ν리μΌμ΄μ (Single Page Application)μ λ§λ€ μ μμ
- React Router v6 (22λ κΈ°μ€ μ΅μ λ²μ )
- μ°Έκ³ : 벨λ‘νΌνΈ React Router v6 νν 리μΌ
- Reach Router β Official Website
- React Router β Official WebsiteβοΈ
2. React Router κΈ°λ³Έ μ¬μ©λ²
2.1 μ€μΉ
1$ yarn create react-app router-tutorial # μ°μ΅μ© ν΄λ2$ cd router-tutorial34$ yarn add react-router-dom # React Router μ€μΉ
2.2 νλ‘μ νΈμ λΌμ°ν° μ μ©
1import React from 'react'2import ReactDOM from 'react-dom/client'3import App from './App'4import { BrowserRouter } from 'react-router-dom' // μΆκ°56const root = ReactDOM.createRoot(document.getElementById('root'))7root.render(8<BrowserRouter>9<App />10</BrowserRouter>,11)
- react-router-domμ λ΄μ₯λμ΄ μλ
BrowserRouter μ»΄ν¬λνΈλ₯Ό μ¬μ©νμ¬ κ°μΈκΈ°- BrowserRouter μ»΄ν¬λνΈ
- μΉ μ ν리μΌμ΄μ μ HTML5μ History APIλ₯Ό μ¬μ©νμ¬ νμ΄μ§λ₯Ό μλ‘ λΆλ¬μ€μ§ μκ³ ,
- μ£Όμλ₯Ό λ³κ²½νκ³ νμ¬ μ£Όμμ κ²½λ‘μ κ΄λ ¨λ μ 보λ₯Ό 리μ‘νΈ μ»΄ν¬λνΈμμ μ¬μ©ν μ μλλ‘ ν΄μ€
- BrowserRouter μ»΄ν¬λνΈ
2.3 μμ : νμ΄μ§ μ»΄ν¬λνΈ μμ±
1// src/pages/Home.js2export default function Home() {3return (4<div>5<h1>ν</h1>6<p>κ°μ₯ λ¨Όμ 보μ¬μ§λ νμ΄μ§μ λλ€.</p>7</div>8)9}
1// src/pages/About.js2export default function About() {3return (4<div>5<h1>μκ°</h1>6<p>리μ‘νΈ λΌμ°ν°λ₯Ό μ¬μ©ν΄ 보λ νλ‘μ νΈμ λλ€.</p>7</div>8)9}
2.4 νΉμ κ²½λ‘μ μνλ μ»΄ν¬λνΈ λ³΄μ¬μ£ΌκΈ° : Route
- μ£Όμ κ²½λ‘μ λ°λΌ μνλ μ»΄ν¬λνΈλ₯Ό 보μ¬μ£ΌκΈ° μν΄
Route μ»΄ν¬λνΈλ₯Ό ν΅ν΄ λΌμ°νΈ μ€μ Route μ»΄ν¬λνΈλRoutes μ»΄ν¬λνΈλ΄λΆμμ μ¬μ©λμ΄μΌ ν¨- μ¬μ©λ² :
<Route path="μ£Όμκ·μΉ" element={보μ¬μ€ μ»΄ν¬λνΈ} />
1import { Route, Routes } from 'react-router-dom'2import About from './pages/About'3import Home from './pages/Home'45export default function App() {6return (7<Routes>8<Route path="/" element={<Home />} />9<Route path="/about" element={<About />} />10</Routes>11)12}
yarn start λ₯Ό μ
λ ₯νμ¬ κ°λ° μλ²λ₯Ό μμ
2.5 λ€λ₯Έ νμ΄μ§λ‘ μ΄λνλ λ§ν¬ 보μ¬μ£ΌκΈ° : Link
μΉ νμ΄μ§μμλ μλ λ§ν¬λ₯Ό 보μ¬μ€ λ, a νκ·Έλ₯Ό μ¬μ©νλλ°,
- 리μ‘νΈ λΌμ°ν°λ₯Ό μ¬μ©νλ νλ‘μ νΈμμ aνκ·Έλ₯Ό λ°λ‘ μ¬μ©νλ©΄ μλ¨
- μλνλ©΄, a νκ·Έλ₯Ό ν΄λ¦ν΄ νμ΄μ§λ₯Ό μ΄λνλ©΄, λΈλΌμ°μ κ° νμ΄μ§λ₯Ό μλ‘ λΆλ¬μ€κ² λκΈ° λλ¬Έ β 리λ λλ§
Link μ»΄ν¬λνΈ
Link μ»΄ν¬λνΈμμ a νκ·Έλ₯Ό μ¬μ©νκΈ΄ νμ§λ§,- νμ΄μ§λ₯Ό μλ‘ λΆλ¬μ€λ κ²μ λ§κ³ , History APIλ₯Ό ν΅ν΄ λΈλΌμ°μ μ£Όμμ κ²½λ‘λ§ λ°κΎΈλ κΈ°λ₯μ΄ λ΄μ₯λμ΄ μμ
- μ¬μ©λ² :
<Link to="κ²½λ‘">λ§ν¬ μ΄λ¦</Link>
2.5.1 μμ
Home νμ΄μ§μμ About νμ΄μ§λ‘ μ΄λν μ μλλ‘ Link μ»΄ν¬λνΈλ₯Ό Home μ»΄ν¬λνΈμμ μ¬μ©
1// src/pages/Home.js2import { Link } from 'react-router-dom'34export default function Home() {5return (6<div>7<h1>ν</h1>8<p>κ°μ₯ λ¨Όμ 보μ¬μ§λ νμ΄μ§μ λλ€.</p>9<Link to="/about">μκ°</Link>10</div>11)12}
3. URL νλΌλ―Έν°μ 쿼리μ€νΈλ§
νμ΄μ§ μ£Όμλ₯Ό μ μν λ κ°λμ μ λμ μΈ κ°μ μ¬μ©ν΄μΌ ν λλ μμ΅λλ€. λ€μκ³Ό κ°μ΄ λ§μ΄μ£ .
URL νλΌλ―Έν°- μ£Όμμ κ²½λ‘μ μ λμ μΈ κ°μ λ£λ νν
- ID λλ μ΄λ¦μ μ¬μ©νμ¬ νΉμ λ°μ΄ν°λ₯Ό μ‘°νν λ μ¬μ©
- e.g. /profile/velopert
쿼리μ€νΈλ§(Querystring)- μ£Όμμ λ·λΆλΆμ
?λ¬Έμμ΄ μ΄νμ key=value λ‘ κ°μ μ μνλ©°,&λ‘ κ΅¬λΆμ νλ νν - ν€μλ κ²μ, νμ΄μ§λ€μ΄μ , μ λ ¬ λ°©μ λ± λ°μ΄ν° μ‘°νμ νμν μ΅μ μ μ λ¬ν λ μ¬μ©
- e.g. /articles?page=1&keyword=react
- μ£Όμμ λ·λΆλΆμ
3.1 μμ : URL νλΌλ―Έν°
Profile μ»΄ν¬λνΈλ₯Ό pages κ²½λ‘μ λ€μκ³Ό κ°μ΄ μμ±
1// src/pages/Profile.js2import { useParams } from 'react-router-dom'34const data = {5velopert: {6name: 'κΉλ―Όμ€',7description: '리μ‘νΈλ₯Ό μ’μνλ κ°λ°μ',8},9gildong: {10name: 'νκΈΈλ',11description: 'κ³ μ μμ€ νκΈΈλμ μ μ£ΌμΈκ³΅',12},13}1415export default function Profile() {16// URL νλΌλ―Έν°μ μ΄λ¦μ λΌμ°νΈ μ€μ μ ν λ Route μ»΄ν¬λνΈμ path propsλ₯Ό ν΅νμ¬ μ€μ 17const params = useParams() // useParams Hookμ μ¬μ©νμ¬ κ°μ²΄ ννλ‘ μ‘°ν κ°λ₯18const profile = data[params.username] // username URL νλΌλ―Έν°λ₯Ό ν΅νμ¬ νλ‘νμ μ‘°ν1920return (21<div>22<h1>μ¬μ©μ νλ‘ν</h1>23{profile ? (24<div>25<h2>{profile.name}</h2>26<p>{profile.description}</p>27</div>28) : (29<p>μ‘΄μ¬νμ§ μλ νλ‘νμ λλ€.</p>30)}31</div>32)33}
App μ»΄ν¬λνΈ νμΌμ μ΄μ΄μ μλ‘μ΄ λΌμ°νΈλ₯Ό λ€μκ³Ό κ°μ΄ μ€μ νκΈ°
1// src/App.js2import { Route, Routes } from 'react-router-dom'3import About from './pages/About'4import Home from './pages/Home'5import Profile from './pages/Profile'67export default function App() {8return (9<Routes>10<Route path="/" element={<Home />} />11<Route path="/about" element={<About />} />12{/* URL νλΌλ―Έν°λ /profiles/:username κ³Ό κ°μ΄ κ²½λ‘μ : λ₯Ό μ¬μ©νμ¬ μ€μ */}13{/* λ§μ½ URL νλΌλ―Έν°κ° μ¬λ¬κ°μΈ κ²½μ°μ /profiles/:username/:field μ κ°μ ννλ‘ μ€μ κ°λ₯ */}14<Route path="/profiles/:username" element={<Profile />} />15</Routes>16)17}
Profile νμ΄μ§λ‘ μ΄λμ ν μ μλλ‘ Home νμ΄μ§μ Link λ₯Ό λ λ§λ€κΈ°
1// src/pages/Home.js2import { Link } from 'react-router-dom'34export default function Home() {5return (6<div>7<h1>ν</h1>8<p>κ°μ₯ λ¨Όμ 보μ¬μ§λ νμ΄μ§μ λλ€.</p>9<ul>10<li>11<Link to="/about">μκ°</Link>12</li>13<li>14<Link to="/profiles/velopert">velopertμ νλ‘ν</Link>15</li>16<li>17<Link to="/profiles/gildong">gildongμ νλ‘ν</Link>18</li>19<li>20<Link to="/profiles/void">μ‘΄μ¬νμ§ μλ νλ‘ν</Link>21</li>22</ul>23</div>24)25}
μ΄μ μλ‘ λ§λ λ§ν¬λ₯Ό λλ¬μ Profile νμ΄μ§λ‘ μ΄λν΄λ³΄μΈμ.
3.2 μμ : 쿼리μ€νΈλ§
쿼리μ€νΈλ§μ μ¬μ©ν λλ URL νλΌλ―Έν°μ λ¬λ¦¬ Route μ»΄ν¬λνΈλ₯Ό μ¬μ©ν λ λ³λλ‘ μ€μ ν΄μΌλλ κ²μ μμ΅λλ€.
π‘
useLocation()location κ°μ²΄λ₯Ό λ°ννλ©°, μ΄ κ°μ²΄λ νμ¬ μ¬μ©μκ° λ³΄κ³ μλ νμ΄μ§μ μ 보λ₯Ό μ§λ Hook
locationκ°μ²΄ μμλ λ€μκ³Ό κ°μ κ°μ΄ λ€μ΄μμ
- pathname : νμ¬ μ£Όμμ κ²½λ‘ (쿼리μ€νΈλ§ μ μΈ)
- search : 맨 μμ ? λ¬Έμ ν¬ν¨ν 쿼리μ€νΈλ§ κ°
- hash : μ£Όμμ # λ¬Έμμ΄ λ€μ κ°
- μ£Όλ‘ History APIκ° μ§μμλλ ꡬν λΈλΌμ°μ μμ ν΄λΌμ΄μΈνΈ λΌμ°ν μ μ¬μ©ν λ μ°λ ν΄μ λΌμ°ν°μμ μ¬μ©
- state : νμ΄μ§λ‘ μ΄λν λ μμλ‘ λ£μ μ μλ μν κ°
- key :
locationκ°μ²΄μ κ³ μ κ°
- μ΄κΈ°μλ
defaultμ΄λ©° νμ΄μ§κ° λ³κ²½λ λλ§λ€ κ³ μ μ κ°μ΄ μμ±λ¨
About νμ΄μ§ μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ ν΄λ³΄μΈμ.
1// src/pages/About.js2import { useLocation } from 'react-router-dom'34export default function About() {5// useLocation() : location κ°μ²΄λ₯Ό λ°ν6// - location κ°μ²΄λ νμ¬ μ¬μ©μκ° λ³΄κ³ μλ νμ΄μ§μ μ 보λ₯Ό μ§λ Hook7const location = useLocation()89return (10<div>11<h1>μκ°</h1>12<p>리μ‘νΈ λΌμ°ν°λ₯Ό μ¬μ©ν΄ 보λ νλ‘μ νΈμ λλ€.</p>13<p>쿼리μ€νΈλ§: {location.search}</p>14</div>15)16}
쿼리μ€νΈλ§μ location.search κ°μ ν΅ν΄ μ‘°νλ₯Ό ν μ μμ΅λλ€.
μ£Όμμ°½μ http://localhost:3000/about?detail=true&mode=1λ₯Ό μ
λ ₯ν΄μ μ΄λ€ κ°μ΄ λνλλμ§ νμΈν΄λ³΄μΈμ.
쿼리μ€νΈλ§ κ°μ΄ ?detail=true&mode=1 μΌλ‘ νμλ©λλ€.
μ΄ λ¬Έμμ΄μμ ? λ‘ μ§μ°κ³ , & λ¬Έμμ΄λ‘ λΆλ¦¬νλ€ key μ value λ₯Ό νμ±νλ μμ
μ ν΄μΌ ν©λλ€.
μ΄ μμ
μ λ³΄ν΅ npm μμ qs λλ querystring ν¨ν€μ§λ₯Ό μ€μΉν΄μ μ²λ¦¬ν μ μμ΅λλ€.
쿼리μ€νΈλ§μ λ°λ‘ νμ±κΉμ§ ν΄μΌλλ€λ©΄ λ²κ±°λ‘μΈμλ μλλ°,
리μ‘νΈ λΌμ°ν°μμλ v6λΆν° useSearchParams λΌλ Hookμ μ 곡ν©λλ€.
π‘
useSearchParamsλ°°μ΄ νμ μ κ°μ λ°ννλ©°,
- 첫λ²μ§Έ μμλ 쿼리 νλΌλ―Έν°λ₯Ό μ‘°ννκ±°λ μμ νλ λ©μλλ€μ΄ λ΄κΈ΄ κ°μ²΄λ₯Ό λ°ν
getλ©μλλ₯Ό ν΅ν΄ νΉμ 쿼리νλΌλ―Έν°λ₯Ό μ‘°νsetλ©μλλ₯Ό ν΅ν΄ νΉμ 쿼리νλΌλ―Έν°λ₯Ό μ λ°μ΄νΈ
- λ§μ½ μ‘°νμμ 쿼리νλΌλ―Έν°κ° μ‘΄μ¬νμ§ μλλ€λ©΄
nullλ‘ μ‘°ν- λλ²μ§Έ μμλ 쿼리 νλΌλ―Έν°λ₯Ό κ°μ²΄ννλ‘ μ λ°μ΄νΈν μ μλ ν¨μλ₯Ό λ°ν
쿼리νλΌλ―Έν°λ₯Ό μ¬μ©ν λ μ£Όμν μ
- 쿼리νλΌλ―Έν°λ₯Ό μ‘°νν λ κ°μ 무쑰건 λ¬Έμμ΄ νμ μ
booleanκ°μ λ£κ³ κ°μ λΉκ΅νλ €λ©΄, λ°λμ'true'κ°μ΄ λ°μ΄νλ‘ κ°μΈμ λΉκ΅λ₯Ό ν΄μΌ ν¨- μ«μλ₯Ό λ€λ£¨κ² λλ€λ©΄
parseIntλ₯Ό μ¬μ©νμ¬ μ«μ νμ μΌλ‘ λ³ν
λ€μμ μ΄ Hookμ μ¬μ©νμ¬ μΏΌλ¦¬μ€νΈλ§μ μ½κ² νμ±νμ¬ μ¬μ©νλ μμμ λλ€.
1// src/pages/About.js2import { useSearchParams } from 'react-router-dom'34export default function About() {5const [searchParams, setSearchParams] = useSearchParams() // 쿼리μ€νΈλ§μ νμ±ν΄μ£Όλ Hook6const detail = searchParams.get('detail') // get() : νΉμ 쿼리 νλΌλ―Έν°λ₯Ό μ‘°ν7const mode = searchParams.get('mode')89const onToggleDetail = () => {10// detail 쿼리 νλΌλ―Έν°μ κ°μ΄ trueμ΄λ©΄11setSearchParams({ mode, detail: detail === 'true' ? false : true })12}1314const onIncreaseMode = () => {15// mode 쿼리 νλΌλ―Έν°μ κ°μ΄ nullμ΄λ©΄16const nextMode = mode === null ? 1 : parseInt(mode) + 117setSearchParams({ mode: nextMode, detail })18}1920return (21<div>22<h1>μκ°</h1>23<p>리μ‘νΈ λΌμ°ν°λ₯Ό μ¬μ©ν΄ 보λ νλ‘μ νΈμ λλ€.</p>24<p>detail: {detail}</p>25<p>mode: {mode}</p>26<button onClick={onToggleDetail}>Toggle detail</button>27<button onClick={onIncreaseMode}>mode + 1</button>28</div>29)30}

4. μ€μ²©λ λΌμ°νΈ
μ€μ²©λ λΌμ°νΈλ₯Ό μ΄ν΄ν΄λ³΄κΈ° μνμ¬, κ²μκΈ λͺ©λ‘μ 보μ¬μ£Όλ νμ΄μ§μ κ²μκΈμ μ½λ νμ΄μ§λ₯Ό λ§λ€μ΄λ³΄κ² μ΅λλ€
1// src/pages/Articles.js2import { Link } from 'react-router-dom'34export default function Articles() {5return (6<ul>7<li>8<Link to="/articles/1">κ²μκΈ 1</Link>9</li>10<li>11<Link to="/articles/2">κ²μκΈ 2</Link>12</li>13<li>14<Link to="/articles/3">κ²μκΈ 3</Link>15</li>16</ul>17)18}
1// src/pages/Article.js2import { useParams } from 'react-router-dom'34export default function Article() {5const { id } = useParams()6return (7<div>8<h2>κ²μκΈ {id}</h2>9</div>10)11}
λ μ»΄ν¬λνΈλ₯Ό λ§λ€μλ€λ©΄, ν΄λΉ νμ΄μ§λ€μ λΌμ°νΈλ₯Ό App μ»΄ν¬λνΈμμ μ€μ
1import { Route, Routes } from 'react-router-dom'2import About from './pages/About'3import Article from './pages/Article'4import Articles from './pages/Articles'5import Home from './pages/Home'6import Profile from './pages/Profile'78export default function App() {9return (10<Routes>11<Route path="/" element={<Home />} />12<Route path="/about" element={<About />} />13<Route path="/profiles/:username" element={<Profile />} />14<Route path="/articles" element={<Articles />} />15<Route path="/articles/:id" element={<Article />} />16</Routes>17)18}
κ·Έ λ€μμλ Home μ»΄ν¬λνΈμμ κ²μκΈ λͺ©λ‘ νμ΄μ§λ‘ κ°λ λ§ν¬λ₯Ό μΆκ°
1// src/pages/Home.js2import { Link } from 'react-router-dom'34export default function Home() {5return (6<div>7<h1>ν</h1>8<p>κ°μ₯ λ¨Όμ 보μ¬μ§λ νμ΄μ§μ λλ€.</p>9<ul>10μλ΅...11<li>12<Link to="/articles">κ²μκΈ λͺ©λ‘</Link>13</li>14</ul>15</div>16)17}
κ²μκΈ λͺ©λ‘ νμ΄μ§λ₯Ό μ΄μ΄μ λͺ©λ‘μ΄ μ λνλλμ§ νμΈνκ³ , κ²μκΈμ λ§ν¬λ₯Ό λλ¬ κ²μκΈ μ½κΈ° νμ΄μ§λ μ λνλλμ§ νμΈν΄λ³΄μΈμ.
κ²μκΈ λͺ©λ‘ νμ΄μ§μμ κ²μκΈμ μ΄μμ λ, κ²μκΈμ νλ¨μ λͺ©λ‘μ 보μ¬μ€μΌνλ€λ©΄ μ΄λ¨κΉμ?
λ§μ½ κΈ°μ‘΄ λ°©μμΌλ‘ ꡬνμ νλ€λ©΄ μλ§ λ€μκ³Ό κ°μ΄ ArticleList μ»΄ν¬λνΈλ₯Ό λ°λ‘ λ§λ€μ΄μ,
κ° νμ΄μ§ μ»΄ν¬λνΈμμ μ¬μ©μ ν΄μΌλμ κ²μ
λλ€.
1<div>2<h2>κ²μκΈ {id}</h2>3<ArticleList />4</div>
μ€μ²©λ λΌμ°νΈλ₯Ό μ¬μ©νλ€λ©΄ μ’ λ λμ λ°©μμΌλ‘ ꡬνμ ν μ μμ΅λλ€. μ΄λ²μλ μ€μ²©λ λΌμ°νΈ ννλ‘ λΌμ°νΈλ₯Ό μ€μ ν΄λ³΄κ² μ΅λλ€.
1import { Route, Routes } from 'react-router-dom'2import About from './pages/About'3import Article from './pages/Article'4import Articles from './pages/Articles'5import Home from './pages/Home'6import Profile from './pages/Profile'78export default function App() {9return (10<Routes>11<Route path="/" element={<Home />} />12<Route path="/about" element={<About />} />13<Route path="/profiles/:username" element={<Profile />} />14<Route path="/articles" element={<Articles />} />15<Route path="/articles" element={<Articles />}>16<Route path=":id" element={<Article />} />17</Route>18</Routes>19)20}
κ·Έ λ€μμλ Articles μ»΄ν¬λνΈμμ 리μ‘νΈ λΌμ°ν°μμ μ 곡νλ Outlet μ»΄ν¬λνΈλ₯Ό μ¬μ©ν΄μΌ ν©λλ€.
Outlet μ»΄ν¬λνΈ:RouteμchildrenμΌλ‘ λ€μ΄κ°λ JSX μ리먼νΈλ₯Ό 보μ¬μ£Όλ μν- μ§κΈμ κ²½μ°μ λ€μ λ΄μ©μ΄
Outletμ»΄ν¬λνΈλ₯Ό ν΅ν΄μ 보μ¬μ§ <Route path=":id" element={<Article />} />
- μ§κΈμ κ²½μ°μ λ€μ λ΄μ©μ΄
Articles μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ ν΄μ£ΌμΈμ.
1// src/pages/Articles.js2import { Link, Outlet } from 'react-router-dom'34export default function Articles() {5return (6<div>7{/* Outlet μ»΄ν¬λνΈκ° μ¬μ©λ μ리μ μ€μ²©λ λΌμ°νΈκ° 보μ¬μ§ */}8<Outlet />9<ul>10<li>11<Link to="/articles/1">κ²μκΈ 1</Link>12</li>13<li>14<Link to="/articles/2">κ²μκΈ 2</Link>15</li>16<li>17<Link to="/articles/3">κ²μκΈ 3</Link>18</li>19</ul>20</div>21)22}
μ΄μ /articles/1 κ²½λ‘μ λ€μ΄κ°λ³΄μΈμ. κ²μκΈ νλ¨μ κ²μκΈ λͺ©λ‘μ΄ μ λνλλμ§ νμΈνμΈμ.
4.1 κ³΅ν΅ λ μ΄μμ μ»΄ν¬λνΈ
μ€μ²©λ λΌμ°νΈμ Outlet μ νμ΄μ§λΌλ¦¬ 곡ν΅μ μΌλ‘ 보μ¬μ€μΌ νλ λ μ΄μμμ΄ μμλλ μ μ©νκ² μ¬μ©ν¨
- e.g.
Home,About,Profileνμ΄μ§μμ μλ¨μ ν€λλ₯Ό 보μ¬μ€μΌ νλ μν© - μ€μ²©λ λΌμ°νΈμ
Outletμ νμ©νμ¬ κ΅¬ννλ©΄, μ»΄ν¬λνΈλ₯Ό νλ²λ§ μ¬μ©ν΄λ λλ€λ μ₯μ μ΄ μμ
μ°μ , κ³΅ν΅ λ μ΄μμμ μν Layout μ»΄ν¬λνΈλ₯Ό src λλ ν°λ¦¬μ λ§λμΈμ.
1// src/Layout.js2import { Outlet } from 'react-router-dom'34export default function Layout() {5return (6<div>7<header style={{ background: 'lightgray', padding: 16, fontSize: 24 }}>Header</header>8<main>9<Outlet />10</main>11</div>12)13}
κ° νμ΄μ§ μ»΄ν¬λνΈκ° 보μ¬μ ΈμΌ νλ λΆλΆμ Outlet μ»΄ν¬λνΈλ₯Ό μ¬μ©ν΄μ£Όμμ΅λλ€.
μ»΄ν¬λνΈλ₯Ό λ€ μμ±νμ
¨μΌλ©΄ App μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ νμΈμ.
1import { Route, Routes } from 'react-router-dom'2import Layout from './Layout'3import About from './pages/About'4import Article from './pages/Article'5import Articles from './pages/Articles'6import Home from './pages/Home'7import Profile from './pages/Profile'89export default function App() {10return (11<Routes>12<Route element={<Layout />}>13<Route path="/" element={<Home />} />14<Route path="/about" element={<About />} />15<Route path="/profiles/:username" element={<Profile />} />16</Route>17<Route path="/articles" element={<Articles />}>18<Route path=":id" element={<Article />} />19</Route>20</Routes>21)22}
μ΄μ Home νμ΄μ§μ λ€μ΄κ°μ, ν€λκ° μ λνλ¬λμ§ νμΈνμΈμ.
4.2 index props
Route μ»΄ν¬λνΈμλ index λΌλ propsκ° μμ΅λλ€.
- props λ
path="/"μ λμΌν μλ―Έλ₯Ό κ°μ§λλ€.
Home μ»΄ν¬λνΈκ° μ¬μ©λ Route μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ λ³κ²½ν΄λ³΄μΈμ
1export default function App() {2return (3<Routes>4<Route element={<Layout />}>5{/* path="/"λ₯Ό indexλ‘ μμ */}6<Route index element={<Home />} />7<Route path="/about" element={<About />} />8<Route path="/profiles/:username" element={<Profile />} />9</Route>10<Route path="/articles" element={<Articles />}>11<Route path=":id" element={<Article />} />12</Route>13</Routes>14)15}
κ·Έλ¦¬κ³ , / κ²½λ‘λ‘ λ€μ΄κ°μ λ μ¬μ ν Home νμ΄μ§κ° μ¬μ ν μ λμ€κ³ μλμ?
indexpropμ μμ λΌμ°νΈμ κ²½λ‘μ μΌμΉνμ§λ§, κ·Έ μ΄νμ κ²½λ‘κ° μ£Όμ΄μ§μ§ μμμλ 보μ¬μ§λ λΌμ°νΈλ₯Ό μ€μ ν λ μ¬μ©path="/"μ λμΌν μν μ νλ©° μ΄λ₯Ό μ’ λ λͺ μμ μΌλ‘ νννλ λ°©λ²
5. 리μ‘νΈ λΌμ°ν° λΆκ°κΈ°λ₯
리μ‘νΈ λΌμ°ν°μλ μΉ μ ν리μΌμ΄μ μμ λΌμ°ν μ κ΄λ ¨λ μμ μ ν λ μ¬μ©ν μ μλ μ μ©ν APIλ€μ μ 곡
5.1 useNavigate
useNavigate:Linkμ»΄ν¬λνΈλ₯Ό μ¬μ©νμ§ μκ³ λ€λ₯Έ νμ΄μ§λ‘ μ΄λμ ν΄μΌ νλ μν©μ μ¬μ©νλ Hook
Layout μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ
1// src/Layout.js2import { Outlet, useNavigate } from 'react-router-dom'34export default function Layout() {5// navigate νλΌλ―Έν°κ° μ«μ νμ μ΄λΌλ©΄ μμΌλ‘ κ°κ±°λ, λ€λ‘ κ°6// navigate(-1) μ νλ©΄ ν λ² λ€λ‘κ°κ³ navigate(-2) λ₯Ό νλ©΄ λ λ² λ€λ‘ κ°7// λ°λλ‘ navigate(1) μ νλ©΄ μμΌλ‘ ν λ² κ° (λ¨, λ€λ‘κ°κΈ°λ₯Ό 1λ²ν μνμ¬μΌ ν¨)8const navigate = useNavigate()910const goBack = () => {11// μ΄μ νμ΄μ§λ‘ μ΄λ12navigate(-1)13}1415// λ€λ₯Έ νμ΄μ§λ‘ μ΄λμ ν λ replace λΌλ μ΅μ μ΄ μ‘΄μ¬16// replace μ΅μ μ μ¬μ©νλ©΄, νμ΄μ§λ₯Ό μ΄λν λ νμ¬ νμ΄μ§λ₯Ό νμ΄μ§ κΈ°λ‘μ λ¨κΈ°μ§ μμ17const goArticles = () => {18// articles κ²½λ‘λ‘ μ΄λ19navigate('/articles')20}2122return (23<div>24<header style={{ background: 'lightgray', padding: 16, fontSize: 24 }}>25<button onClick={goBack}>λ€λ‘κ°κΈ°</button>26<button onClick={goArticles}>κ²μκΈ λͺ©λ‘</button>27</header>28<main>29<Outlet />30</main>31</div>32)33}
λ²νΌμ λλ μλ μ μμ μΌλ‘ μ΄μ νμ΄μ§λ‘ μ΄λνκ±°λ, κ²μκΈ λͺ©λ‘ νμ΄μ§λ‘ μ΄λμ΄ λλμ§ νμΈνμΈμ.
5.1.1 replace μ΅μ
λ€λ₯Έ νμ΄μ§λ‘ μ΄λμ ν λ replace λΌλ μ΅μ
μ΄ μμ΅λλ€.
replace μ΅μ
μ μ¬μ©νλ©΄ νμ΄μ§λ₯Ό μ΄λν λ, νμ¬ νμ΄μ§λ₯Ό νμ΄μ§ κΈ°λ‘μ λ¨κΈ°μ§ μμ΅λλ€.
λ°©κΈ μμ±νλ goArticles ν¨μλ₯Ό λ€μκ³Ό κ°μ΄ μμ ν΄λ³΄μΈμ.
1const goArticles = () => {2navigate('/articles', { replace: true })3}
κ·Έ λ€μμ / κ²½λ‘λ‘ λ€μ΄κ°μ Home νμ΄μ§λ₯Ό λμ΄ λ€μ, μκ° λ§ν¬λ₯Ό λλ¬ About νμ΄μ§λ‘ μ΄λνμΈμ.
κ·Έλ¦¬κ³ , μλ¨μ κ²μκΈ λͺ©λ‘ νμ΄μ§λ₯Ό λλ¬λ³΄μΈμ.
κ·Έ μνμμ λΈλΌμ°μ μ λ€λ‘κ°κΈ° λ²νΌμ λλ¬ μ΄μ νμ΄μ§λ‘ μ΄λμ ν΄λ³΄μΈμ.
λ§μ½ { replace: true } μ€μ μ΄ μμλλΌλ©΄ μ§μ μ λ΄€λ νμ΄μ§μΈ About νμ΄μ§κ° λνλμΌ νμ§λ§,
replace μ΅μ
μ΄ νμ±νλμ΄μκΈ° λλ¬Έμ, κ·Έ μ μ νμ΄μ§μΈ Home νμ΄μ§κ° λνλκ² λ©λλ€.
5.2 NavLink
NavLink μ»΄ν¬λνΈ
- λ§ν¬μμ μ¬μ©νλ κ²½λ‘κ° νμ¬ λΌμ°νΈμ κ²½λ‘μ μΌμΉνλ κ²½μ° νΉμ μ€νμΌ λλ CSS ν΄λμ€λ₯Ό μ μ©νλ μ»΄ν¬λνΈ
styleλλclassNameμ μ€μ ν λ,{ isActive: boolean }μ νλΌλ―Έν°λ‘ μ λ¬λ°λ ν¨μ νμ μ κ°μ μ λ¬ν¨
1<NavLink style={({isActive}) => isActive ? activeStyle : undefined} />2<NavLink className={({isActive}) => isActive ? 'active' : undefined} />
Articles νμ΄μ§ μ»΄ν¬λνΈμμ μ΄ μ»΄ν¬λνΈλ₯Ό μ¬μ©ν΄λ΄
μλ€.
1// src/pages/Articles.js2import { NavLink, Outlet } from 'react-router-dom'34export default function Articles() {5const activeStyle = {6color: 'green',7fontSize: 21,8}910return (11<div>12<Outlet />13<ul>14<li>15<NavLink to="/articles/1" style={({ isActive }) => (isActive ? activeStyle : undefined)}>16κ²μκΈ 117</NavLink>18</li>19<li>20<NavLink to="/articles/2" style={({ isActive }) => (isActive ? activeStyle : undefined)}>21κ²μκΈ 222</NavLink>23</li>24<li>25<NavLink to="/articles/3" style={({ isActive }) => (isActive ? activeStyle : undefined)}>26κ²μκΈ 327</NavLink>28</li>29</ul>30</div>31)32}
νμ¬ λ³΄κ³ μλ κ²μκΈμ λ§ν¬μ ν μ€νΈκ° λ 컀μ§κ³ μ΄λ‘μμΌλ‘ λ³ν©λλ€.
μ€μ λ‘ λΉμ·ν μμ
μ νκ² λλ©΄ νμ¬ NavLink λ₯Ό κ°μΌ λ λ€λ₯Έ μ»΄ν¬λνΈλ₯Ό λ§λ€μ΄μ,
λ€μκ³Ό κ°μ΄ 리ν©ν λ§νμ¬ μ¬μ©νμλ κ²μ κΆμ₯ν©λλ€.
1// src/pages/Articles.js2import { NavLink, Outlet } from 'react-router-dom'34export default function Articles() {5return (6<div>7<Outlet />8<ul>9<ArticleItem id={1} />10<ArticleItem id={2} />11<ArticleItem id={3} />12</ul>13</div>14)15}1617const ArticleItem = ({ id }) => {18const activeStyle = {19color: 'green',20fontSize: 21,21}22return (23<li>24<NavLink to={`/articles/${id}`} style={({ isActive }) => (isActive ? activeStyle : undefined)}>25κ²μκΈ {id}26</NavLink>27</li>28)29}
5.3 NotFound νμ΄μ§
NotFound νμ΄μ§
- μ¬μ μ μ μλμ§ μλ κ²½λ‘μ μ¬μ©μκ° μ§μ νμ λ 보μ¬μ£Όλ νμ΄μ§
- λ€μλ§ν΄, νμ΄μ§λ₯Ό μ°Ύμ μ μμ λ λνλλ νμ΄μ§
NotFound μ»΄ν¬λνΈλ₯Ό μμ±νμΈμ.
1// src/pages/NotFound.js2export default function NotFound() {3return (4<div5style={{6display: 'flex',7alignItems: 'center',8justifyContent: 'center',9fontSize: 64,10position: 'absolute',11width: '100%',12height: '100%',13}}14>1540416</div>17)18}
κ·Έ λ€μμ App μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ
1import { Route, Routes } from 'react-router-dom'2import Layout from './Layout'3import About from './pages/About'4import Article from './pages/Article'5import Articles from './pages/Articles'6import Home from './pages/Home'7import NotFound from './pages/NotFound'8import Profile from './pages/Profile'910export default function App() {11return (12<Routes>13<Route element={<Layout />}>14<Route index element={<Home />} />15<Route path="/about" element={<About />} />16<Route path="/profiles/:username" element={<Profile />} />17</Route>18<Route path="/articles" element={<Articles />}>19<Route path=":id" element={<Article />} />20</Route>21{/* * λ wildcard λ¬Έμλ‘ μ무 ν μ€νΈλ λ§€μΉνλ€λ λ» */}22{/* path="*"λ μμμ μ μν κ²½λ‘ μΈ λͺ¨λ μν©μ λ λλ§λ¨ */}23<Route path="*" element={<NotFound />} />24</Routes>25)26}
5.4 Navigate μ»΄ν¬λνΈ
- μ»΄ν¬λνΈλ₯Ό νλ©΄μ 보μ¬μ£Όλ μκ° λ€λ₯Έ νμ΄μ§λ‘ μ΄λμ νκ³ μΆμ λ μ¬μ©νλ μ»΄ν¬λνΈ
- μ¦, νμ΄μ§λ₯Ό 리λ€μ΄λ νΈ νκ³ μΆμ λ μ¬μ©
- e.g. μ¬μ©μμ λ‘κ·ΈμΈμ΄ νμν νμ΄μ§μΈλ° λ‘κ·ΈμΈμ μνλ€λ©΄ λ‘κ·ΈμΈ νμ΄μ§λ‘ μ΄λ
λ νμ΄μ§ μ»΄ν¬λνΈλ₯Ό pages λλ ν°λ¦¬μ λ§λμΈμ.
1// src/pages/Login.js2export default function Login() {3return <div>λ‘κ·ΈμΈ νμ΄μ§</div>4}
1// src/pages/MyPage.js2import { Navigate } from 'react-router-dom'34export default function MyPage() {5// π isLoggedIn κ°μ΄ λ‘κ·ΈμΈ μνμ λ°λΌ true λλ falseλ₯Ό κ°λ₯΄ν¨λ€κ³ κ°μ 6const isLoggedIn = false78// isLoggedInμ΄ falseλΌλ©΄ Navigate μ»΄ν¬λνΈλ₯Ό ν΅ν΄ /login κ²½λ‘λ‘ μ΄λ9// - replace propsλ useNavigate μμ μ€λͺ ν κ²κ³Ό λμΌν¨10// - νμ΄μ§λ₯Ό μ΄λν λ νμ¬ νμ΄μ§λ₯Ό κΈ°λ‘μ λ¨κΈ°μ§ μκΈ° λλ¬Έμ,11// - μ΄λ ν λ€λ‘κ°κΈ°λ₯Ό λλ μ λ 2 νμ΄μ§ μ μ νμ΄μ§λ‘ μ΄λ12if (!isLoggedIn) {13return <Navigate to="/login" replace={true} />14}1516return <div>λ§μ΄ νμ΄μ§</div>17}
μ»΄ν¬λνΈλ₯Ό λ€ μμ±νμ
¨μΌλ©΄ App μ»΄ν¬λνΈλ₯Ό λ€μκ³Ό κ°μ΄ μμ ν΄μ£ΌμΈμ.
1export default function App() {2return (3<Routes>4<Route element={<Layout />}>5<Route index element={<Home />} />6<Route path="/about" element={<About />} />7<Route path="/profiles/:username" element={<Profile />} />8</Route>9<Route path="/articles" element={<Articles />}>10<Route path=":id" element={<Article />} />11</Route>12<Route path="/login" element={<Login />} />13<Route path="/mypage" element={<MyPage />} />14<Route path="*" element={<NotFound />} />15</Routes>16)17}
κ·Έ λ€μμλ λΈλΌμ°μ μμ /mypage κ²½λ‘λ‘ μ΄λν΄λ³΄μΈμ. νμ΄μ§κ° λ‘λ©λλ μκ° λ°λ‘ Login νμ΄μ§λ‘ μ΄λλ©λλ€.