권한과 운영
권한과 메뉴
에너지 플랫폼은 한 회사 내부 시스템이 아닙니다. 수요처 고객, 설비 공급사, 운영사가 같은 플랫폼에 들어오고, 회사마다 쓰는 서비스도 다릅니다. 그래서 "누가 어떤 회사의 어떤 메뉴를 어디까지 볼 수 있는가"를 정교하게 나눠야 합니다.
1. 구성 요소
member (사용자)
└─ member_role (서비스 유형 × 회사 유형 × 역할)
└─ role
├─ role_permission → permission (API 권한)
└─ role_menu → menu (화면 접근, access_level)
company
├─ company_service (사용 중인 서비스)
├─ company_role_menu_include / exclude (회사별 메뉴 예외)
└─ company_relation (수요처 ↔ 공급사)
| 요소 | 역할 |
|---|---|
| member | 로그인 주체, 소속 회사/부서 |
| role | 역할 (관리자, 담당자, 조회자 등) |
| permission | API 단위 권한 코드 |
| menu | 화면 트리 (parent_id, menu_path) |
| service_type | 서비스 구분 (공통코드 SERVICE_TYPE) |
| company_type | 회사 유형 (수요처, 공급사, 운영사) |
2. 서비스 유형
같은 플랫폼 안에 여러 서비스가 있으면 역할도 서비스별로 달라야 합니다.
- 한 사용자가 서비스 A에서는 관리자, 서비스 B에서는 조회자일 수 있습니다
member_role,role_menu에service_type_id를 넣어 서비스별로 분리합니다company_service로 회사가 구독 중인 서비스만 메뉴에 노출합니다
3. 메뉴 접근
role_menu
| 컬럼 | 설명 |
|---|---|
| role_id, service_type_id, menu_id | 역할-서비스-메뉴 |
| access_level | 조회 / 편집 / 관리 |
| is_visible | 메뉴 노출 여부 |
- 메뉴는 트리 구조(
parent_id)라서 상위 메뉴 권한이 없으면 하위도 숨깁니다 access_level로 같은 화면에서 버튼(등록, 수정, 삭제) 노출을 제어합니다- 프론트는 로그인 시 메뉴 트리와 접근 레벨을 받아 라우팅과 사이드바를 구성합니다
4. 회사별 예외
역할은 공통인데 특정 회사만 메뉴를 더 주거나 빼야 하는 경우가 생깁니다.
| 테이블 | 용도 |
|---|---|
| company_role_menu_include | 이 회사의 이 역할에는 메뉴 추가 (사유 기록) |
| company_role_menu_exclude | 이 회사의 이 역할에서는 메뉴 제외 |
최종 메뉴 = role_menu ∪ include - exclude (회사 서비스 범위 내)
역할을 회사마다 복제하면 역할 수가 폭발합니다. 예외 테이블로 처리하는 편이 관리하기 쉽습니다.
5. 데이터 범위
메뉴 권한과 데이터 범위는 별개입니다. 같은 "사용량 조회" 화면이라도 볼 수 있는 데이터가 다릅니다.
| 회사 유형 | 데이터 범위 |
|---|---|
| 운영사 | 전체 회사 |
| 공급사 | 계약 관계(company_relation)가 있는 수요처 |
| 수요처 | 자기 회사 (필요 시 사업장 단위) |
company_type_scope_policy에 서비스 × 회사 유형별 조회 범위(SCOPE_TYPE)를 둡니다- API는 모든 조회에
company_id범위 필터를 강제합니다. 프론트에서 숨기는 것만으로는 보안이 아닙니다 - 계약 기간이 끝난 공급사는 해당 수요처 데이터 접근이 자동으로 끊겨야 합니다
6. 인증
- JWT 액세스 토큰 + 리프레시 토큰 구조
- 리프레시 토큰은 해시로 저장(
member_refresh_token.token_hash)하고 만료 시각을 둡니다 - 로그아웃, 비밀번호 변경 시 리프레시 토큰 폐기
- 보고서 서비스처럼 별도 서버도 같은 토큰을 검증해야 합니다. 내부망이라고 인증을 빼면 보고서 파일 URL이 그대로 노출됩니다
7. 권한 체크 위치
| 위치 | 체크 내용 |
|---|---|
| 프론트 라우터 | 메뉴 접근 (UX) |
| 프론트 버튼 | access_level (UX) |
| API 미들웨어 | 토큰, permission 코드 |
| API 서비스 | 데이터 범위 (company_id, relation) |
| DB | 최후 방어 (soft delete scope 등) |
UX용 체크와 보안용 체크를 구분해야 합니다. 프론트 체크는 편의, API 체크가 진짜 권한입니다.
8. 운영 팁
- 권한 코드는
리소스:행위규칙으로 (meter:read, meter:write) - 역할은 적게, 예외는 테이블로
- 메뉴 추가 시 role_menu 기본 매핑을 마이그레이션에 포함
- 권한 변경 이력(누가, 언제, 무엇을)을 남김
- 운영사 계정은 접근 로그를 별도로 남김 (고객 데이터 열람 감사)