콘텐츠로 이동

Ch 5. 메뉴·권한·메시지 등록

이 챕터를 마치면

  • hera-v4에서 새 화면이 네비게이션에 표시되려면 무엇을 등록해야 하는지 설명할 수 있습니다.
  • SYS0103(메뉴 관리), SYS0102(메시지), SYS0201(권한 템플릿), SYS0202(권한 등록), SYS0204(역할 등록)의 역할을 구분할 수 있습니다.
  • Ch 4에서 만든 PT0101 화면을 메뉴에 띄우고 권한을 적용할 수 있습니다.

1. 등록이 필요한 이유

Ch 4에서 코드를 완성했다면 https://localhost:8000/pt/0101에 직접 접근하면 화면은 뜹니다. 그러나 다음 두 가지는 아직 동작하지 않습니다.

문제 원인
좌측 네비게이션에 메뉴가 없습니다 sys_menu 테이블에 PT0101이 등록되지 않았습니다
조회 버튼 클릭 시 403 응답 @PreAuthorize("hasRole('ROLE_PT0101_READ')") 권한이 어떤 사용자에게도 부여되지 않았습니다

이 챕터에서는 시스템 관리 화면으로 이 두 문제를 해결합니다.


2. 등록 순서 개요

뒤 단계가 앞 단계를 참조하므로 6단계 순서를 지켜야 합니다.

[1] SYS0103  메뉴 등록       → sys_menu 테이블에 PT, PT01, PT0101 행 추가
[2] SYS0102  메시지 등록     → sys_message 테이블에 메뉴명/빵조각 메시지 추가
[3] SYS0201  권한 템플릿     → sys_rbac_auth_tmpl에 PT0101 권한 코드 정의
[4] SYS0202  권한 등록       → sys_rbac_auth_name + auth_entry에 권한 그룹 생성
[5] SYS0204  역할 등록       → sys_rbac_role_entry에 역할 ↔ 권한 그룹 연결
[6] SYS0301  사용자에 역할 배정  → 현재 계정에 역할 부여

화면들의 위치

모든 관리 화면은 시스템 어드민 계정으로 로그인해야 접근 가능합니다. 좌측 네비 → 시스템 관리 > 시스템 관리 또는 보안 관리 그룹에서 찾습니다.


3. [1] SYS0103 — 메뉴 등록

화면 경로: /sys/0103 (메뉴 관리)

메뉴는 3단계 계층 구조입니다.

레벨 타입 ID 예시 설명
0 MENU PT 최상위 네비 그룹
1 FOLDER PT01 하위 폴더 (좌측 메뉴 분류)
2 URL PT0101 실제 화면 링크

3.1 PT 최상위 메뉴 추가

화면 왼쪽 트리에서 루트(최상위)를 선택하고 메뉴 추가 버튼을 클릭합니다.

필드 입력값
메뉴 ID PT
타입 MENU
카테고리 PT
레벨 0
정렬 순서 (사내 최하위 번호 + 1)

3.2 PT01 폴더 추가

트리에서 PT를 선택하고 하위 메뉴 추가 버튼을 클릭합니다.

필드 입력값
메뉴 ID PT01
타입 FOLDER
카테고리 PT
레벨 1
정렬 순서 1

3.3 PT0101 화면 메뉴 추가

트리에서 PT01을 선택하고 하위 메뉴 추가 버튼을 클릭합니다.

필드 입력값
메뉴 ID PT0101
타입 URL
URL /pt/0101
카테고리 PT
레벨 2
정렬 순서 1
webMenu Y (웹 메뉴 표시)

저장하면 sys_menu 테이블에 다음 3개 행이 생성됩니다.

-- 등록 결과 확인
SELECT id, parent_id, type, url, level FROM sys_menu WHERE id LIKE 'PT%' ORDER BY level;
-- 기대 출력:
-- PT    | ''   | MENU   | null      | 0
-- PT01  | PT   | FOLDER | null      | 1
-- PT0101| PT01 | URL    | /pt/0101  | 2

4. [2] SYS0102 — 메시지 등록

화면 경로: /sys/0102 (메시지)

hera-v4의 화면 제목, 메뉴명, 빵조각(breadcrumb)은 모두 DB 메시지 테이블(sys_message)에서 읽어옵니다. 코드에 하드코딩하지 않으므로, 메뉴를 브라우저에 올바른 이름으로 띄우려면 메시지 코드부터 등록합니다.

4.1 등록할 메시지 목록

