콘텐츠로 이동

code-gen popup 개발자 가이드

****_hera-code-genpopup 프로파일은 DB 테이블 메타데이터를 기준으로 팝업 전용 HTML fragment를 생성하고, 필요하면 부모 화면에 팝업 호출 버튼과 layout:insert까지 자동으로 추가하는 프로세스다.

1. 개요

목적

  • 기존 webapp 화면에 붙일 offcanvas 또는 modal 팝업 fragment를 생성한다.
  • 입력 화면과 조회 전용 화면을 분리해서 생성한다.
  • DB 컬럼 기반 초안 생성 후 개발자가 YAML로 필드 순서, 레이아웃, 컨트롤 타입을 보정한다.
  • 최종 렌더 단계에서 부모 페이지의 toolbar 버튼과 fragment insert 영역을 패치한다.

실행 모드

항목
Spring profile popup
code-generator.mode popup
ConfigBuilder PopupConfigBuilder
Generator WebappPopupGenerator
출력 위치 hera-webapp/src/main/resources/templates/{module}/

지원 유형

popup.type popup.page-type 템플릿 출력 suffix 기본 fragment
offcanvas input OC0101-html.tmpl o01 offcanvas
offcanvas view OC0102-html.tmpl o01-ro offcanvas
modal input MD0101-html.tmpl m01 modal
modal view MD0102-html.tmpl m01-ro modal

3단계 산출 흐름

application-codegen-popup.yml
  -> table 단계: popup-table/{domain-code}-popup-table.yml 생성
  -> layout 단계: popup-config/{domain-code}-popup-config.yml 생성
  -> render 단계: hera-webapp templates HTML 생성 + 부모 페이지 패치

popup.stage=auto이면 파일 존재 여부와 수정 시간을 기준으로 다음 단계가 자동 결정된다.

  • popup-table 파일이 없으면 table
  • popup-table은 있고 popup-config가 없으면 layout
  • popup-tablepopup-config보다 최신이면 layout
  • 그 외에는 render

2. 빠른 시작

1. 설정 파일 수정

_hera-code-gen/src/main/resources/application-codegen-popup.yml을 열고 대상 정보를 지정한다.

code-generator:
  mode: popup
  run-mode: output-module

  package:
    module: sys

  target-table: sys_board_content_reply

  webapp:
    domain-code: sys9902
    popup:
      type: offcanvas
      page-type: input
      size: md
      stage: auto
      parent-page-id: sys0101

핵심 설정은 다음과 같다.

설정 설명
target-table DB 메타데이터를 읽을 원본 테이블
package.module 출력 템플릿 하위 모듈 경로. 예: sys
webapp.domain-code 출력 파일명과 popup YAML 파일명 기준
popup.type offcanvas 또는 modal
popup.page-type input 또는 view
popup.size sm: 1열, md: 2열, lg: 3열. 기본 컬럼 수와 width 산정에 사용
popup.parent-page-id 버튼과 layout:insert를 추가할 부모 화면 id

2. 1차 실행: popup-table 생성

_hera-code-gen AppRunner 실행

또는

./gradlew :_hera-code-gen:bootRun --args="--spring.profiles.active=popup"

생성 파일:

_hera-code-gen/src/main/resources/popup-table/{domain-code}-popup-table.yml

이 파일에서 화면에 보여줄 필드와 숨김 필드를 정리한다.

3. 2차 실행: popup-config 생성

_hera-code-gen AppRunner 실행

또는

./gradlew :_hera-code-gen:bootRun --args="--spring.profiles.active=popup"

생성 파일:

_hera-code-gen/src/main/resources/popup-config/{domain-code}-popup-config.yml

이 파일에서 팝업 제목, 크기, 행/열 배치, 컨트롤 타입, readonly, 검색 버튼, 공통코드 그룹 등을 보정한다.

4. 3차 실행: HTML 렌더 및 부모 페이지 패치

_hera-code-gen AppRunner 실행

또는

./gradlew :_hera-code-gen:bootRun --args="--spring.profiles.active=popup"

생성 파일 예시:

hera-webapp/src/main/resources/templates/sys/sys9902-o01.html

parent-page-id가 있으면 부모 페이지에도 다음 항목이 추가된다.

  • <div class="card-options toolbar"> 내부 팝업 열기 버튼
  • 부모 page-content 종료 전 layout:insert="~{sys/sys9902-o01 :: offcanvas}"

3. 단계별 적용 가이드

Step 1. popup 기본 설정 확정

먼저 application-codegen-popup.yml에는 실행에 필요한 최소값만 둔다.

