-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #94 from TakhyunKim/docs/protected-route
Protected Route μ λν ν¬μ€ν μ λ‘λ π
- Loading branch information
Showing
5 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,334 @@ | ||
--- | ||
title: "Protected Route λ‘ μμ νκ² μ 보, κΈ°λ₯ 보νΈνκΈ°" | ||
subtitle: "React μμ Protected Route ꡬν" | ||
date: "2023-06-12" | ||
thumbnailUrl: "/images/protectedRoute/thumbnail.jpg" | ||
tag: "react,protected route" | ||
description: "React λ₯Ό μ¬μ©ν΄μ Protected Route ꡬν" | ||
postingType: "post" | ||
--- | ||
|
||
μμΌλ‘ React λ₯Ό κΈ°λ°μΌλ‘ λ€μν μλ리μ€λ₯Ό λμνλ κ²μ μ 리ν΄λ³Ό μκ°μ λλ€.<br /> | ||
Protected Route λ 첫 λ²μ§Έ μλ리μ€μ΄λ©°, ꡬνν΄μΌν μλ리μ€μ <br /> | ||
μ μ μ§μ ꡬννλ©΄μ 리λ§μΈλνκ³ μλ‘ λ°°μ λ λ΄μ©μ μ 리ν©λλ€. | ||
|
||
μ€μ ꡬνμ μλ GitHub Repo λ§ν¬λ₯Ό ν΅ν΄ νμΈν΄λ³΄μ€ μ μμ΅λλ€. | ||
|
||
- [protected route with react GitHub Repo](https://github.com/TakhyunKim/react-study/tree/main/protected-route) | ||
|
||
## ꡬν μλλ¦¬μ€ | ||
|
||
1. νμ΄μ§λ "λ©μΈ", "λ‘κ·ΈμΈ", "λ§μ΄νμ΄μ§", "λμ보λ" λ₯Ό ꡬνν©λλ€. | ||
2. λ‘κ·ΈμΈν μ μ κ° μλ κ²½μ°, "λ§μ΄νμ΄μ§", "λμ보λ" λ μ κ·Όν μ μμ΅λλ€. | ||
3. λ‘κ·ΈμΈν μ μ μΌ κ²½μ°, λ‘κ·ΈμΈ νμ΄μ§λ‘ μ κ·Ό μ λ©μΈ νμ΄μ§λ‘ μ΄λν©λλ€. | ||
|
||
## μ μ | ||
|
||
μ΄λ¦ κ·Έλλ‘ Route λ₯Ό protected νλ κ²μ μλ―Έν©λλ€.<br /> | ||
`νΉμ 쑰건` μ λ§μ‘±νμ§ μμ κ²½μ°, νΉμ νμ΄μ§λ‘ μ΄λμν€κ³ ,<br /> | ||
`νΉμ 쑰건` μ λ§μ‘±ν κ²½μ°, ν΄λΉ νμ΄μ§λ‘ μ΄λνλ λ°©μμ λλ€.<br /> | ||
|
||
λ³΄ν΅ μΈμ¦κ³Ό κ°μ΄ μ μ ν κΆνμ΄ μλ μ μ λ‘λΆν° μ 보, κΈ°λ₯μ 보νΈνκΈ° μν΄<br /> | ||
νΉμ κ²½λ‘μ μ κ·Όμ λ°©μ§ν λ `Protected Route` λ₯Ό μ¬μ©ν©λλ€. | ||
|
||
## 리λ§μΈλ νΉμ λ°°μ λ μ | ||
|
||
### μλλ¦¬μ€ μΈμ μ²λ¦¬ν λΆλΆ - replace | ||
|
||
μ΄λ² `Protected Route` λ₯Ό ꡬννλ©΄μ λ‘κ·ΈμΈμ΄ λμ΄μμ§ μμ μ μ λ login νμ΄μ§λ‘ route νλ λ‘μ§μ ꡬννμ΅λλ€.<br /> | ||
μ΄ κ³Όμ μμ `replace` μ΅μ μ μ¬μ©νμ΅λλ€. μ΄λ₯Ό μ¬μ©νμ§ μμ κ²½μ° μ΄λ€ μ΄μκ° λ°μνλμ§ μμ±νκ² μ΅λλ€. | ||
|
||
> 1. login μ νμ§ μμ μνμμ `Protected Route` λ `λμ보λ`, `λ§μ΄νμ΄μ§` λ‘ μ΄λν©λλ€. | ||
> 2. `Protected Route` λ‘ μΈν΄ login νμ΄μ§λ‘ μ΄λν©λλ€. | ||
> 3. login νμ΄μ§μμ λ€λ‘κ°κΈ°λ₯Ό ν©λλ€. | ||
μ μ λ login νμ΄μ§μ κ°νλ μν©μ΄ λ©λλ€. κ·Έ μ΄μ λ μλμ κ°μ΅λλ€. | ||
|
||
`Protected Route` μ μν΄ login νμ΄μ§λ‘ μ΄λνλ©΄ λΈλΌμ°μ History Stack μ μλμ κ°μ΅λλ€.<br /> | ||
μ²μ λ©μΈ νμ΄μ§μμ λ§μ΄νμ΄μ§λ‘ κ·Έλ¦¬κ³ λ‘κ·ΈμΈ νμ΄μ§λ‘ Stack μ΄ μμ¬μλ κ²μ λ³Ό μ μμ΅λλ€. | ||
|
||
![protected route {{ w: 1100, h: 780, parentW: 50 }}](/images/protectedRoute/protected-route.png) | ||
|
||
μ μνμμ λ€λ‘κ°κΈ°λ₯Ό νκ² λλ©΄ Stack μλ£ κ΅¬μ‘°μ λμ λ°©μμ λ°λΌ μ΅μμ λ‘κ·ΈμΈ νμ΄μ§κ°<br /> | ||
μ¬λΌμ§κ² λ©λλ€. κ·ΈλΌ λ§μ΄ νμ΄μ§λ‘ μ΄λνκ² λ©λλ€. | ||
|
||
![back history stack {{ w: 980, h: 810, parentW: 50 }}](/images/protectedRoute/back-image.png) | ||
|
||
λ¬Έμ λ μμ§ λ‘κ·ΈμΈμ νμ§ μμ<br /> | ||
λ§μ΄ νμ΄μ§λ‘ μ΄λν κ²½μ° `Protected Route` μ μν΄ λ€μ λ‘κ·ΈμΈ νμ΄μ§λ‘ μ΄λν©λλ€.<br /> | ||
|
||
![protected route {{ w: 1100, h: 780, parentW: 50 }}](/images/protectedRoute/protected-route.png) | ||
|
||
κ²°κ³Όμ μΌλ‘ λ€λ‘ κ°κΈ°λ₯Ό ν΄λ μ¬μ©μλ κ³μ λ‘κ·ΈμΈ νμ΄μ§λ₯Ό λ³΄κ² λ©λλ€.<br /> | ||
μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ `replace` option μ νμ©νμ΅λλ€. | ||
|
||
### replace? | ||
|
||
ProtectedRoute μ»΄ν¬λνΈ μ½λλ μλμ κ°μ΅λλ€. | ||
|
||
```tsx | ||
import { useRecoilValue } from "recoil"; | ||
import { Navigate, Outlet, useLocation } from "react-router-dom"; | ||
|
||
import { isLoginUserSelector } from "../recoil/user"; | ||
|
||
function ProtectedRoute() { | ||
const currentLocation = useLocation(); | ||
const isLoginUser = useRecoilValue(isLoginUserSelector); | ||
|
||
if (!isLoginUser) { | ||
return <Navigate to="/login" replace state={{ from: currentLocation }} />; | ||
} else { | ||
return <Outlet />; | ||
} | ||
} | ||
``` | ||
|
||
Navigate μ»΄ν¬λνΈμμ `replace` props μ μ¬μ©νκ³ μμ΅λλ€.<br /> | ||
`replace` μ μν μ History Stack μ νμ¬ νλͺ©μ λ체νλ μν μ ν©λλ€.<br /> | ||
|
||
- [react router history docs](https://v5.reactrouter.com/web/api/history) | ||
|
||
νμ¬ νλͺ©μ λ체νκ² λλ€λ 건 μλμ κ°μ΄ μ 리ν μ μμ κ² κ°μ΅λλ€. | ||
|
||
> 1. λ‘κ·ΈμΈμ νμ§ μμ μνμμ λ§μ΄ νμ΄μ§λ‘ μ΄λν©λλ€.<br /> | ||
> (History Stack μ λ©μΈ νμ΄μ§, λ§μ΄ νμ΄μ§ μμΌλ‘ μ€νμ΄ μμ¬μμ΅λλ€.) | ||
> 2. `Protected Route` μ μν΄ λ‘κ·ΈμΈ νμ΄μ§λ‘ μ΄λν©λλ€.<br /> | ||
> (replace μ μν΄ λ§μ΄ νμ΄μ§ μ€νμ΄ λ‘κ·ΈμΈ νμ΄μ§ μ€νμΌλ‘ λ체λ©λλ€.) | ||
μ΄λ κ² λ κ²½μ° μλμ κ°μ μ€ν ꡬ쑰λ₯Ό κ°μ§κ² λ©λλ€. | ||
|
||
![replace {{ w: 1000, h: 770, parentW: 50 }}](/images/protectedRoute/replace.png) | ||
|
||
μ΄ μνμμ λ€λ‘ κ°κΈ°λ₯Ό λλ₯΄λ©΄ λ©μΈ νμ΄μ§λ‘ μ΄λνλ―λ‘<br /> | ||
μ΄μ μ¬μ©μκ° λ€λ‘ κ°κΈ°λ₯Ό λλ¬λ κ³μ λ‘κ·ΈμΈ νμ΄μ§λ₯Ό νκΈ°νλ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€. | ||
|
||
- [kakao location replace ν¬μ€ν ](https://fe-developers.kakaoent.com/2022/221124-router-without-library/#location-replace) | ||
- [replace method MDN](https://developer.mozilla.org/en-US/docs/Web/API/Location/replace) | ||
|
||
### μλλ¦¬μ€ μΈμ μ²λ¦¬ν λΆλΆ - Navigate state | ||
|
||
λ‘κ·ΈμΈμ νμ§ μμ κ²½μ°, λμ보λ, λ§μ΄νμ΄μ§λ‘ μ΄λ μ `Protected Route` μ μν΄ login νμ΄μ§λ‘ μ΄λν©λλ€.<br /> | ||
login νμ΄μ§μμ λ‘κ·ΈμΈμ μ±κ³΅ν κ²½μ°, μ°λ¦¬λ μ΄λλ‘ μ΄λν κ²μΌλ‘ μμν κΉμ?<br /> | ||
μλ μ μνκ³ μ νλ νμ΄μ§λ‘ μ΄λν κ²μΌλ‘ μμν κ²λλ€. | ||
|
||
νμ¬ κΈ°νμμλ λͺ μλμ§ μμμ§λ§, μ¬μ©μ μ μ₯μμ λΉμ°νκ³ νΈλ¦¬ν κΈ°λ₯μ ꡬννκ³ μ ν©λλ€.<br /> | ||
μ΄ κΈ°λ₯μ μν΄ νμν μ μ λ€μκ³Ό κ°μ΅λλ€. | ||
|
||
> 1. `Protected Route` μ μν΄ login νμ΄μ§λ‘ μ΄λνκΈ° μ νμ΄μ§κ° 무μμΈμ§ μμμΌν©λλ€. | ||
> 2. λ‘κ·ΈμΈμ΄ μλ£λ ν, μ΄μ νμ΄μ§(μλ κ°κ³ μ νλ νμ΄μ§)λ‘ μ΄λν μ μμ΄μΌν©λλ€.<br /> | ||
> κ·Έλ λ€λ©΄ μ΄μ νμ΄μ§μ λν μ 보λ₯Ό λ‘κ·ΈμΈ νμ΄μ§μμλ μκ³ μμ΄μΌν©λλ€. | ||
μ°λ¦¬λ μ΄μ `replace` μ΅μ μ μ¬μ©νλ©΄μ μλ λ€μ΄κ°κ³ μ νλ νμ΄μ§λ₯Ό History Stack μμ<br /> | ||
μ°Ύμ μ μμ΅λλ€. κ·Έλ κΈ°μ λ€λ₯Έ λ°©λ²μ λͺ¨μν΄μΌν©λλ€. | ||
|
||
κ·Έλ λ€λ©΄ replace κ° λκΈ° μ , νμ¬ νμ΄μ§μ λν location μ 보λ₯Ό κ°μ Έμ€κ³ <br /> | ||
login νμ΄μ§λ‘ κ·Έ μ 보λ₯Ό μ λ¬νλ©΄ λ κ² κ°μ΅λλ€. | ||
|
||
μ΄λ₯Ό μν΄ react-router-dom λΌμ΄λΈλ¬λ¦¬μ `useLocation` hook μ νμ©ν΄λ³΄κ² μ΅λλ€.<br /> | ||
useLocation hook μ νμ¬ location κ°μ²΄λ₯Ό λ°νν©λλ€. <br /> | ||
μ΄λ₯Ό ν΅ν΄ νμ¬ location μ 보λ₯Ό κ°μ§κ³ μμ΅λλ€. | ||
|
||
- [react router useLocation hook docs](https://reactrouter.com/en/main/hooks/use-location) | ||
|
||
κ·Έλ¦¬κ³ location μ 보λ₯Ό login νμ΄μ§λ‘ μ λ¬νκΈ° μν΄ Navigate μ»΄ν¬λνΈμ state prop μ νμ©ν©λλ€.<br /> | ||
state prop μ ν΅ν΄ μ΄λ€ μνλ₯Ό μ΄λν νμ΄μ§λ‘ μ λ¬ν μ μμ΅λλ€.<br /> | ||
`useLocation`, `Navigate μ»΄ν¬λνΈμ state prop` λ κ°μ§λ₯Ό νμ©νμ¬ μλμ κ°μ΄ ꡬννμ΅λλ€. | ||
|
||
```tsx | ||
import { useRecoilValue } from "recoil"; | ||
import { Navigate, Outlet, useLocation } from "react-router-dom"; | ||
|
||
import { isLoginUserSelector } from "../recoil/user"; | ||
|
||
function ProtectedRoute() { | ||
const currentLocation = useLocation(); // νμ¬ location κ°μ²΄ μ 보λ₯Ό κ°μ Έμ¨λ€. | ||
const isLoginUser = useRecoilValue(isLoginUserSelector); | ||
|
||
if (!isLoginUser) { | ||
// Navigate μ»΄ν¬λνΈμ state prop μ νμ¬ location κ°μ²΄λ₯Ό μ λ¬νλ€. | ||
return <Navigate to="/login" replace state={{ from: currentLocation }} />; | ||
} else { | ||
return <Outlet />; | ||
} | ||
} | ||
``` | ||
|
||
κ·Έλ¦¬κ³ login νμ΄μ§μμλ location κ°μ²΄λ₯Ό μλμ κ°μ΄ νμ©ν©λλ€. | ||
|
||
```tsx | ||
import { useNavigate, useLocation } from "react-router-dom"; | ||
|
||
import { useLogin } from "./hooks/login"; | ||
|
||
import type { FormEvent } from "react"; | ||
|
||
function Login() { | ||
// ... λ€λ₯Έ λΉμ¦λμ€ μ½λ | ||
const loginMutation = useLogin(); | ||
const location = useLocation(); | ||
const navigation = useNavigate(); | ||
|
||
// useLocation hooks μ ν΅ν΄ μ λ¬ν location μ pathname μ κ°μ Έμ¨λ€. | ||
// λ§μ½ μμ κ²½μ° `/` λ©μΈ νμ΄μ§λ‘ μ΄λνλ€. | ||
const from = location.state?.from?.pathname ?? "/"; | ||
|
||
const handleLoginSubmit = (event: FormEvent<HTMLFormElement>) => { | ||
event.preventDefault(); | ||
|
||
loginMutation.mutate( | ||
{ id, password }, | ||
{ | ||
onSuccess: (response: { accessToken: string }) => { | ||
// API νΈμΆμ΄ μ±κ³΅νμ κ²½μ°, useNavigate hook μ μ¬μ©νμ¬ μ΄λ | ||
navigation(from); | ||
}, | ||
onError: () => { | ||
alert("λ‘κ·ΈμΈ μ€ν¨!"); | ||
}, | ||
} | ||
); | ||
}; | ||
|
||
return ( | ||
<FormWrapper onSubmit={handleLoginSubmit}> | ||
{/** λ€λ₯Έ μ»΄ν¬λνΈ... */} | ||
</FormWrapper> | ||
); | ||
} | ||
``` | ||
|
||
λ‘κ·ΈμΈμ΄ μ±κ³΅νμ κ²½μ°, μ λ¬ν location κ°μ²΄ μ 보λ₯Ό νμ©νμ¬ νμ΄μ§λ₯Ό μ΄λνλ λ°©μμ λλ€.<br /> | ||
μ΄λ₯Ό ν΅ν΄ λ‘κ·ΈμΈ μ±κ³΅ μ, μλ κ°κ³ μ νλ νμ΄μ§λ‘ μ΄λνλ κΈ°λ₯ λν ꡬνν μ μμ΅λλ€. | ||
|
||
### μλ‘κ² μ¬μ©ν΄λ³΄κ³ λ°°μ΄ κ² - Outlet | ||
|
||
`Outlet` μ react router dom μμ μ 곡νλ μ»΄ν¬λνΈλ‘<br /> | ||
μ€μ²© λΌμ°ν , μ€μ²© λ μ΄μμ (React μ children κ³Ό κ°μ) κΈ°λ₯μΌλ‘ νμ©ν μ μμ΅λλ€. | ||
|
||
- [react router Outlet docs](https://reactrouter.com/en/main/components/outlet) | ||
|
||
곡μ λ¬Έμμ μμ λ₯Ό 보면 μ¬μ©λ²μ μ½κ² μ΄ν΄ν μ μμ΅λλ€. | ||
|
||
```tsx | ||
function Dashboard() { | ||
return ( | ||
<div> | ||
<h1>Dashboard</h1> | ||
|
||
{/* This element will render either <DashboardMessages> when the URL is | ||
"/messages", <DashboardTasks> at "/tasks", or null if it is "/" | ||
*/} | ||
<Outlet /> | ||
</div> | ||
); | ||
} | ||
|
||
function App() { | ||
return ( | ||
<Routes> | ||
<Route path="/" element={<Dashboard />}> | ||
<Route path="messages" element={<DashboardMessages />} /> | ||
<Route path="tasks" element={<DashboardTasks />} /> | ||
</Route> | ||
</Routes> | ||
); | ||
} | ||
``` | ||
|
||
`/messages`, `/tasks` λ‘ μ΄λν κ²½μ°, νμ `<h1>Dashboard</h1>` μ ν¨κ» λμμ§λ κ²μ λ³Ό μ μμ΅λλ€.<br /> | ||
`/messages`, `/tasks` router μμμλ `/` κ° μκ³ , μ΄ λ Dashboard μ»΄ν¬λνΈλ₯Ό μΆλ ₯ν©λλ€. | ||
|
||
κ·Έλ¦¬κ³ Dashboard μμλ λ΄λΆμμλ `Outlet` μ μ¬μ©νμ¬ `/messages`, `/tasks` λ‘ μ΄λ μ<br /> | ||
μ€νλ μ»΄ν¬λνΈλ₯Ό `Outlet` μ μμΉμμ μ€νν©λλ€.<br /> | ||
μ΄λ¬ν νΉμ§μΌλ‘ μΈν΄ React μ children κ³Ό λΉμ·ν λμμ΄λΌκ³ λ§μλλ Έμ΅λλ€. | ||
|
||
κ·Έλ λ€λ©΄ μ΄λ¬ν μ€μ²© λΌμ°ν , λ μ΄μμμ μ 곡νλ `Outlet` μ `Protected Route` λ₯Ό ꡬνν λ μ΄λ»κ²<br /> | ||
μ¬μ©νμκΉμ? μ΄λ μλ μ½λμμ νμΈν μ μμ΅λλ€. | ||
|
||
```tsx | ||
// routes/ProtectedRoute.tsx | ||
import { useRecoilValue } from "recoil"; | ||
import { Navigate, Outlet, useLocation } from "react-router-dom"; | ||
|
||
import { isLoginUserSelector } from "../recoil/user"; | ||
|
||
function ProtectedRoute() { | ||
const currentLocation = useLocation(); | ||
const isLoginUser = useRecoilValue(isLoginUserSelector); | ||
|
||
if (!isLoginUser) { | ||
return <Navigate to="/login" replace state={{ from: currentLocation }} />; | ||
} else { | ||
return <Outlet />; | ||
} | ||
} | ||
// routes/index.tsx | ||
import { BrowserRouter, Routes, Route } from "react-router-dom"; | ||
|
||
import Main from "../pages/Main"; | ||
import Login from "../pages/Login"; | ||
import MyPage from "../pages/MyPage"; | ||
import Dashboard from "../pages/Dashboard"; | ||
import ProtectedRoute from "./ProtectedRoute"; | ||
|
||
function Routers() { | ||
return ( | ||
<BrowserRouter> | ||
<Routes> | ||
<Route path="/" element={<Main />} /> | ||
<Route path="/login" element={<Login />} /> | ||
<Route element={<ProtectedRoute />}> | ||
<Route path="/my-page" element={<MyPage />} /> | ||
<Route path="/dashboard" element={<Dashboard />} /> | ||
</Route> | ||
</Routes> | ||
</BrowserRouter> | ||
); | ||
} | ||
``` | ||
|
||
`Outlet` μ `ProtectedRoute` μ»΄ν¬λνΈμμ μ¬μ©νμ΅λλ€.<br /> | ||
λ‘κ·ΈμΈμ΄ λμμ λ, `<Outlet />` μ»΄ν¬λνΈλ₯Ό return ν©λλ€. | ||
|
||
κ·Έλ¦¬κ³ Routes μ»΄ν¬λνΈμμλ μ΄λ¬ν `ProtectedRoute` λ₯Ό `/my-page`, `/dashboard` μμμ<br /> | ||
Route λ‘ κ°μΌ ννλ‘ κ΅¬νλμ΄ μμ΅λλ€. | ||
|
||
μ°λ¦¬κ° ꡬνν `ProtectedRoute` λ λ‘κ·ΈμΈμ΄ λμ§ μμμ λλ login νμ΄μ§λ‘,<br /> | ||
λ‘κ·ΈμΈμ΄ λμμ λ μλ μ΄λνκ³ μ νλ νμ΄μ§λ‘ μ΄λνλ κ²μ΄ λͺ©μ μ λλ€.<br /> | ||
μ΄λ₯Ό `Outlet` μ ν΅ν΄ ꡬννμ΅λλ€.<br /> | ||
λ‘κ·ΈμΈμ΄ λμμ λ `Outlet` μ μ¬μ©νμ¬ κ·Έ νμμ μμΉν Route μ»΄ν¬λνΈλ₯Ό μΆλ ₯νλ λ°©μμΌλ‘μ. | ||
|
||
μ΄λ κ² κ΅¬ννκ² λ κ²½μ° μλμ κ°μ μ₯μ μ΄ μμ΅λλ€. | ||
|
||
> 1. λ€λ₯Έ Route μμ ProtectedRoute μ κΈ°λ₯μ΄ νμνλ€λ©΄ λμΌνκ² κ°μΈμ£Όλ©΄ λλ€. | ||
> 2. μ μ©μ΄ λ§€μ° μ½κ³ , κ° μ»΄ν¬λνΈ(ProtectedRoute, μλ μΆλ ₯νκ³ μ νλ μ½€ν¬λνΈ)λ κ°μ ν μΌλ§ ν μ μλ€. | ||
> (κ΄μ¬μ¬μ λΆλ¦¬) | ||
## νκΈ° | ||
|
||
Navigate μ replace μ κ²½μ°, μ΄λ€ κ²½μ°μ μ¬μ©νλμ§λ μκ³ μμμΌλ μ΄λ»κ² λμνλμ§<br /> | ||
λͺ νν μκ³ μμ§ μμμ΅λλ€. μ΄λ² κΈ°νλ₯Ό ν΅ν΄ 'λ΄κ° λͺ¨νΈνκ² μκ³ μμꡬλ' λΌλ κ²μ κΊ λ«κΈ°λ νꡬμ.<br /> | ||
μ무λλ νμ μμ μ μ§λ³΄μλ₯Ό νκ³ μκ³ , κ·Έλ κΈ°μ Protected Route μ κ°μ΄ μ΄κΈ°μ μ μ νλ λ°©μμ<br /> | ||
μ§μ μ½λλ‘ μμ¨λ³Έμ§ κ½€ λν°λΌ 리λ§μΈλλ₯Ό νμ€ν ν΄λ΄€λ€λ μ μμ μ»μ΄κ°λ μ μ΄ μλ€κ³ μκ°ν©λλ€. | ||
|
||
λν React Router Dom `Outlet` μ λ£κΈ°λ§ νμμ§ μ¬ν νμ©ν΄λ³Έ μ μ΄ μμκΈ°μ λμμ΄ λ§μ΄ λμμ΅λλ€.<br /> | ||
μ€μ²© λΌμ°ν , λ μ΄μμμ΄λΌλ κ²μ΄ μ΄λ»κ² λμμ μ€ μ μλμ§λ₯Ό μ μ μμκ³ , μ§μ μ¬μ©νλ©΄μ<br /> | ||
κ·Έ μ리λ₯Ό νμ νλ€λ μ μμ μ’μ κ²½νμ΄λΌκ³ μκ°ν©λλ€. | ||
_(νμ€ν μ§μ μ¬μ©ν΄λ΄μΌ μκ² λ€λ μ λν λ€μκΈ λλΌκ² λμμ΅λλ€.)_ | ||
|
||
κΈ°μ μ μΈ λΆλΆμμ μ»μ΄κ°λ λΆλΆλ λ§μκ³ , κΈ°μ‘΄ μλ리μ€μμ κ°λ°μκ° κ΅¬ννλ©΄μ λ μκ°ν΄λ΄μΌν μ μ<br /> | ||
κ³ λ―Όνλ λΆλΆλ λμμ΄ λ§μ΄ λμμ΅λλ€. κΈ°νμλ₯Ό λΆμνκ³ , κ°λ°νλ©΄μ λͺ©μ리λ₯Ό λ΄λ κ²μ΄ μ€μνκΈ°μ<br /> | ||
μμ£Ό μ‘°κ·Έλ§ν μ€νμμλΆν° μκ°νλ μ°μ΅μ ν΄λ΄€λ€λ μ μμ μ’μ κ²½νμ΄λΌκ³ μκ°ν©λλ€. | ||
|
||
μλ리μ€λλ‘ κ΅¬ννκ³ λμ΄ μλ, μ§μ ν μ€νΈν΄λ³΄λ©΄μ 'μ΄κ±΄ μ’ λΆνΈνλ°?', 'λ€λ₯Έ κ³³μ μ΄λ»κ² λμ΄μμ§?'<br /> | ||
μ κ°μ μ°κ²°λ μκ°, μ루μ μ°ΎκΈ° λ± μ΄λ₯Ό μ§μμ μΌλ‘ 체λννλ κ²μ λͺ©νλ‘ μ°μ΅ν΄λ³Ό μκ°μ λλ€. | ||
|
||
## λ νΌλ°μ€ | ||
|
||
- [react router history docs](https://v5.reactrouter.com/web/api/history) | ||
- [kakao location replace ν¬μ€ν ](https://fe-developers.kakaoent.com/2022/221124-router-without-library/#location-replace) | ||
- [replace method MDN](https://developer.mozilla.org/en-US/docs/Web/API/Location/replace) | ||
- [react router useLocation hook docs](https://reactrouter.com/en/main/hooks/use-location) | ||
- [react router Outlet docs](https://reactrouter.com/en/main/components/outlet) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2f7c34d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
takhyun-dev β ./
takhyun-dev-git-main-takhyunkim.vercel.app
takhyun-dev-takhyunkim.vercel.app
takhyun.dev