ํฐ์คํ ๋ฆฌ ๋ทฐ
๐ React ๋ก๊ทธ์ธ ์ธ์ฆ ํ๋ฆ ์ ๋ฆฌ (ProtectedRoute / PublicRoute ์ค๊ณ)
vellahw 2026. 3. 31. 11:08๐
๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด ๋ฐ๋์ ๋ง์ฃผ์น๋ ๋ฌธ์ ๊ฐ ์๋๋ฐ
๋ฐ๋ก ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ฅธ ๋ผ์ฐํ
์ฒ๋ฆฌ๋ค.
๋๋ ์ด๋ฒ์ ๋ก๊ทธ์ธ ํ๋ก์ฐ๋ฅผ ๊ตฌํํ๋ฉด์ ๋ก๊ทธ์ธ ์ธ์ฆ์ด ์ฑ๊ณต ์ํ(200 ์ฝ๋)์ธ๋ฐ๋ ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋์ด ์ ๋๋ ์ํฉ์ ๊ฒช์๊ณ ๊ทธ ๊ณผ์ ์์ ๋ก๊ทธ์ธ/๋น๋ก๊ทธ์ธ ๋ผ์ฐํ ๊ตฌ์กฐ๋ฅผ ํ ๋ฒ ์ ๋๋ก ์ ๋ฆฌํ๊ฒ ๋๋ค.
๋ฌธ์ ์ํฉ
์ฒ์์ ์ด๋ฐ ๊ตฌ์กฐ์๋ค.
/**
* fileName : useCheckAuth
* description : ๋ก๊ทธ์ธ ์ํ ํ์ธ ํ ํ์ ์ ํ ํฐ ๊ฐฑ์ ๋ฐ ํ์ด์ง ์ด๋์ ๊ฒฐ์ ํ๋ ์ปค์คํ
ํ
*/
export const useCheckAuth = () => {
const { data, isLoading, isError, refetch } = useAuthQuery(); // ๋ก๊ทธ์ธ ์ํ ํ์ธ
...
if (data) {
const code = data.code; // ์๋ต ์ฝ๋
if (code === 200) return { isLoading: false, navigateTo: "/home", showChildren: true };
...
}
return { isLoading: false, navigateTo: "/login", showChildren: false };
};
/**
* fileName : ProtectRoute
* description : ์ธ์ฆ์ด ํ์ํ ๋ผ์ฐํธ๋ฅผ ๋ณดํธํ๋ ์ปดํฌ๋ํธ. ๋ก๊ทธ์ธ ์ธ์ฆ๋ ์ฌ์ฉ์๋ง ํ์ด์ง ์ ๊ทผ ํ์ฉ
*/
export default function ProtectedRoute({ children }: { children: React.ReactNode; }) {
const { isLoading, navigateTo, showChildren } = useCheckAuth();
...
if (navigateTo) return <Navigate to={navigateTo} replace />;
if (showChildren) return children;
}
๊ฒ๋ณด๊ธฐ์๋ ๋ฌธ์ ์์ด ๋ณด์๋ค.
ํ์ง๋ง ์ค์ ๋ก๋ ๊ตฌ์กฐ์ ์ผ๋ก ์ถฉ๋์ด ๋ฐ์ํ๋ค.
๋ญ๊ฐ ๋ฌธ์ ์๋?
ํต์ฌ์ ๐ navigateTo์ showChildren์ ๋์์ ์ฐ๊ณ ์์๋ค.
ProtectedRoute์์ /home์ผ๋ก ๋ณด๋ด๋ ๋ก์ง ์์ฒด๊ฐ ๊ตฌ์กฐ์ ์ผ๋ก ์ด์ํ ์ํ์ธ๊ฑฐ๋ค.
์ฆ, ์ธ์ฆ ์ฑ๊ณต ์ ์ด๋๋ ํ๋ ค๊ณ ํ๊ณ ๋ ๋๋ง๋ ํ๋ ค๊ณ ํ๋ค.
์ปค์คํ ํ ์์ code === 200์ด๋ฉด:
- navigateTo: "/home"
- showChildren: true
๋ ๋ค true์ธ ์ํ์ด๋ค.
์ด ์ํ์์ ์คํ ์์๋:
- navigateTo ๋จผ์ ์คํ๋จ
- showChildren์ ์์ ๋ ๋๋ง ์ ๋จ
๊ฒ๋ค๊ฐ /home์์๋ ProtectedRoute๋ฅผ ์ฐ๊ณ ์์ผ๋ฉด ์๊ธฐ ์์ ์ผ๋ก ๊ณ์ redirect๋ฅผ ์๋ํ๋ค.
๊ฒฐ๊ณผ๋ ์ด๋์ด ์ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ฑฐ๋ ๋ฌดํ ๋ฃจํ๊ฐ ๋ฐ์ํ๋ค.
๐ก ํด๊ฒฐ ๋ฐฉํฅ
๋ผ์ฐํธ ๊ฐ๋๋ ์ด๋์ํค๋ ์ญํ ์ด ์๋๋ค
์ฌ์ค ์ด ๋ก์ง์ ์ค๊ณ๊ฐ ์๋ชป๋๊ฑฐ๋ค.
์ธ์ฆ์ ์ฑ๊ณตํ๋๋ฐ ์ /home์ผ๋ก ์ด๋์ํค๋?
ProtectedRoute๋ ์๋ ๋ฆฌ๋ค์ด๋ ํธ ๋ด๋น์ด ์๋๋ผ ๊ทธ ๊ฐ๋ง ๋ณด๊ณ ์ ๊ทผ ํ์ฉ์ด๋ ์ฐจ๋จ๋ง ํด์ผ ํ๋ ๊ฒ์ด๋ค.
์ญํ ๋ถ๋ฆฌ
| ์ธ์ฆ ์ํ ํ๋จ | useCheckAuth |
| ์ ๊ทผ ํ์ฉ/์ฐจ๋จ | ProtectedRoute |
| ๋ก๊ทธ์ธ ์ ์ ์ ๊ทผ ์ฐจ๋จ | PublicRoute |
| ํ์ด์ง ์ด๋ | ๋ก๊ทธ์ธ ์ฑ๊ณต ์ |
ProtectedRoute๋ UI๋ฅผ ๋ด๋นํ๊ณ
useCheckAuth๋ ์ธ์ฆ ์ํ๋ฅผ ํ๋จํ๋ค.
์ฌ๋ฐ๋ฅธ ๊ตฌ์กฐ
๋ผ์ฐํ ์ 2๊ฐ๋ก ๋๋๋ค.
์ธ์ฆ ํ์ ๋ผ์ฐํธ (Private)
- ๋ก๊ทธ์ธํด์ผ ์ ๊ทผ ๊ฐ๋ฅ
- ์: /home, /mypage
๋น์ธ์ฆ ์ ์ฉ ๋ผ์ฐํธ (Public)
- ๋ก๊ทธ์ธ ์ํ๋ฉด ์ ๊ทผํ๋ฉด ์ ๋จ
- ์: /login, /signup
1. ์ธ์ฆ ์ํ ์ปค์คํ ํ
export const useCheckAuth = () => {
const { data, isLoading, isError } = useAuthQuery();
if (isLoading) {
return { isLoading: true, isAuthenticated: false };
}
if (isError) {
return { isLoading: false, isAuthenticated: false };
}
// ์ด๋์ํค์ง ๋ง๊ณ ๊ทธ๋ฅ ํต๊ณผ
if (data?.code === 200) {
return { isLoading: false, isAuthenticated: true };
}
return { isLoading: false, isAuthenticated: false };
};
ํต์ฌ์ isAuthenticated ํ๋๋ก ๋จ์ํํ์ฌ ๋จ์ผ ์ฑ ์ + ๋จ์ ๋ก์ง์ผ๋ก ๋ฒ๊ทธ๋ฅผ ๊ฐ์ํ๋ ๊ฒ์ด๋ค.
2. ProtectedRoute (๋ก๊ทธ์ธ ํ์ ํ์ด์ง ๋ณดํธ)
export default function ProtectedRoute({ children }) {
const { isLoading, isAuthenticated } = useCheckAuth();
if (isLoading) return <Loading />;
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return children;
}
๋ก๊ทธ์ธ ์ ํ์ผ๋ฉด ์ฐจ๋จ
3. PublicRoute (๋ก๊ทธ์ธํ ์ฌ๋ ๋ง๊ธฐ)
export default function PublicRoute({ children }) {
const { isLoading, isAuthenticated } = useCheckAuth();
if (isLoading) return <Loading />;
if (isAuthenticated) {
return <Navigate to="/home" replace />;
}
return children;
}
๋ก๊ทธ์ธ ํ์ผ๋ฉด ๋ก๊ทธ์ธ ํ์ด์ง ๋ค์ด๊ฐ์ง ๋ชปํ๊ฒ ๋ง๊ธฐ
4. Router ๊ตฌ์ฑ
<Routes>
{/* ๋ก๊ทธ์ธ ์ ๋ ์ฌ๋๋ง */}
<Route
path="/login"
element={
<PublicRoute>
<Login />
</PublicRoute>
}
/>
{/* ๋ก๊ทธ์ธ ๋ ์ฌ๋๋ง */}
<Route
path="/home"
element={
<ProtectedRoute>
<Home />
</ProtectedRoute>
}
/>
</Routes>
5. ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ์ด๋ ์ฒ๋ฆฌ
const handleLogin = async () => {
const res = await loginApi();
if (res.success) {
navigate("/home");
}
};
๐ ์ฌ๊ธฐ์๋ง ์ด๋ํ๋ค
๋ด๊ฐ ํ๋ ์ค์
๋ด๊ฐ ํ๋ ์ค์๋ฅผ ์ ๋ฆฌํ์๋ฉด
โ ProtectedRoute์์ /home์ผ๋ก ๋ณด๋ด๊ธฐ
์ด๊ฑด ์ ๋ ํ๋ฉด ์ ๋๋ค.
โ navigateTo + showChildren ๊ฐ์ด ์ฐ๊ธฐ
์ด ๊ฒฝ์ฐ ์ํ ์ถฉ๋์ด ๋ฐ์ํ๋ค.
โ ์ธ์ฆ ์ฑ๊ณต ์ redirect๋ฅผ ๊ฐ๋์์ ์ฒ๋ฆฌ
์ด ๊ฒฝ์ฐ๋ ์ฑ ์ ๋ถ๋ฆฌ๊ฐ ๊นจ์ง๋ค.
๊ฒฐ๋ก
๋ผ์ฐํ ์ ๋จ์ํด์ผ ๋ฒ๊ทธ๊ฐ ์๋ค.
- ์ธ์ฆ ํ → ์ํ๋ง ๋ฐํํ๋ค
- ๋ผ์ฐํธ ๊ฐ๋ → ๋ง๊ธฐ๋ง ํ๋ค
- ํ์ด์ง ์ด๋ → ์ด๋ฒคํธ์์ ์ฒ๋ฆฌํ๋ค
์ด 3๊ฐ๋ง ์ง์ผ๋ ๋ก๊ทธ์ธ ํ๋ก์ฐ๋ ๊ฑฐ์ ๊ผฌ์ด์ง ์์ ๊ฒ์ด๋ค.
