RBAC Policies (역할 기반 접근 제어)
ProDi는 다차원 조직 체계와 대규모 보안 통제를 보장하기 위해 단위 정책 기반 역할 권한 제어 (Policy-Based RBAC) 아키텍처를 채택하고 있습니다.
단순히 특정 역할(ADMIN, USER 등)에 따라 하드코딩된 페이지 분기를 타는 기존 방식과 달리, 각 사용자의 역할에 귀속된 세부 정책(Policy) 조합을 통해 기능적 접근 영역과 좌측 내비게이션 메뉴를 동적으로 제어합니다.
1. 데이터베이스 구조 (ERD)
보안 정책 모델은 사용자(USER), 권한 그룹(USER_ROLE), 미세 정책(POLICY), 사이드바 메뉴(MENU) 테이블로 이루어져 있습니다.
각 요소별 핵심 역할
- USER (사용자): 시스템 사용자로,
ROLE외래키를 통해 단 1개의 권한 그룹(예:ADMIN,MANAGER,USER)에 매핑됩니다. - USER_ROLE (권한 그룹): 정책들을 묶어 관리하는 최상위 역할명입니다.
- POLICY (정책): 시스템 내부 액션의 최소 단위입니다. 예:
inquiry:read(조회),inquiry:delete(삭제),form:write(작성). - ROLE_POLICY (정책 맵): 권한 그룹에 포함될 세부 정책 리스트를 연결하는 매핑 테이블입니다.
- MENU (메뉴): 사이드바 및 페이지 메뉴 구조를 정의하며,
REQUIRED_POLICY컬럼을 가지고 있어 해당 메뉴 노출 요건을 규정합니다.
2. 권한 제어 라이프사이클 (Workflow)
사용자가 로그인한 후, 프론트엔드 버튼 노출부터 백엔드 API 방어막까지의 4단계 검증 프로세스입니다.
3. 개발자 구현 가이드
① 백엔드 API 데코레이터 적용
FastAPI 라우터 진입점에서 특정 정책을 충족하는지 강제 검사하기 위해 @require_policy 의존성을 적용합니다.
from fastapi import APIRouter, Depends
from app.auth.dependencies import require_policy
router = APIRouter(prefix="/inquiries")
@router.delete("/{inquiry_id}", dependencies=[Depends(require_policy("inquiry:delete"))])
async def delete_inquiry(inquiry_id: int):
# 삭제 로직 실행
return {"status": "success"}② 프론트엔드 엘리먼트 가시성 제어
Svelte 5 UI 단에서 특정 기능을 노출시키거나 잠그려면 hasPolicy 헬퍼 함수를 적용합니다.
<script lang="ts">
import { authStore } from '$lib/stores/auth';
import { hasPolicy } from '$lib/utils/policy';
</script>
{#if hasPolicy($authStore.policies, 'inquiry:delete')}
<button on:click={handleDelete} class="btn-danger">
리서치 삭제
</button>
{/if}