메시지 코드 메시지 타입 메시지 내용 (ko)
MENU.PT MENU PT 관리
MENU.PT01 MENU PT 기본관리
MENU.PT0101 MENU 가상 코드 관리
PT0101.BREADCRUMB BREADCRUMB PT 관리 / 가상 코드 관리
PT0101.HTML_TITLE HTML_TITLE HERA [가상 코드 관리]

4.2 등록 방법

화면에서 신규 등록 버튼을 클릭하고 아래 필드를 입력한 뒤 저장합니다.

필드 설명
메시지 코드 위 표의 메시지 코드
메시지 타입 위 표의 타입
카테고리 APP (메뉴/빵조각은 APP 카테고리)
그룹 코드 MENU (MENU 타입) 또는 PT0101 (화면 메시지)
locale ko
메시지 내용 위 표의 한국어 내용
사용여부 Y

MENU 타입 메시지 우선 등록

MENU.PT, MENU.PT01, MENU.PT0101 3개를 먼저 등록하면 SYS0103 화면 트리에서 방금 추가한 PT 메뉴 항목에 이름이 표시됩니다.

메시지 코드 네이밍 패턴

패턴 용도 예시
MENU.{ID} 네비게이션 메뉴 표시명 MENU.PT0101 = "가상 코드 관리"
{SCREEN}.BREADCRUMB 화면 상단 경로 표시 PT0101.BREADCRUMB = "PT 관리 / 가상 코드 관리"
{SCREEN}.HTML_TITLE 브라우저 탭 제목 PT0101.HTML_TITLE = "HERA [가상 코드 관리]"
{SCREEN}.LABEL.* 화면 내 라벨 PT0101.LABEL.CODE = "코드"

5. [3] SYS0201 — 권한 템플릿 등록

화면 경로: /sys/0201 (권한 템플릿)

권한 템플릿(sys_rbac_auth_tmpl)은 "이 메뉴에서 어떤 권한들이 존재하는지"를 정의합니다. 나중에 SYS0202에서 권한을 부여할 때 이 템플릿이 체크박스 UI의 기반이 됩니다.

5.1 PT 카테고리 추가

트리에서 최상위를 선택하고 카테고리 추가:

필드 입력값
카테고리 PT
상위 ID (비움 — 최상위)

5.2 PT01 폴더 추가

PT 항목을 선택하고 폴더 추가:

필드 입력값
ID PT01
상위 ID PT (자동 입력)

5.3 PT0101 메뉴 항목 추가

PT01 항목을 선택하고 메뉴 추가:

필드 입력값
ID PT0101
상위 ID PT01
정렬 순서 0
권한1 코드 READ
권한2 코드 CREATE
권한3 코드 UPDATE
권한4 코드 DELETE

저장하면 sys_rbac_auth_tmpl 에 아래 행이 생성됩니다.

SELECT category, id, parent_id, perm1_code, perm2_code, perm3_code, perm4_code
FROM sys_rbac_auth_tmpl WHERE category = 'PT';
-- PT | PT0101 | PT01 | READ | CREATE | UPDATE | DELETE

권한 코드와 Spring Security ROLE의 관계

템플릿의 perm1_code = 'READ' 는 Spring Security의 ROLE_PT0101_READ로 변환됩니다. 변환 규칙: ROLE_{메뉴ID}_{PERM_CODE}ROLE_PT0101_READ Ch 4에서 @PreAuthorize("hasRole('ROLE_PT0101_READ')") 로 작성한 이유가 이 패턴 때문입니다.


6. [4] SYS0202 — 권한 등록

화면 경로: /sys/0202 (권한 등록)

권한 등록은 "어느 권한 그룹에 PT0101의 어떤 권한을 부여할 것인가"를 결정합니다. sys_rbac_auth_name에 그룹을 만들고, sys_rbac_auth_entry에 메뉴별 체크 항목을 저장합니다.

6.1 신규 권한 그룹 생성

신규 등록 버튼 클릭 후 이름 입력:

필드 입력값
권한 이름 PT 전체 권한
별칭 (영문) PT_FULL_AUTH

저장하면 UUID가 자동 생성되어 sys_rbac_auth_name.id가 됩니다.

6.2 PT0101 권한 체크

생성된 권한 그룹을 선택하면 우측에 SYS0201에서 등록한 권한 템플릿 트리가 나타납니다.

PT > PT01 > PT0101 항목에서 부여할 권한을 체크합니다.

권한 코드 체크 여부 설명
READ 목록 조회
CREATE 신규 등록
UPDATE 수정
DELETE 삭제