target-table: sys_board_content_reply
webapp:
  domain-code: sys9902
  popup:
    type: offcanvas
    page-type: input
    size: md
    stage: auto
    parent-page-id: sys0101

page-id, page-title, width, height는 처음부터 고정하지 않아도 된다. popup-config 생성 후 화면 요구사항에 맞춰 수정하는 편이 관리하기 쉽다.

Step 2. popup-table 보정

popup-table은 화면 필드 후보를 고르는 1차 설계 파일이다.

table:
  name: "sys_board_content_reply"
  title: "댓글"
hidden-fields:
  - boardContentReplyId
fields:
  - boardContentId
  - replyContent
  - useYn
# additional-fields:
#   - name: "replyTypeName"
#     label: "댓글 유형명"
#     input-type: "text"

적용 규칙:

  • PK 컬럼은 기본적으로 hidden-fields에 들어간다.
  • 화면에 노출할 컬럼은 fields에 둔다.
  • 필드 순서는 화면 출력 순서가 된다.
  • DB에 없는 보조 필드는 additional-fields에 정의하고 fields에도 같은 name을 추가한다.
  • 숨김 필드를 화면에 보이게 하려면 hidden-fields에서 제거하고 fields로 옮긴다.
  • additional-fields: table에 정의되지 않은 field를 추가한다. name속성을 fields에 추가하고 labelinput-type을 정의한다.

additional-fields 추가 예제

table:
  name: "sys_board_content_reply"
  title: "댓글"
hidden-fields:
  - boardContentReplyId
fields:
  - boardContentId
  - replyContent
  - useYn
  - replyTypeName
additional-fields:
   - name: "replyTypeName"
     label: "댓글 유형명"
     input-type: "text"

Step 3. popup-config 보정

popup-config는 실제 HTML 렌더링의 source of truth다.

popup:
  type: "offcanvas"
  page-type: "input"
  page-id: "boardContentReplyRegOffcanvas"
  domain-code: "sys9902"
  page-title: "댓글 등록"
  width: "720px"
  height: "340px"
  parent-page-id: "sys0101"
card:
  title: "기본 정보"
hidden-fields:
  - name: "boardContentReplyId"
    value: ""
col-groups:
  - key: "label-1"
    width: "120px"
  - key: "field-1"
    width: "auto"
rows:
  - row:
      - label: "댓글 내용"
        required: true
        col-group: "field-1"
        colspan: 3
        rowspan: 1
        controls:
          - name: "replyContent"
            input-type: "textarea"
            align: "left"
            readonly: false
            disabled: false
            search-btn: false
            rows: 3
            common-code-group: ""

주요 컨트롤 타입:

input-type 렌더링
text 일반 input
number 숫자 input, 우측 정렬 권장
date datepicker 클래스 포함 input
textarea textarea
select select2 대상 select
select-yn Y/N select
radio inline radio
check, checkbox inline checkbox

Step 4. 렌더 결과 확인

최종 생성 HTML에서 다음을 확인한다.

  • fragment 이름이 offcanvas 또는 modal인지 확인
  • page-id가 중복되지 않는지 확인
  • name, id, hidden field가 후속 JS에서 기대하는 값과 맞는지 확인
  • select, radio, check에 필요한 공통코드 map 주석을 실제 데이터 바인딩 방식에 맞게 해제/수정
  • view 화면이면 입력 컨트롤이 읽기 전용 표시 목적에 맞는지 확인

Step 5. 부모 페이지 패치 확인

parent-page-idsys0101이면 패치 대상은 다음 규칙으로 계산된다.

hera-webapp/src/main/resources/templates/{rootDomain}/{parent-page-id}.html
rootDomain = parent-page-id 앞 3자리
예: sys0101 -> templates/sys/sys0101.html

부모 페이지에는 다음 구조가 있어야 자동 버튼 생성이 가능하다.

<div class="card-options toolbar">
    ...
</div>

그리고 page-content를 감싸는 마지막 </th:block>이 있어야 layout:insert 블록을 삽입할 수 있다.

4. 핵심 패턴 & 안티패턴

핵심 패턴

패턴 설명
auto stage 유지 일반 작업에서는 stage: auto로 두고 파일 상태로 다음 단계를 판단하게 한다.
popup-table은 필드 선별 전용 필드 노출 여부와 순서만 빠르게 정리한다. 세부 레이아웃은 popup-config에서 한다.
popup-config를 최종 설계 파일로 관리 실제 렌더링 기준은 popup-config다. 제목, 크기, id, rows, controls를 여기서 확정한다.
page-id 명시 같은 부모 화면에 팝업이 여러 개 붙는 경우 DOM id 충돌을 피하기 위해 명시한다.
parent-page-id는 최종 렌더 단계에서만 사용 YAML 초안 생성과 fragment 렌더링은 부모 패치 없이도 가능하다.
DB 외 필드는 additional-fields 사용 임의 필드를 코드에 하드코딩하지 않고 YAML 입력으로 유지한다.

