5.1 KiB
5.1 KiB
메뉴 관리 개발 가이드
포탈 GNB/마이페이지 메뉴는 menu.yml → DB(PTL_MENU_*) → 캐시 → 템플릿 렌더 구조로 동작하며,
노출/배치 관리는 eapim-admin 포탈메뉴관리(파트너포탈 > 포탈관리 > 메뉴 관리)에서 수행한다.
구성 요소
| 구성 | 위치 | 역할 |
|---|---|---|
menu.yml |
src/main/resources/menu.yml |
기본 메뉴 정의 (id/노출명/path/권한/기본 배치) |
roles.yml |
src/main/resources/roles.yml |
역할 정의 (portal.portal_security 이동분) |
| 엔티티/공유 서비스 | elink-portal-common com.eactive.apim.portal.menu.* |
PTL_MENU_ITEM·PTL_MENU_PLACEMENT·PTL_ROLE(+AUTHORITY), PortalMenuDataService |
| 시더 | djb/menu/MenuSeeder.java |
부팅 시 yml→DB 적재 (ApplicationReadyEvent) |
| 캐시 | djb/menu/MenuService.java |
role 비의존 트리 스냅샷, TTL 1시간(PTL_PROPERTY) |
| 렌더 | djb/menu/MenuModelAdvice.java → 모델 menuView |
요청별 노출(EXPOSE_ROLES) 필터 |
| 접근 제어 | djb/menu/MenuAccessInterceptor.java |
ACCESS_ROLES 서버측 집행 (경로 정확 일치) |
| 내부 API | djb/menu/MenuInternalController.java |
POST /internal/menu/reload (admin 캐시 리로드 수신) |
메뉴를 소비하는 템플릿: fragment/djbank/header_container.html(데스크톱 nav·마이페이지 드롭다운·모바일 drawer),
fragment/djbank/service_sidebar.html. 모두 ${menuView} 를 반복 렌더하므로 메뉴 추가 시 템플릿 수정 불필요.
menu.yml 스키마
portal-menu:
items:
- id: support # kebab-case 필수 (^[a-z0-9-]+$). 변경 금지(변경=신규 항목)
name: "고객지원"
group: true # 상위 그룹. path 생략 시 클릭 없음(자식 있어야 노출)
section: GNB # GNB(기본) | MYPAGE. 자식은 부모 섹션 상속
expose-roles: [] # 생략=전체(익명 포함), AUTHENTICATED=로그인자, 그 외 역할코드 any-of
children:
- { id: support-faq, name: "FAQ", path: /faq_list }
- { id: my-page-webhook, name: "Webhook 관리", path: /webhook, icon: fa-bell,
expose-roles: [ROLE_WEBHOOK], access-roles: [ROLE_WEBHOOK] }
expose-roles= 메뉴 노출 조건,access-roles= URL 접근 조건(인터셉터 차단, redirect).icon은 마이페이지 드롭다운 전용(FontAwesome 클래스).- 정렬은 yml 나열 순서(기본 배치 sort = index×10).
시딩 규칙 (MenuSeeder)
- 항목: id 기준 upsert. yml 값이 바뀌면 DFLT_*(기본값 스냅샷)를 갱신하고,
관리자가 수정하지 않은 필드(현재값==구 기본값)만 새 기본값을 따라간다.
구조 필드(
group/section/icon/new-window)는 항상 yml 이 이긴다. - 배치:
PTL_MENU_PLACEMENT가 비어있을 때만 기본 배치로 최초 시딩. 이후 배치는 admin 이 소유한다 — 재배포/재기동에도 보존됨. - yml 에서 항목을 제거해도 DB 는 삭제하지 않고 경고 로그만 남긴다(수동 정리).
- 부팅 시딩 주체는 인증 사용자가 없으므로
CREATED_BY=SYSTEM.
캐시와 리로드
- 스냅샷 TTL: PTL_PROPERTY
Portal / menu.cache.ttl-seconds(기본 3600초). - 즉시 반영:
curl -X POST http://127.0.0.1:39130/internal/menu/reload(admin 포탈메뉴관리의 [캐시 Reload] 버튼이 동일 호출 수행). - 내부 API 가드:
Portal / menu.internal.allow-ips허용 IP 목록(기본 loopback)- X-Forwarded-For 동반 요청 거부. CSRF 면제(
/internal/menu/**).
- X-Forwarded-For 동반 요청 거부. CSRF 면제(
- admin 측 호출 URL:
Portal / portal.internal.menu-reload-url.
새 메뉴 추가 절차
기본 메뉴(코드 배포와 함께)
- 페이지/라우트 준비 (
portal.pages또는@GetMapping— 기존 방식 그대로) menu.yml에 항목 추가 (필요 시 breadcrumb 용page.home트리도 갱신 — 별도 체계 유지)- 재기동 → 시딩 로그 확인 → 헤더/드로어 노출 확인
- 이미 운영 중인 DB 라면 배치는 자동 추가되지 않음(배치 시딩은 최초 1회) — admin 화면에서 미배치 → 원하는 위치로 드래그 후 저장
운영자 임시 메뉴(외부 링크 등): admin 포탈메뉴관리 [메뉴 추가] → 미배치 생성 → 드래그 배치 → 저장 → 캐시 Reload. 커스텀 항목은 미배치 시 삭제된다.
로컬 개발 주의
gradle bootRun으로 시딩까지 확인하려면 damo-manager 가 classpath 에 필요:JAVA_TOOL_OPTIONS="-Xbootclasspath/a:<...>/apache-tomcat-9.0.115-djb/lib/damo-manager.jar"(미지정 시 감사 컬럼 암호화 컨버터에서 NoClassDefFoundError).- 템플릿/메뉴 반영 확인은 서버 재시작 후 curl 로.
- elink-portal-common 수정 후 Q클래스 duplicate 컴파일 오류 시 각 모듈
build/generated삭제 후 재컴파일.
역할(roles.yml) 변경
- 로그인 권한 확장은
PortalRolesProperties(yml 바인딩)를 직접 사용 — DB 미러(PTL_ROLE*)는 admin 권한 선택 체크박스 소스 전용. - 역할 추가 시
roles.yml의authority-names에 한글 라벨을 함께 등록해야 admin 화면에 표기된다.