반응형
Note1. Proetected Route
- Protected Route는 React Router에서 특정 경로 접근 전에 인증/권한을 확인하는 컴포넌트이다.
- 중요한 자원 (관리자 대시보드 등) 의 UI 노출을 방지할 수 있다.
하지만 개발자 도구로 우회가 가능하기에 완전한 보안은 불가능하고 서버단에서 API 접근에 대한 보안처리는 반드시 따로 해줘야만 한다.
이것은 CSR (Client-Side-Rendering)의 한계로 Spring MVC나 Next.js같은 SSR(Server-Side-Rendering) 방식을 사용하는 프레임워크는 Nginx 같은 프록시에서 html 자원 호출 자체를 서버단에서 제한할 수 있으나, CSR은 불가능하기 때문이다.
예시로 사용자가 .../admin 페이지로 접근을 시도하면 Protected Route가 권한을 확인하고, 권한이 있으면 페이지를 표시 권한이 없으면 설정한 페이지로 리다이렉트한다.
Protected Route에서 사용하기 위해 utils/jwt.js에 JWT 어드민 권한 체크 함수를 정의했다.

export const isAdmin = (): boolean => {
const token = localStorage.getItem('authToken');
if (!token) { return false; }
try {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64)
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join('')
);
const payload = JSON.parse(jsonPayload);
const authorities = payload.authorities || [];
return Array.isArray(authorities) && authorities.includes('ROLE_ADMIN');
} catch (error) {
return false;
}
};
Note2. 403 Forbidden Page

다음으로 권한 없이 관리자 페이지에 접근하면 리다이렉트할 403 페이지를 간단하게 정의한다.
import { useNavigate } from 'react-router-dom';
const ForbiddenPage = () => {
const navigate = useNavigate();
return (
<div className="min-h-screen bg-white flex items-center justify-center">
<div className="text-center">
<h1 className="text-6xl font-bold text-gray-900 mb-4">403</h1>
<h2 className="text-2xl font-medium text-gray-700 mb-2">접근 권한이 없습니다</h2>
<p className="text-gray-500 mb-8">이 페이지에 접근할 수 있는 권한이 없습니다.</p>
<div className="space-x-4">
<button
onClick={() => navigate(-1)}
className="px-6 py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300 transition"
>
이전 페이지
</button>
<button
onClick={() => navigate('/')}
className="px-6 py-2 bg-gray-900 text-white rounded hover:bg-gray-800 transition"
>
홈으로
</button>
</div>
</div>
</div>
);
};
export default ForbiddenPage;
Note3. ProtectedRotue

로그인하지 않은 경우에는 로그인 페이지로
로그인 했지만 권한이 없는 경우에는 방금 정의한 403 페이지로 리다이렉트 시킨다.
import { Navigate } from 'react-router-dom';
import { isAdmin } from '@/utils/jwt';
interface ProtectedRouteProps {
children: React.ReactNode;
requireAdmin?: boolean;
}
const ProtectedRoute = ({ children, requireAdmin = false }: ProtectedRouteProps) => {
if (requireAdmin) {
const token = localStorage.getItem('authToken');
// 로그인하지 않은 경우 → 로그인 페이지로 리다이렉트
if (!token) {
return <Navigate to="/login" replace />;
}
// 로그인했지만 관리자 권한이 없는 경우 → 403 페이지로 리다이렉트
if (!isAdmin()) {
return <Navigate to="/403" replace />;
}
}
return <>{children}</>;
};
export default ProtectedRoute;
마지막으로 Admin Dashboard로의 접근을 ProtectedRoute로 막아주었다.
<Route
path="/admin"
element={
<ProtectedRoute requireAdmin={true}>
<AdminDashboard />
</ProtectedRoute>
}
/>반응형
'dev > React' 카테고리의 다른 글
| React Note1. state, variable useState, useEffect (0) | 2026.02.07 |
|---|