안티패턴

안티패턴 문제
생성된 HTML을 먼저 직접 수정 재렌더 시 덮어쓰기 위험이 있다. 반복 가능한 변경은 popup-config에 반영한다.
popup-table만 수정하고 바로 render 기대 popup-table이 바뀌면 layout 단계가 다시 돌아 popup-config를 갱신해야 한다.
parent-page-id를 잘못 지정 존재하지 않는 부모 페이지면 렌더 마지막에 실패한다.
부모 toolbar 구조 변경 patcher는 <div class="card-options toolbar"> 패턴을 찾는다. 구조가 다르면 버튼 삽입에 실패한다.
popup.type, popup.page-type 임의 값 사용 허용 값 외에는 예외가 발생한다.
domain-code 대소문자 혼용 출력 파일과 YAML 파일명은 소문자 기준으로 처리된다. 도메인 코드는 일관되게 소문자로 쓰는 편이 안전하다.

5. 트러블슈팅

[CODE-GEN] popup mode requires code-generator.target-table.

application-codegen-popup.ymlcode-generator.target-table이 비어 있다. 팝업 초안은 DB 테이블 메타데이터를 기반으로 하므로 대상 테이블을 반드시 지정해야 한다.

popup.stage 값이 허용 범위를 벗어났다. 아래 중 하나로 수정한다.

stage: auto

강제로 특정 단계만 실행해야 할 때만 table, layout, render를 사용한다.

layout 단계에 필요한 popup-table/{domain-code}-popup-table.yml이 없다. stage: auto 또는 stage: table로 1차 파일을 먼저 생성한다.

render 단계에 필요한 popup-config/{domain-code}-popup-config.yml이 없다. popup-table을 만든 뒤 다시 실행해서 popup-config를 먼저 생성한다.

[CODE-GEN] popup.type must be offcanvas or modal

popup.typeoffcanvas, modal만 허용된다. 대소문자는 내부에서 소문자로 정규화되지만 다른 값은 사용할 수 없다.

[CODE-GEN] popup.page-type must be input or view

popup.page-typeinput, view만 허용된다.

popup.parent-page-id로 계산한 부모 HTML 파일이 없다. 예를 들어 parent-page-id: sys0101이면 hera-webapp/src/main/resources/templates/sys/sys0101.html이 존재해야 한다.

부모 페이지에 다음 toolbar 구조가 없다.

<div class="card-options toolbar">

부모 페이지 구조를 기존 webapp 패턴에 맞추거나, parent-page-id를 비워 fragment만 생성한 뒤 수동으로 붙인다.

부모 페이지에서 layout:insert 블록을 넣을 기준이 되는 마지막 </th:block>을 찾지 못했다. 부모 템플릿의 page-content 구조를 확인한다.

한글 주석이나 placeholder가 깨져 보임

일부 generator 소스의 문자열은 기존 인코딩 이슈로 깨져 보일 수 있다. 새로 생성/수정하는 YAML과 Markdown은 UTF-8로 저장하고, 실제 화면 문구는 popup-config에서 명시적으로 보정한다.

6. 레퍼런스 링크

설정과 실행

  • _hera-code-gen/src/main/resources/application-codegen-popup.yml
  • _hera-code-gen/src/main/resources/application.yml
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/config/CodeGenConfig.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/config/GlobalConfigFactory.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/config/PopupConfigBuilder.java

generator 구현

  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/GeneratorFactory.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/core/constant/GenTypeConst.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/core/config/WebappPopupConfig.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/WebappPopupGenerator.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/WebappPopupParentPagePatcher.java

YAML 스펙

  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/popup/PopupTableSpec.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/popup/PopupTableSpecIO.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/popup/PopupSpec.java
  • _hera-code-gen/src/main/java/kr/co/dandisoft/hera/codegen/generator/webapp/popup/PopupSpecIO.java

템플릿

  • _hera-code-gen/src/main/resources/templates/popup/OC0101-html.tmpl
  • _hera-code-gen/src/main/resources/templates/popup/OC0102-html.tmpl
  • _hera-code-gen/src/main/resources/templates/popup/MD0101-html.tmpl
  • _hera-code-gen/src/main/resources/templates/popup/MD0102-html.tmpl

관련 문서

  • docs/references/code-gen-form-field-guide.md
  • .agents/skills/project/hera-codegen/SKILL.md