저장하면 sys_rbac_auth_entry 테이블에 다음 행이 생성됩니다.

SELECT auth_id, category, menu_id, perm1, perm2, perm3, perm4
FROM sys_rbac_auth_entry WHERE category = 'PT' AND menu_id = 'PT0101';
-- {UUID} | PT | PT0101 | PT01 | true | true | true | true

기존 권한 그룹에 추가하는 경우

신규 개발자를 위한 권한 그룹이 이미 있다면 새로 만들 필요 없이 기존 그룹을 선택해서 PT0101 권한만 추가 체크하면 됩니다.


7. [5] SYS0204 — 역할 등록 (권한 그룹 연결)

화면 경로: /sys/0204 (역할 등록)

역할(sys_rbac_role_name)은 여러 권한 그룹(sys_rbac_auth_name)을 묶는 단위입니다. 사용자에게는 역할 단위로 부여합니다.

7.1 기존 역할에 권한 그룹 추가 (권장)

이미 개발자용 역할이 존재한다면 해당 역할을 열어서 PT 전체 권한 그룹을 추가합니다.

목록에서 역할 선택 → 우측 권한 그룹 패널 → PT 전체 권한 추가 → 저장

-- 결과 확인
SELECT rn.name, an.name AS auth_name
FROM sys_rbac_role_name rn
JOIN sys_rbac_role_entry re ON re.id = rn.id
JOIN sys_rbac_auth_name an ON an.id = re.auth_id
WHERE rn.name = '개발자 역할';
-- 개발자 역할 | PT 전체 권한

7.2 신규 역할 생성 (별도 역할이 필요한 경우)

신규 등록 → 역할명 입력 → 권한 그룹 추가 → 저장

필드 입력값
역할 이름 PT 개발자 역할
별칭 ROLE_PT_DEVELOPER

생성 후 PT 전체 권한 그룹을 연결합니다.


8. [6] SYS0301 — 사용자에 역할 배정

화면 경로: /sys/0301 (사용자 관리)

역할을 현재 로그인 계정에 부여합니다.

  1. 사용자 목록에서 본인 계정 선택
  2. 우측 역할 탭 열기
  3. PT 개발자 역할 (또는 추가한 역할) 선택 → 배정
  4. 저장

로그아웃 후 재로그인

역할 배정 후 반드시 로그아웃 → 재로그인해야 새 권한이 세션에 반영됩니다. hera-v4는 로그인 시점에 권한을 세션에 로드하기 때문입니다.


9. 화면 접속 확인

재로그인 후 다음 순서로 확인합니다.

확인 항목 기대 결과
좌측 네비 → PT 관리 PT 메뉴 그룹 표시
PT 관리 > PT 기본관리 > 가상 코드 관리 클릭 /pt/0101 화면 이동
화면 상단 제목 HERA [가상 코드 관리] 표시
빵조각 PT 관리 / 가상 코드 관리 표시
조회 버튼 클릭 200 응답, 그리드 데이터 표시

403이 계속 발생하는 경우

세션 재로드 후에도 403이 발생하면 다음을 확인합니다. 1. SYS0202에서 perm 체크가 저장됐는지 DB 확인 (sys_rbac_auth_entry.perm1 = true) 2. SYS0204에서 역할 ↔ 권한 그룹이 연결됐는지 확인 (sys_rbac_role_entry) 3. SYS0301에서 사용자 ↔ 역할이 연결됐는지 확인


10. DB로 보는 전체 연결 구조

6단계 등록이 만들어내는 DB 레코드와 연결 관계입니다.

