Files
eapim-portal/readme-docs/메뉴-관리-개발-가이드.md
T

5.1 KiB
Raw Blame History

메뉴 관리 개발 가이드

포탈 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)

  1. 항목: id 기준 upsert. yml 값이 바뀌면 DFLT_*(기본값 스냅샷)를 갱신하고, 관리자가 수정하지 않은 필드(현재값==구 기본값)만 새 기본값을 따라간다. 구조 필드(group/section/icon/new-window)는 항상 yml 이 이긴다.
  2. 배치: PTL_MENU_PLACEMENT비어있을 때만 기본 배치로 최초 시딩. 이후 배치는 admin 이 소유한다 — 재배포/재기동에도 보존됨.
  3. yml 에서 항목을 제거해도 DB 는 삭제하지 않고 경고 로그만 남긴다(수동 정리).
  4. 부팅 시딩 주체는 인증 사용자가 없으므로 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/**).
  • admin 측 호출 URL: Portal / portal.internal.menu-reload-url.

새 메뉴 추가 절차

기본 메뉴(코드 배포와 함께)

  1. 페이지/라우트 준비 (portal.pages 또는 @GetMapping — 기존 방식 그대로)
  2. menu.yml 에 항목 추가 (필요 시 breadcrumb 용 page.home 트리도 갱신 — 별도 체계 유지)
  3. 재기동 → 시딩 로그 확인 → 헤더/드로어 노출 확인
  4. 이미 운영 중인 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.ymlauthority-names 에 한글 라벨을 함께 등록해야 admin 화면에 표기된다.