빈 번들 503 을 "에셋을 선언한 활성 확장이 있는데 결과가 비었다" 로 판정해, 스타일 규칙이 아직 없는 0바이트 CSS 만 선언된 기본 구성이 통째로 503 이 됐다. file_get_contents 는 0바이트에서 false 가 아니라 '' 를 돌려주므로 읽기 실패 분기도 타지 않는다. 선언 축 게터는 전부 file_exists 게이트라 부재를 셀 수 없어, 존재 게이트가 없는 getDeclaredAssetAbsolutePaths 를 통로로 두고 503 의 근거를 소실 축(findMissingDeclaredAssets)으로 옮긴다. 존재하되 비었으면 빈 200 이다. 곁들여: 실패 배너 항목명을 내부 구분 키에서 사용자 어휘로(engine-v1.64.7), 봇 화면이 없는 템플릿 CSS 를 링크하지 않도록 실재 게이트, 매니페스트 자산 선언 드리프트 4건 정정.
13 KiB
Hello 사용자 템플릿 — 에이전트 가이드
이 문서는 이 템플릿을 수정하는 에이전트·확장개발자를 위한 것입니다. 도입 검토·운영 관점은 README.md 를 보세요.
TL;DR (5초 요약)
1. 유형: 템플릿 (gnuboard7-hello_user_template, type=user) — 학습용 최소 User 템플릿. Basic 컴포넌트 8 + 베이스 1 + 홈 1 + **오류 6종**. 홈이 학습용 모듈 API 를 `data_sources` 로 연동한다. `hidden: true`
2. 확장 방식: 훅 없음 — 확장점은 화면 구조와 데이터소스 선언이다. 제공 컴포넌트 목록이 곧 계약
3. 건드리면 안 되는 것: 오류 레이아웃 6종 축소, 401 에서 직접 리다이렉트, 컴포넌트 등록을 한 번만 시도(재시도 필요), 샘플에 실제 사이트 화면 추가
4. 작업 위치: `templates/_bundled/gnuboard7-hello_user_template` — 활성 디렉토리 직접 수정 금지
5. 반영: `php artisan template:update gnuboard7-hello_user_template --force`
1. 이 확장은 무엇인가
학습용 최소 User 템플릿입니다. 방문자 화면 템플릿이 성립하기 위한 최소 구성과, 모듈의 공개 API 를 화면에 연결하는 법을 보이는 것이 목적입니다.
담긴 것은 넷입니다 — Basic 컴포넌트 8개, 베이스 레이아웃 _user_base, 홈 화면 하나,
오류 레이아웃 6종(401 · 403 · 404 · 500 · 503 · maintenance).
홈 화면이 이 샘플의 핵심입니다. data_sources 로 학습용 모듈의 메모 API
(/api/modules/gnuboard7-hello_module/memos)를 호출해 목록을 그립니다 — 모듈이 데이터를,
템플릿이 화면을 담당하는 그누보드7 의 기본 경계를 가장 짧게 보여주는 예시입니다. 실제 게시판·이커머스
모듈도 방문자 화면을 갖지 않고 같은 방식으로 템플릿에 맡깁니다.
manifest.hidden = true 라 관리자 UI 의 템플릿 목록에 나타나지 않습니다. artisan CLI 로는
정상 설치·활성화됩니다.
의도적으로 하지 않는 것: 실제 사이트 화면 · composite/layout 컴포넌트 · 액션 핸들러 ·
SEO 설정 · 확장 오버라이드. sirsoft-basic 이 컴포넌트 79개와 레이아웃 166개를 갖는 것과
나란히 보면 무엇이 필수이고 무엇이 그 템플릿의 선택인지 드러납니다.
2. 디렉토리 지도
| 경로 | 역할 | 수정 시 필요한 절차 |
|---|---|---|
template.json |
manifest (버전 SSoT) | version 변경 시 package.json·package-lock.json 동기화 |
routes.json |
라우트 → 레이아웃 매핑 | php artisan template:update gnuboard7-hello_user_template --force |
layouts/ |
레이아웃 JSON | php artisan template:update gnuboard7-hello_user_template --force (빌드 불필요) |
src/components/ |
React 컴포넌트 | php artisan template:build → php artisan template:update gnuboard7-hello_user_template --force |
dist/ |
커밋되는 빌드 산출물 | --production 으로 재빌드 (sourceMappingURL 잔존 금지) |
CHANGELOG.md |
변경 이력 | 버전 상향 시 항목 추가 (미기재 시 버전 상향 불가) |
components.json |
편집기 컴포넌트 선언 (레이아웃 저작자가 읽는 props 계약) | php artisan template:update gnuboard7-hello_user_template --force |
docs/ |
개발자 문서 | 표면 변경 시 php artisan ext:docgen 재실행 |
lang/ |
다국어 | 키 추가 시 ko·en 동시 반영 + 번들 ja 팩 동기화 |
3. 핵심 흐름
서버 코드가 없으므로 흐름은 컴포넌트 등록 → 라우트 → 레이아웃 → 데이터소스 입니다.
컴포넌트 등록: src/index.ts 가 모듈 로드 시점에 코어 ComponentRegistry 를 찾아 Basic
8개를 등록합니다. 레지스트리가 없으면 경고를 남기고 건너뜁니다.
이 지점이 Admin 샘플과 다릅니다.
gnuboard7-hello_admin_template은initTemplate()안에서 100ms 간격 최대 50회 재시도로 등록하지만, 이 템플릿은 모듈 로드 시점에 한 번만 시도합니다. 로드 순서에 따라 그 시점에 레지스트리가 아직 없으면 등록이 건너뛰어지고, 그러면 레이아웃이 참조하는 컴포넌트 이름을 찾지 못해 화면이 빕니다 — 콘솔 경고 외에는 흔적이 없습니다. 새 템플릿을 만들 때는 Admin 샘플의 재시도 형태를 따르는 것이 안전합니다.
화면 렌더: routes.json 이 / 를 home 에 대응 → 그 레이아웃이 _user_base 를 상속해
헤더·푸터를 얻고 콘텐츠를 채웁니다 → data_sources 의 memos 가 학습용 모듈의 API 를
auto_fetch 로 호출(loading_strategy: progressive) → 응답이 목록 컴포넌트에 바인딩됩니다.
오류 렌더: 코어가 401/403/404/500/503/maintenance 상황을 만나면 활성 템플릿의 해당
레이아웃을 부릅니다. 여섯 모두 _user_base 를 상속하므로 오류 화면에서도 공통 뼈대가
유지됩니다. 401 에서 로그인 리다이렉트를 직접 구현하지 않습니다 — 코어
TemplateApp.showRouteError 가드가 처리합니다.
4. 확장점
| 확장점 | 수 | 상세 |
|---|---|---|
| 제공 컴포넌트 | 8개 | 제공 컴포넌트 |
| 레이아웃 | 8개 | 레이아웃 목록 |
| 전용 핸들러 | 0개 | 템플릿 전용 핸들러 |
| 확장 오버라이드 | 0개 | 확장 오버라이드 |
템플릿의 확장점은 훅이 아니라 화면 구조입니다.
| 확장점 | 이 샘플에서 |
|---|---|
| 제공 컴포넌트 | Basic 8개. 다른 확장이 조각을 끼워 넣을 때 여기 있는 것만 쓸 수 있습니다 |
| 레이아웃 | 8개(베이스 1 + 홈 1 + 오류 6). 모듈이 layout_extensions 로 조각을 끼울 자리는 홈뿐입니다 |
| 확장 오버라이드 | 없음. extensions/{확장}/ 에 같은 이름의 조각을 두면 그 확장이 제공한 원본을 대체합니다 |
| 전용 핸들러 | 없음 |
데이터소스가 이 템플릿의 실질적인 확장점입니다. 홈 화면이 학습용 모듈의 API 를 호출하듯,
User 템플릿은 자기가 그리고 싶은 화면에 필요한 API 를 data_sources 로 선언해 가져옵니다.
모듈을 바꾸거나 늘려도 템플릿의 구조는 그대로이고 선언만 바뀝니다.
그 대가로 모듈의 응답 형태가 바뀌면 화면이 조용히 빕니다. 의존한 모듈을 업그레이드한 뒤에는 그 화면이 여전히 데이터를 그리는지 확인해야 합니다.
5. 수정 시 동반 의무
_bundled에서만 수정하고php artisan template:update gnuboard7-hello_user_template --force로 반영- manifest version 상향 시
package.json·package-lock.json동기화 + CHANGELOG 기재 template.json의assets경로는 실제 산출물을 가리켜야 한다 — 없는 경로를 선언하면 검색엔진용(봇) 화면이 404 를 가리키는<link>를 싣고, 일반 화면에는 흔적이 남지 않는다- 레이아웃 JSON 변경 시 빌드 없이 update 만 — 신규 Tailwind 클래스는 빌드된 CSS 에 존재하는지 확인
- TSX/TS 변경 시
--production재빌드 후dist/커밋 (sourceMappingURL 잔존 금지) - 다국어 키 추가 시 ko·en 동시 반영 + 번들 ja 언어팩 증분 동기화
- 오류 레이아웃 6종(401·403·404·500·503·maintenance)이 모두 있는지 확인 — 하나라도 없으면 그 상황에서 백지가 된다
- 컴포넌트 등록 경로를 손댔다면 재시도 여부를 확인 — 한 번만 시도하면 로드 순서에 따라 화면이 조용히 빈다
- 의존 모듈(
gnuboard7-hello_module)의 API 응답 형태가 바뀌면 홈 화면이 조용히 빈다 — 그 모듈을 올릴 때 함께 확인 - 컴포넌트를 추가·삭제했다면 소스 ·
template.json레지스트리 ·components.json을 함께 갱신 manifest.hidden = true를 유지 (복제본에서만 제거)- TSX 를 고쳤다면
template:build --production후dist/동반 커밋 (sourceMappingURL잔존 금지) - 레이아웃 렌더링 테스트(
__tests__/layouts/*.test.tsx)는 이 템플릿 디렉토리에 둔다 - 레이아웃·컴포넌트·
data_source를 건드렸다면docs/editor-spec.md를 확인 — 이 확장은 편집기 스펙이 없어memos가 편집기 캔버스에서 빈 화면으로 보인다.data_source를 더 늘리면 그 자리도 같은 상태가 된다
6. 금지 패턴
| 금지 | 올바른 사용 | 이유 |
|---|---|---|
| 오류 레이아웃 6종 중 일부를 빼기 | 401 · 403 · 404 · 500 · 503 · maintenance 전부 유지 | 코어가 그 상황에서 활성 템플릿의 레이아웃을 부른다 — 없으면 방문자에게 백지가 된다 |
401 레이아웃에서 로그인으로 직접 리다이렉트 |
코어 TemplateApp.showRouteError 가드에 위임 |
이중 리다이렉트가 되고, 돌아올 위치를 코어가 이미 관리한다 |
| 컴포넌트 등록을 한 번만 시도 | Admin 샘플처럼 재시도 루프를 둔다 | 로드 순서에 따라 레지스트리가 아직 없을 수 있다 — 등록에 실패하면 화면이 조용히 빈다 |
extends 없는 독립 레이아웃에서 toast·openModal 사용 |
_user_base 를 상속하거나 호스트 컴포넌트를 직접 마운트 |
호스트가 없으면 핸들러는 성공으로 기록되는데 화면에는 아무것도 나타나지 않는다 |
| 모듈 API 응답 필드를 화면에서 그대로 가정하고 방어 없이 바인딩 | {{값 ?? ''}} 같은 폴백과 배열 경로 확인 |
응답 형태가 바뀌면 화면이 조용히 빈다 |
| 이 샘플에 실제 사이트 화면을 더해 "쓸모 있게" 만들기 | 짧게 유지하고, 필요한 화면은 별도 템플릿으로 | 샘플의 가치는 "최소 구성이 무엇인가" 를 보이는 것이다 |
manifest.hidden 을 제거 |
그대로 둔다 (복제본에서만 제거) | 학습용 템플릿이 운영 사이트의 템플릿 목록에 섞인다 |
컴포넌트를 추가하면서 template.json 의 레지스트리를 갱신하지 않기 |
소스·레지스트리·components.json 을 함께 |
레이아웃이 참조하는 이름을 찾지 못해 그 컴포넌트만 조용히 렌더되지 않는다 |
TSX 를 고치고 dist/ 재빌드 없이 커밋 |
template:build --production 후 dist/ 동반 커밋 |
브라우저가 받는 것은 커밋된 dist/ 다 — 소스 수정이 사문화된다 |
7. 테스트 실행
| 종류 | 개수 | 위치 |
|---|---|---|
| PHPUnit | 0개 | — |
| Vitest | 2개 | vitest.config.ts |
| Playwright | 0개 | — |
| 시나리오 매니페스트 | 0개 | — |
# Vitest (확장 디렉토리에서) (PowerShell)
cd templates/_bundled/gnuboard7-hello_user_template && powershell -Command "npm run test:run -- <대상>"
무필터 전체 실행은 금지되어 있습니다 — 변경 범위에 걸리는 대상만 지정해 실행합니다.
8. 문서 목차
| 문서 | 내용 | 상태 |
|---|---|---|
| docs/README.md | 문서 통합 목차와 실측 집계 | ✅ |
| docs/architecture.md | 설계 의도·계층 지도·디렉토리 맵 | ✅ |
| docs/components.md | 템플릿이 제공하는 컴포넌트 | ✅ |
| docs/layouts.md | 레이아웃 목록과 라우트 매핑 | ✅ |
| docs/handlers.md | 템플릿 전용 핸들러와 부트스트랩 | ✅ |
| docs/editor-spec.md | 레이아웃 편집기에 선언한 팔레트·컨트롤·샘플 데이터 | ✅ |
| CHANGELOG.md | 변경 이력 | ✅ |