erDiagram
    sys_menu {
        varchar id PK
        varchar parent_id
        varchar type
        varchar url
    }
    sys_message {
        varchar message_code PK
        varchar message_name
        varchar message_type
        varchar locale
    }
    sys_rbac_auth_tmpl {
        varchar category PK
        varchar id PK
        varchar parent_id PK
        varchar perm1_code
        varchar perm2_code
        varchar perm3_code
        varchar perm4_code
    }
    sys_rbac_auth_name {
        varchar id PK
        varchar name
    }
    sys_rbac_auth_entry {
        varchar auth_id PK
        varchar menu_id PK
        boolean perm1
        boolean perm2
        boolean perm3
        boolean perm4
    }
    sys_rbac_role_name {
        varchar id PK
        varchar name
    }
    sys_rbac_role_entry {
        varchar id PK
        varchar auth_id PK
    }

    sys_menu ||--o{ sys_rbac_auth_tmpl : "menu_id 참조"
    sys_menu ||--o{ sys_rbac_auth_entry : "menu_id 참조"
    sys_rbac_auth_name ||--o{ sys_rbac_auth_entry : "auth_id"
    sys_rbac_role_name ||--o{ sys_rbac_role_entry : "id"
    sys_rbac_auth_name ||--o{ sys_rbac_role_entry : "auth_id"

실제 생성 데이터 요약

-- [1] SYS0103: 메뉴
INSERT INTO sys_menu (id, parent_id, type, url, level) VALUES
    ('PT',    '',    'MENU',   null,       0),
    ('PT01',  'PT',  'FOLDER', null,       1),
    ('PT0101','PT01','URL',    '/pt/0101', 2);

-- [2] SYS0102: 메시지
INSERT INTO sys_message (message_code, message_name, message_type, locale) VALUES
    ('MENU.PT',         'PT 관리',           'MENU',       'ko'),
    ('MENU.PT01',       'PT 기본관리',        'MENU',       'ko'),
    ('MENU.PT0101',     '가상 코드 관리',     'MENU',       'ko'),
    ('PT0101.BREADCRUMB', 'PT 관리 / 가상 코드 관리', 'BREADCRUMB', 'ko');

-- [3] SYS0201: 권한 템플릿
INSERT INTO sys_rbac_auth_tmpl (category, id, parent_id, perm1_code, perm2_code, perm3_code, perm4_code)
    VALUES ('PT', 'PT0101', 'PT01', 'READ', 'CREATE', 'UPDATE', 'DELETE');

-- [4] SYS0202: 권한 그룹 + 권한 항목
INSERT INTO sys_rbac_auth_name (id, name) VALUES ('{UUID}', 'PT 전체 권한');
INSERT INTO sys_rbac_auth_entry (auth_id, category, menu_id, parent_menu_id, perm1, perm2, perm3, perm4, ...)
    VALUES ('{UUID}', 'PT', 'PT0101', 'PT01', true, true, true, true, ...);

-- [5] SYS0204: 역할에 권한 그룹 추가
INSERT INTO sys_rbac_role_entry (id, auth_id) VALUES ('{역할 UUID}', '{권한 UUID}');

11. 권한 코드 변환 원리

hera-v4 보안 설정이 sys_rbac_auth_tmpl의 권한 코드를 Spring Security ROLE로 어떻게 바꾸는지 알면 @PreAuthorize 어노테이션을 직관적으로 작성할 수 있습니다.

[DB] sys_rbac_auth_tmpl.id        = PT0101
[DB] sys_rbac_auth_tmpl.perm1_code = READ
     ↓  변환 규칙: ROLE_{ID}_{PERM_CODE}
[Spring Security] ROLE_PT0101_READ
[코드] @PreAuthorize("hasRole('ROLE_PT0101_READ')")

새 메뉴를 추가할 때도 권한 코드를 따로 외울 필요 없이 ROLE_{메뉴ID}_{템플릿에_등록한_PERM_CODE} 패턴 하나만 기억하면 충분합니다.


12. 이 챕터 요약

단계 화면 테이블 등록 내용
1 SYS0103 sys_menu PT, PT01, PT0101 메뉴 계층
2 SYS0102 sys_message 메뉴명, 빵조각, HTML 제목 메시지
3 SYS0201 sys_rbac_auth_tmpl PT0101에 READ/CREATE/UPDATE/DELETE 코드 정의
4 SYS0202 sys_rbac_auth_name
sys_rbac_auth_entry
권한 그룹 생성 + 각 메뉴 권한 체크
5 SYS0204 sys_rbac_role_entry 역할에 권한 그룹 연결
6 SYS0301 (역할 배정 테이블) 사용자에 역할 부여 → 재로그인

학습 매뉴얼 완료

이 챕터를 완료하면 hera-v4에서 신규 메뉴 1개를 자력으로 만드는 전 과정을 경험한 것입니다.

Part 1 전체 흐름:

Ch 1. hera-v4 읽는 법      — 14모듈 구조, 두 가지 요청 흐름 이해
Ch 2. 로컬 환경 셋업       — JDK 25, 라이선스, hera-webapp 로컬 실행
Ch 3. sys0101 깊이 보기    — 8단계 요청 흐름을 코드로 추적
Ch 4. 가상 코드 관리 만들기 — 13개 파일로 신규 CRUD 메뉴 구현
Ch 5. 메뉴·권한·메시지 등록 — DB 등록으로 메뉴 노출 + 권한 적용