Imported from JasonMMo/nexacro-claude-skills (
plugins/nexacro-fullstack-starter/skills/nexacro-fullstack-starter/SKILL.md). Install upstream withnpx skills add JasonMMo/nexacro-claude-skills --skill nexacro-fullstack-starter. Copyright stays with the author.
Nexacro Fullstack Starter
Scaffold a ready-to-run Nexacro N v24 project in one step. You pick (JDK, framework, eGov?) — the skill picks the runner, clones the monorepo, strips everything you don't need, substitutes tokens, and hands you a working project.
개요 / Overview
- 입력: jdk 버전, 프레임워크, (eGov 사용 여부), 프로젝트 이름
- 출력: nxui + Spring 서버가 들어있는 독립 프로젝트 디렉터리
- 소스:
github.com/JasonMMo/nexacroN-fullstack(clone 후 sparse-checkout) - 매트릭스:
assets/matrix.json(현재 7개 runner 구현 완료 + 1개 placeholder) - 출력 구조:
<TARGET_DIR>/{nxui/, src/, pom.xml, README.md}— runner 디렉터리 평탄화 (project root 에서 바로mvn실행 가능)
Step 1 — 파라미터 수집 / Collect parameters
1-1. 파라미터 수집
CLI 아규먼트(--jdk, --framework 등)로 전달된 값은 이미 받은 것으로 간주하고 건너뜁니다.
자동 확정 항목 (질문 없이 즉시 설정):
- nexacro 버전:
nexacroN고정 (현재 유일 지원 버전) - 타겟 디렉터리:
./<PROJECT_NAME>으로 자동 확정 (프로젝트명 입력 후 계산)
사용자 입력 필요 항목 (3개만 질문):
[1/3] JDK 버전 / JDK version
선택지: 8 | 17
- 8 → Spring 5 / javax / Boot 2 / eGov4
- 17 → Spring 6 / jakarta / Boot 3 / eGov5
[2/3] 프레임워크 / Framework
선택지:
- spring-boot (Spring Boot - embedded Tomcat) ✅ 구현 완료
- spring-mvc (전통 MVC - WAR 배포, Tomcat 10/9) ✅ 구현 완료
- egov-boot (표준프레임워크 Boot - eGov 4/5) ✅ 구현 완료
- egov-mvc (표준프레임워크 MVC - jdk8만, eGov 4) ✅ 구현 완료
- webflux (Spring WebFlux - jdk17만) ⏳ 업스트림 Plan 2 대기
현재 사용 가능: spring-boot, spring-mvc, egov-boot, egov-mvc.
`webflux` 는 upstream nexacroN-fullstack 에 placeholder README 만
있으므로 scaffold 시 거부됩니다.
[3/3] 프로젝트 이름 / Project name
예: my-nexacro-app
제약: 영숫자 + 하이픈만, 공백 불가
3개 질문이 끝나면 자동으로 아래를 확정한다 (추가 질문 없음):
NEXACRO_VERSION = nexacroNTARGET_DIR = ./<PROJECT_NAME>경고: TARGET_DIR 이 이미 존재하면 중단 (덮어쓰기 안 함)
1-2. 파생 변수 계산
assets/matrix.json 의 derivationRules 로 파생:
| 변수 | 규칙 |
|---|---|
servletApi |
jdk >= 17 ? "jakarta" : "javax" |
springMajor |
servletApi == "jakarta" ? 6 : 5 |
bootMajor |
framework ∈ {spring-boot, egov-boot, webflux} ? (jakarta ? 3 : 2) : null |
egovMajor |
framework == "egov-boot" ? (jakarta ? 5 : 4) : (framework == "egov-mvc" ? 4 : null) |
1-3. runner key 결정
(framework, jdk) 조합으로 runner key 계산 — 상세는 references/runner-selection-guide.md 참고.
예:
(spring-boot, 17)→boot-jdk17-jakarta(egov-mvc, 8)→egov4-mvc-jdk8-javax(webflux, 17)→webflux-jdk17-jakarta
Step 2 — 호환성 체크 / Compatibility check
assets/matrix.json 의 rejectedCombinations 를 순회하며 요청 조합이 매치되면 거부하고 사유와 대안을 출력합니다.
현재 거부 조합:
framework=egov-mvc + jdk=17— eGov4 MVC jdk17 미지원 →egov5-boot-jdk17-jakarta권장framework=webflux + jdk=8— WebFlux는 jdk17+ 전용 →boot-jdk8-javax권장framework=webflux— 업스트림 nexacroN-fullstack 에 placeholder 만 존재 (Plan 2 미구현). 현재 scaffold 가능:spring-boot(양 lane),spring-mvc(양 lane),egov-boot(eGov 5 jdk17/jakarta, eGov 4 jdk8/javax),egov-mvc(eGov 4 jdk8/javax). webflux 요청 시 alternative 로(spring-boot, jdk=17)권장.
호환성 통과 시 확정된 runner key 및 파생 변수 전체를 사용자에게 재확인합니다:
🎯 확정 구성 / Confirmed configuration
────────────────────────────────────────
nexacro: nexacroN
runner: boot-jdk17-jakarta
jdk: 17
servletApi: jakarta
framework: spring-boot
bootMajor: 3
springMajor: 6
egovMajor: (none)
────────────────────────────────────────
이대로 진행할까요? / Proceed? (y/n)
Step 3 — Sparse clone & flatten
업스트림
JasonMMo/nexacroN-fullstack의 implemented runner (samples/runners/boot-jdk17-jakarta,samples/runners/boot-jdk8-javax) 는 self-contained 입니다 (parent BOM / shared-business 의존성 없음). 따라서 sparse-checkout 으로nxui+ 해당 runner 만 받은 뒤, runner 디렉터리 내용을 project root 로 평탄화하면 바로 빌드 가능합니다.
3-0. 실행 환경 가드 (필수)
본 Step 의 모든 셸 명령은 단일 native shell 세션 에서 실행해야 합니다. $TMP_DIR 변수가 호출 간에 공유되어야 하기 때문입니다.
- ✅ Bash 도구로
&&chained command 한 번에 실행 - ✅ 또는 각 단계 직전에
export TMP_DIR=...재선언 - ❌
ctx_batch_execute처럼 호출별 컨테이너 격리가 일어나는 도구 사용 금지 (각 호출마다 새/tmp가 생성되어 이전 단계 산출물을 못 찾음)
3-1. 임시 디렉터리로 sparse clone (--no-cone 모드)
TMP_DIR=$(mktemp -d)
cd "$TMP_DIR"
git clone --filter=blob:none --no-checkout https://github.com/JasonMMo/nexacroN-fullstack.git
cd nexacroN-fullstack
git sparse-checkout init --no-cone
git sparse-checkout set \
nxui \
samples/runners/${RUNNER_KEY}
git checkout
--no-cone모드 이유: cone 모드는 디렉터리 단위만 허용하고 파일 단위 패턴을 거부합니다. 일관되게--no-cone사용. top-levelapi-contract,core, rootpom.xml, rootREADME.md, rootLICENSE,.gitignore,samples/seed-data,samples/shared-business*는 모두 체크아웃 대상에서 제외 — runner 가 self-contained 이므로 불필요합니다.
3-2. 타겟 디렉터리로 평탄화 복사
nxui/ 는 그대로 복사하고, runner 디렉터리의 내용물 (src/, pom.xml, README.md) 을 project root 로 평탄화합니다.
mkdir -p "${TARGET_DIR}"
cp -r "$TMP_DIR/nexacroN-fullstack/nxui" "${TARGET_DIR}/"
cp -r "$TMP_DIR/nexacroN-fullstack/samples/runners/${RUNNER_KEY}/." "${TARGET_DIR}/"
rm -rf "$TMP_DIR"
cd "${TARGET_DIR}"
3-3. 산출 트리 검증 (필수)
평탄화가 정확히 적용됐는지 검증:
# 있어서는 안 되는 디렉터리/파일
for forbidden in api-contract core samples; do
[ -e "$forbidden" ] && { echo "ERROR: '$forbidden' should not exist after flatten" >&2; exit 1; }
done
# 반드시 있어야 하는 항목
for required in nxui src pom.xml; do
[ ! -e "$required" ] && { echo "ERROR: required '$required' missing" >&2; exit 1; }
done
echo "✅ flatten verified: nxui/ src/ pom.xml"
3-4. 4.2 canonical layout 검증 (필수)
업스트림 runner 가 GitLab canonical uiadapter 패턴 (com.nexacro.uiadapter.{config, controller, domain, mapper, service, service.impl} 평면 패키지) 을 따르는지 강제 검증합니다. OLD self-implemented 패턴 (com.nexacro.fullstack.* / com.nexacro.runner.*) 이 감지되면 실패하고 사용자에게 PR 머지 상태 점검을 요청합니다.
# legacy 패키지 부재 확인
LEGACY_PKGS=("src/main/java/com/nexacro/fullstack" "src/main/java/com/nexacro/runner")
for legacy in "${LEGACY_PKGS[@]}"; do
if [ -e "$legacy" ]; then
echo "ERROR: legacy package '$legacy' detected." >&2
echo " 업스트림 main 이 OLD self-implemented 패턴입니다." >&2
echo " PR #2 (jakarta) / Phase 2 (javax) 머지 상태를 확인하세요." >&2
exit 1
fi
done
# canonical 패키지 존재 확인
REQUIRED_PKG="src/main/java/com/nexacro/uiadapter"
[ ! -d "$REQUIRED_PKG" ] && { echo "ERROR: canonical package '$REQUIRED_PKG' missing" >&2; exit 1; }
# packaging 판별 — WAR runner 는 SpringApplication 진입점 없음 (Tomcat 가 부트스트랩)
IS_WAR=0
if grep -q '<packaging>war</packaging>' pom.xml 2>/dev/null; then
IS_WAR=1
fi
# Application.java 는 Boot runner 전용 (jar packaging). WAR 일 때는 검증 생략.
if [ "$IS_WAR" -eq 0 ]; then
[ ! -f "$REQUIRED_PKG/Application.java" ] && { echo "ERROR: '$REQUIRED_PKG/Application.java' missing (Boot runner)" >&2; exit 1; }
fi
# 6 개 필수 서브패키지 존재 확인
REQUIRED_SUBDIRS=("config" "controller" "domain" "mapper" "service" "service/impl")
for sub in "${REQUIRED_SUBDIRS[@]}"; do
if [ ! -d "$REQUIRED_PKG/$sub" ]; then
echo "ERROR: canonical subpackage '$REQUIRED_PKG/$sub' missing" >&2
echo " 4.2 layout: com.nexacro.uiadapter.{config, controller, domain, mapper, service, service.impl}" >&2
exit 1
fi
done
# service/ 가 interface 만 (구현체는 service/impl/ 에) 있는지 sanity check
IMPL_OUTSIDE=$(find "$REQUIRED_PKG/service" -maxdepth 1 -name "*Impl.java" 2>/dev/null | wc -l)
if [ "$IMPL_OUTSIDE" -gt 0 ]; then
echo "WARNING: '$REQUIRED_PKG/service/' contains *Impl.java — should be in service/impl/" >&2
fi
echo "✅ 4.2 layout verified"
echo " - legacy packages absent (com.nexacro.{fullstack,runner})"
echo " - canonical: com.nexacro.uiadapter.{config, controller, domain, mapper, service, service/impl}"
if [ "$IS_WAR" -eq 1 ]; then
echo " - packaging: WAR (Application.java 검증 생략 — Tomcat 가 부트스트랩)"
else
echo " - packaging: JAR (Application.java 검증 완료)"
fi
Step 4 — 토큰 치환 / Token substitution
matrix.json 의 tokens 를 순회하며 타겟 디렉터리의 모든 텍스트 파일에서 {{TOKEN}} 을 실제 값으로 치환합니다.
| 토큰 | 치환 값 |
|---|---|
{{PROJECT_NAME}} |
사용자 입력 프로젝트명 |
{{BACKEND_URL}} |
http://localhost:8080/uiadapter/ |
{{CONTEXT_PATH}} |
/uiadapter |
{{SERVER_PORT}} |
8080 |
추가로 Maven 아티팩트 ID 도 업데이트:
# pom.xml 들의 <artifactId>{{PROJECT_NAME}}</artifactId> 치환
find . -name "pom.xml" -exec sed -i "s|{{PROJECT_NAME}}|${PROJECT_NAME}|g" {} \;
Windows 환경에서는
sed -i대신 Python 스크립트 사용 (references/troubleshooting.md 참고).
Step 5 — 후처리 / Post-processing
5-1. 프로젝트 전용 README 생성
타겟 디렉터리에 사용자 설정이 반영된 README.md 덮어쓰기:
# {{PROJECT_NAME}}
Generated by `nexacro-fullstack-starter` plugin.
- **nexacro version**: nexacroN
- **runner**: {{RUNNER_KEY}}
- **jdk**: {{JDK}}
- **framework**: {{FRAMEWORK}}
## Run
1. 서버 실행 (project root 에서 바로): `{{RUN_CMD}}`
2. nexacro IDE 에서 `nxui/packageN.xprj` 열기
3. 브라우저: http://localhost:8080/uiadapter/
## Build prerequisite
- JDK 17+ (jdk8 lane 도 빌드 시점은 JDK 17 권장 — HSQLDB 2.7.x 가 Java 11+ 필요)
- Maven 3.6+
- 인터넷 (tobesoft Nexus 에서 nexacro 1st-party JAR 다운로드, 익명 접근)
5-2. 초기 커밋 (옵션)
Windows 인코딩 가드: scaffold 안에 한글/CP949 파일명이나 CRLF 차이로 인한 git 경고가 있으면 출력 바이트가 unpaired UTF-16 surrogate 로 모델 응답에 섞여
400 no low surrogate in string으로 실패합니다. 아래처럼 quiet +core.quotepath=false+ stderr 차단 형태로 실행해 출력 자체를 흘리지 않습니다.
git init -q
git -c core.quotepath=false -c core.autocrlf=false add -A 2>/dev/null
git -c core.quotepath=false commit -q -m "chore: scaffolded from nexacro-fullstack-starter" 2>/dev/null
echo "✅ initial commit created"
실행 결과는 위 한 줄 (
✅ initial commit created) 만 사용자에게 보고. git stdout/stderr 는 절대 그대로 노출하지 말 것.
사용자에게 물어보고 진행 (기본값: yes).
Step 6 — nexacro 빌드 / Nexacro build (xfdl → xjs)
scaffold 가 끝난 직후 nxui/packageN 의 xfdl 소스를 xjs 로 1회 빌드해야 Spring 정적 경로에서 로드할 수 있습니다. 이 단계는 nexacrodeploy.exe (Nexacro Studio 설치 시 동봉) 가 필요하므로 Claude 가 자동 실행하기보다는 사용자의 로컬 /nexacro-build skill 로 핸드오프 합니다.
6-1. 빌드 경로 결정 (runner 별)
| Runner family | Build output path |
|---|---|
boot-*, webflux-* |
./src/main/resources/static/packageN/ |
mvc-*, egov*-mvc-* |
./src/main/webapp/packageN/ |
runner key 의 prefix 로 자동 매핑:
case "${RUNNER_KEY}" in
boot-*|webflux-*) BUILD_OUT="./src/main/resources/static/packageN/" ;;
mvc-*|egov*-mvc-*) BUILD_OUT="./src/main/webapp/packageN/" ;;
esac
6-2. /nexacro-build skill 안내 메시지
사용자에게 아래 문구를 그대로 출력 (자동 실행하지 않음):
📦 nexacro xfdl → xjs 1회 빌드가 필요합니다.
로컬에 Nexacro Studio 가 설치되어 있으면 user skill `/nexacro-build` 로 실행하세요.
권장 파라미터:
project_xprj = ./nxui/packageN/packageN.xprj
output_path = {{BUILD_OUT}}
baselib_path = ./nxui/packageN/nexacrolib
generaterule_path= <SDK>/generate
또는 CLI 로 직접:
nexacrodeploy.exe \
-P ./nxui/packageN/packageN.xprj \
-O {{BUILD_OUT}} \
-B ./nxui/packageN/nexacrolib \
-GENERATERULE <SDK>/generate
6-3. /nexacro-build 가 설치되어 있는 경우 자동 연계
Claude 환경에서 /nexacro-build skill 이 사용 가능하면 Skill 도구로 직접 호출:
Skill(skill: "nexacro-build", args: "project=./nxui/packageN/packageN.xprj output={{BUILD_OUT}}")
skill 이 없으면 6-2 의 안내 문구만 출력하고 다음 Step 으로 넘어갑니다 (실패 아님).
⚠️ nexacro Studio /
nexacrodeploy.exe는 Windows 전용입니다. macOS / Linux 사용자는 Windows 워크스테이션에서 빌드 후 산출물만 커밋하는 워크플로우를 사용하세요 (references/troubleshooting.md 참고).
Step 7 — License 파일 복사 / Server license copy
scaffold 직후 Nexacro N 서버 license 파일 (NexacroN_server_license.xml) 을 프로젝트 resources 디렉터리로 복사할지 사용자에게 확인합니다. license 가 없으면 service 호출 시점 (xapi HttpPlatformResponse.sendData() 직렬화) 에서 com.nexacro.uiadapter.*.exception.InvalidLicenseException 으로 500 이 발생합니다.
7-1. 기본 탐색 위치
scaffold 된 프로젝트의 부모 폴더 를 default 로 검색합니다 (사용자가 license 를 workspace 루트에 두는 관례 반영):
LICENSE_FILE="NexacroN_server_license.xml"
LICENSE_DEFAULT="$(dirname "$(realpath "$TARGET_DIR")")/${LICENSE_FILE}"
LICENSE_TARGET="${TARGET_DIR}/src/main/resources/${LICENSE_FILE}"
예: TARGET_DIR=./nexa-boot-jdk17 이면 ../NexacroN_server_license.xml 검색.
7-2. 사용자 확인 분기
Case A — default 위치에 파일 존재
📋 server license 파일을 발견했습니다
source: <LICENSE_DEFAULT 의 절대 경로>
target: ${TARGET_DIR}/src/main/resources/NexacroN_server_license.xml
이 파일을 프로젝트 resources 폴더로 복사할까요? (y/n) [y]:
y(또는 빈 입력): 복사 후✅ license 복사 완료출력n: 건너뜀, 7-3 의 미설치 안내 출력
Case B — default 위치에 파일 없음
📋 default 위치에 NexacroN_server_license.xml 이 없습니다
(검색: <LICENSE_DEFAULT 의 절대 경로>)
다른 경로에서 가져오시겠습니까? (y/n) [n]:
n(또는 빈 입력): 건너뜀, 7-3 의 미설치 안내 출력y: 사용자에게 license 파일 절대경로 입력받음 → 존재/확장자 검증 후 복사
7-3. 복사 실행 / 미설치 안내
복사:
mkdir -p "${TARGET_DIR}/src/main/resources"
cp "$LICENSE_PATH" "$LICENSE_TARGET"
echo "✅ license 복사 완료: ${LICENSE_TARGET}"
미설치 (skip 한 경우) 출력:
⚠️ license 미설치: 서버는 정상 기동하지만 service 엔드포인트 호출 시
InvalidLicenseException (500) 이 발생합니다.
license 파일을 확보한 후 ${TARGET_DIR}/src/main/resources/ 에 직접
복사하세요.
license 발급 / 갱신은 운영자 영역입니다. skill 은 파일 복사만 담당합니다.
Step 8 — 사용자 안내 / Final guidance
실행 요약 출력:
=== 4.2 layout 검증 통과 ===
✅ flatten verified (api-contract/core/samples absent)
✅ canonical layout (com.nexacro.uiadapter flat package)
✅ legacy packages absent (com.nexacro.{fullstack,runner})
✅ 프로젝트 생성 완료 / Scaffold complete
─────────────────────────────────────
경로: ./{{PROJECT_NAME}}
runner: {{RUNNER_KEY}}
빌드 경로: {{BUILD_OUT}}
license: {{LICENSE_STATUS}} ← "복사 완료" | "미설치 (skipped)"
─────────────────────────────────────
다음 단계 / Next steps:
1. xfdl 빌드: Step 6 참고 (`/nexacro-build` 또는 nexacrodeploy.exe)
2. DB 초기화: (seed-data 는 서버 첫 실행 시 자동 로드)
3. 서버 실행: {{RUN_CMD}} ← project root 에서 바로 실행
4. nexacro IDE: nxui/packageN.xprj 열기
5. 브라우저: http://localhost:8080/uiadapter/
문제 발생 시 references/troubleshooting.md 참고.
참고 / References
references/compatibility-matrix.md— 매트릭스 전체 + 파생 규칙 상세references/repo-map.md—nexacroN-fullstack모노레포 트리 설명references/runner-selection-guide.md— 어떤 runner 를 골라야 하는지 가이드references/troubleshooting.md— 자주 발생하는 이슈 (port 충돌, JDK mismatch, war 배포)