그누보드7 Development Guide
이 문서는 그누보드7 오픈소스 CMS 프로젝트의 개발 가이드입니다. AI 에이전트 및 외부 기여자를 위한 참고 자료입니다.
빠른 참조 - 상세 가이드 문서
| 문서 |
설명 |
TL;DR 핵심 |
| activity-log-hooks.md |
활동 로그 훅 레퍼런스 (Activity Log Hooks Reference) |
코어 66훅 + 이커머스 92훅 + 게시판 32훅 + 페이지 8훅 = 총 198훅 |
| activity-log.md |
활동 로그 시스템 (Activity Log System) |
Monolog 기반: Service 훅 → Listener → Log::channel('activity... |
| api-resources.md |
API 리소스 |
BaseApiResource 상속 필수 |
| authentication.md |
인증 및 세션 처리 |
Laravel Sanctum 토큰 전용 인증 (Bearer 토큰만 사용) |
| broadcasting.md |
Broadcasting (실시간 이벤트) |
Laravel Reverb 사용 (WebSocket) |
| controllers.md |
컨트롤러 계층 구조 |
AdminBaseController / AuthBaseController / PublicBaseCont... |
| core-config.md |
코어 설정 (config/core.php) |
config/core.php = 코어 권한/역할/메뉴/메일템플릿의 SSoT (Single Source ... |
| core-update-system.md |
코어 업데이트 시스템 (Core Update System) |
코어 업그레이드 스텝: upgrades/ 디렉토리 (프로젝트 루트), 네임스페이스 App\Upgrades |
| enum.md |
Enum 사용 규칙 |
상태/타입/분류 = Enum 필수 (PHP 8.1+ Backed Enum) |
| exceptions.md |
Custom Exception 다국어 처리 |
예외 메시지 하드코딩 금지 → __() 함수 필수 |
| middleware.md |
미들웨어 등록 규칙 |
인증 필요 미들웨어 → 전역 등록 금지! |
| notification-system.md |
알림 시스템 (Notification System) |
모든 알림은 BaseNotification 상속 필수 (via() 보일러플레이트 제거) |
| response-helper.md |
API 응답 규칙 (ResponseHelper) |
모든 API 응답은 ResponseHelper 사용 |
| routing.md |
라우트 네이밍 및 경로 |
모든 라우트는 name() 필수: ->name('api.users.index') |
| search-system.md |
Scout 검색 엔진 시스템 (Search System) |
Laravel Scout + DatabaseFulltextEngine: MySQL FULLTEXT + ... |
| seo-system.md |
SEO 페이지 생성기 시스템 (SEO Page Generator) |
SeoMiddleware: 봇 요청 감지 → ?locale= 파라미터 해석 → SeoRenderer가 ... |
| service-provider.md |
서비스 프로바이더 안전성 |
DB 접근 전 .env 파일 존재 확인 필수 |
| service-repository.md |
Service-Repository 패턴 |
RepositoryInterface 주입 필수 (구체 클래스 직접 주입 금지) |
| validation.md |
검증 (Validation) |
필수: FormRequest에서 검증 (Service에 검증 로직 배치 금지) |
| 문서 |
설명 |
TL;DR 핵심 |
| actions-g7core-api.md |
액션 시스템 - G7Core API (React 컴포넌트용) |
- |
| actions-handlers-navigation.md |
액션 핸들러 - 네비게이션 |
- |
| actions-handlers-state.md |
액션 핸들러 - 상태 관리 |
- |
| actions-handlers-ui.md |
액션 핸들러 - UI 인터랙션 |
- |
| actions-handlers.md |
액션 핸들러 - 핸들러별 상세 사용법 |
navigate: 페이지 이동 (path, query, mergeQuery 옵션) |
| actions.md |
액션 핸들러 가이드 |
구조: type 또는 event(이벤트), handler(핸들러명), params(옵션) |
| auth-system.md |
인증 시스템 (AuthManager) |
AuthManager: 싱글톤 인증 상태 관리 클래스 |
| component-props-composite.md |
컴포넌트 Props 레퍼런스 - Composite |
FileUploader: autoUpload, uploadTriggerEvent, imageCompre... |
| component-props.md |
컴포넌트 Props 레퍼런스 |
- |
| components-advanced.md |
컴포넌트 고급 기능 |
- |
| components-patterns.md |
컴포넌트 패턴 및 다국어 |
- |
| components-types.md |
컴포넌트 타입별 개발 규칙 |
- |
| components.md |
컴포넌트 개발 규칙 |
HTML 태그 직접 사용 금지 ( → Div, → Button) |
| dark-mode.md |
다크 모드 지원 (engine-v1.1.0+) |
Tailwind dark: variant 사용 (예: bg-white dark:bg-gray-800) |
| data-binding-i18n.md |
데이터 바인딩 - 다국어 처리 |
- |
| data-binding.md |
데이터 바인딩 및 표현식 |
API 데이터: {{user.name}}, URL 파라미터: {{route.id}} |
| data-sources-advanced.md |
데이터 소스 - 고급 기능 |
- |
| data-sources.md |
데이터 소스 (Data Sources) |
data_sources 배열에 API 정의: id, endpoint, method |
| editors.md |
에디터 컴포넌트 가이드 |
HtmlEditor: HTML/텍스트 편집, 게시판/상품 설명 등 사용 |
| g7core-api-advanced.md |
G7Core 전역 API 레퍼런스 - 고급 |
- |
| g7core-api.md |
G7Core 전역 API 레퍼런스 |
G7Core.state: get/set/subscribe 전역 상태 관리 |
| g7core-helpers.md |
G7Core 헬퍼 API |
- |
| layout-json-components-loading.md |
레이아웃 JSON - 데이터 로딩 및 생명주기 |
- |
| layout-json-components-rendering.md |
레이아웃 JSON - 조건부/반복 렌더링 |
- |
| layout-json-components-slots.md |
레이아웃 JSON - 슬롯 시스템 |
- |
| layout-json-components.md |
레이아웃 JSON - 컴포넌트 (반복 렌더링, Blur, 생명주기, 슬롯) |
if: 조건부 렌더링 (type: "conditional" 사용 금지!) |
| layout-json-features-actions.md |
레이아웃 JSON - 초기화, 모달, 액션, 스크립트 |
- |
| layout-json-features-error.md |
레이아웃 JSON - 에러 핸들링 |
- |
| layout-json-features-styling.md |
레이아웃 JSON - 스타일 및 계산된 값 |
- |
| layout-json-features.md |
레이아웃 JSON - 기능 (에러 핸들링, 초기화, 모달, 액션) |
classMap: 조건부 CSS 클래스 (key → variants 매핑) |
| layout-json-inheritance.md |
레이아웃 JSON - 상속 (Extends, Partial, 병합) |
extends: 베이스 레이아웃 상속 (type: "slot" 위치에 삽입) |
| layout-json.md |
레이아웃 JSON 스키마 |
HTML 태그 직접 사용 금지 → 기본 컴포넌트 사용 (Div, Button, Span) |
| layout-testing.md |
그누보드7 레이아웃 파일 렌더링 테스트 가이드 |
createLayoutTest()로 테스트 헬퍼 생성, mockApi()로 API 응답 모킹 |
| modal-usage.md |
Modal 컴포넌트 사용 가이드 |
modals 섹션 모달은 openModal 핸들러로 열고, closeModal 핸들러로 닫음 |
| responsive-layout.md |
반응형 레이아웃 개발 (engine-v1.1.0+) |
responsive 속성: 컴포넌트 레벨 breakpoint 오버라이드 (권장) |
| security.md |
보안 및 검증 |
레이아웃 JSON: FormRequest + Custom Rule 10종 검증 (서버 사전 차단) |
| state-management-advanced.md |
상태 관리 - 고급 기능 |
- |
| state-management-forms.md |
상태 관리 - 폼 자동 바인딩 및 setState |
- |
| state-management.md |
전역 상태 관리 |
전역 상태: _global.속성명 (앱 전체 공유, 페이지 이동 시 유지) |
| tailwind-safelist.md |
Tailwind Safelist 가이드 |
Tailwind는 빌드 시 사용된 클래스만 CSS에 포함 |
| template-development.md |
템플릿 개발 가이드라인 |
디렉토리: templates/[vendor-template]/ (예: sirsoft-admin_basic) |
| template-handlers.md |
템플릿 전용 핸들러 |
setLocale: 앱 언어 변경 — 엔진 빌트인 (ActionDispatcher) |
| components.md |
sirsoft-admin_basic 컴포넌트 |
Basic 37개: HTML 래핑 (Div, Button, Input, Select, Form, A, ... |
| handlers.md |
sirsoft-admin_basic 핸들러 |
setLocale: 앱 언어 변경 (locale 파라미터) |
| layouts.md |
sirsoft-admin_basic 레이아웃 |
베이스: _admin_base.json (사이드바 + 헤더 + 콘텐츠 슬롯) |
| components.md |
sirsoft-basic 컴포넌트 |
Basic 26개: HTML 래핑 (Div, Button, Input, Select, Form, A, ... |
| handlers.md |
sirsoft-basic 핸들러 |
setTheme/initTheme: 다크/라이트 모드 전환 (admin과 동일 키 공유) |
| layouts.md |
sirsoft-basic 레이아웃 |
베이스: _user_base.json (헤더 + 푸터 + 모바일 네비 + 콘텐츠 슬롯) |
공통 (5개)
프로젝트 개요
프로젝트명: 그누보드7
목적: 오픈소스 CMS 플랫폼
설계 원칙: 코어 수정 최소화, 모듈화, 플러그인 시스템, 템플릿 시스템, 동적 로딩
CRITICAL RULES - 절대 금지 패턴 (DO NOT)
API/핸들러 호출
| 금지 |
올바른 사용 |
G7Core.actions.execute |
G7Core.dispatch |
G7Core.api.call |
G7Core.dispatch({ handler: 'apiCall', ... }) |
handler: "api" |
handler: "apiCall" |
handler: "nav" |
handler: "navigate" |
handler: "setLocalState" |
handler: "setState" + target: "local" |
navigate + replace: true (URL만 변경 시) |
handler: "replaceUrl" |
데이터 바인딩
| 금지 |
올바른 사용 |
{{products.data}} |
{{products?.data?.data}} (배열 경로 확인) |
{{value}} |
{{value ?? ''}} (fallback 필수) |
{{error.data}} |
{{error.errors}} (API 응답 구조) |
{{error.data?.errors ?? {}}} |
{{error.errors}} ({}}} 파서 모호성 회피) |
$value (이벤트 값) |
$event.target.value |
{{props.xxx}} (Partial) |
data_sources ID 직접 참조 |
{{$response.xxx}} (onSuccess) |
{{response.xxx}} ($ 접두사 없음) |
iteration/반복 렌더링
| 금지 |
올바른 사용 |
"item", "index" |
"item_var", "index_var" |
| iteration 내 if 순서 무시 |
if가 iteration보다 먼저 평가됨 |
컴포넌트 Props
| 금지 |
올바른 사용 |
Icon className="w-4 h-4" |
Icon size="sm" 또는 className="text-sm" |
Select valueKey/labelKey |
computed로 { value, label } 변환 |
Form 내 Button type 없음 |
type="button" 명시 (submit 방지) |
options={{options}} |
options={{options ?? []}} (fallback) |
상태 관리
| 금지 |
올바른 사용 |
| 스냅샷 기반 setState |
함수형 업데이트 또는 stateRef.current |
| closeModal 후 setState |
setState 후 closeModal (순서 중요) |
| sortable 내 폼 자동바인딩 |
parentFormContextProp={undefined} |
| await 후 캡처된 상태 사용 |
await 후 G7Core.state.getLocal() 재조회 |
setState params 키에 {{}} 사용 |
키는 정적 경로만, 배열 조작은 .map()/.filter() |
핸들러 정의
| 금지 |
올바른 사용 |
{{handler()}} (표현식에서 호출) |
actions: [{ handler: "xxx" }] |
| 금지 |
올바른 사용 |
"globalHeaders": { "X-Key": "value" } |
"globalHeaders": [{ "pattern": "*", "headers": {...} }] |
| 모든 API에 개별 headers 설정 |
globalHeaders로 공통 헤더 정의 |
| pattern 없이 헤더 정의 |
pattern 필수 (*, /api/shop/* 등) |
템플릿 엔진 내부 버전 (engine-v1.x.x)
코드와 문서에서 engine-v1.x.x 형태의 버전은 템플릿 엔진의 내부 개발 이력입니다.
그누보드7 공식 버전(config/app.php)과는 무관합니다.
- CHANGELOG:
resources/js/core/template-engine/CHANGELOG.md
- 표기법:
engine-v1.X.Y (engine- 접두사 필수, v1.X.Y 단독 사용 금지)
- 사용처: @since JSDoc, 인라인 주석, 규정 문서
엔진 CHANGELOG 반영 규칙
| 트리거 |
필수 작업 |
resources/js/core/template-engine/** 기능 추가 시 |
마이너 버전 업 (engine-v1.X+1.0) + CHANGELOG 기록 |
resources/js/core/template-engine/** 버그 수정 시 |
패치 버전 업 (engine-v1.X.Y+1) + CHANGELOG 기록 |
resources/js/core/*.ts (TemplateApp, G7CoreGlobals 등) 버그 수정 시 |
CHANGELOG [Unreleased] 또는 해당 버전에 기록 |
코드에 @since 추가 시 |
CHANGELOG 해당 버전에 항목 추가 |
| 규정 문서에 엔진 버전 표기 시 |
engine-v1.X.Y 형식 사용 |
엔진 CHANGELOG 대상 범위
엔진 CHANGELOG에 기록하는 대상은 엔진 코어 코드의 변경사항입니다:
| 포함 (엔진 코드) |
제외 (비엔진 코드) |
resources/js/core/template-engine/** |
templates/**/src/components/** (템플릿 컴포넌트) |
resources/js/core/TemplateApp.ts |
modules/**/resources/layouts/** (모듈 레이아웃) |
resources/js/core/G7CoreGlobals.ts |
resources/layouts/** (코어 레이아웃 JSON) |
resources/js/core/template-engine.ts |
docs/** (규정 문서) |
resources/js/core/types/ (엔진 타입) |
백엔드 PHP 코드 |
엔진 CHANGELOG 작성 형식
Keep a Changelog 표준:
### Added — 새 기능
### Fixed — 버그 수정
### Changed — 기존 기능 변경
### Deprecated — 곧 제거될 기능
### Removed — 제거된 기능
CHANGELOG 항목 작성 규칙
엔진 코드 수정 후 CHANGELOG 미기록 시 작업 미완료로 간주합니다.
항목 형식: - 수정 내용 요약 (수정 파일명)
패치 버전 항목 형식: - (engine-v1.X.Y) 수정 내용 (파일명)
버전 결정 기준:
| 상황 |
버전 처리 |
| 새 기능 추가 (핸들러, 속성, API) |
마이너 버전 업: engine-v1.X+1.0 |
| 기존 기능 버그 수정 |
패치 버전 업: engine-v1.X.Y+1 |
| 특정 버전에 귀속 불가한 수정 |
[Unreleased] 섹션에 기록 |
| 릴리스 시 |
[Unreleased] → [engine-v1.X.0]으로 이동 |
대규모 Fixed 섹션 카테고리 분류 (항목 10개 초과 시):
레이아웃 JSON 구현 규칙
레이아웃 작성 체크리스트
주의 사항
테스트 프로토콜
그누보드7 레이아웃 렌더링 테스트
| 특성 |
설명 |
| 테스트 환경 |
Vitest (jsdom) - 브라우저 불필요 |
| 렌더링 |
DynamicRenderer를 통한 실제 React 렌더링 |
| 유틸리티 |
createLayoutTest() - 이미 구축됨 |
| API 모킹 |
mockApi() - fetch 자동 모킹 |
| 상태 관리 |
getState(), setState() - 즉시 사용 가능 |
| 액션 트리거 |
triggerAction() - 핸들러 실행 |
테스트 작성 트리거
| 수정 대상 |
테스트 파일 위치 |
테스트 유형 |
app/Models/*.php |
tests/Unit/Models/*Test.php |
모델 메서드, 관계, 스코프 |
app/Services/*.php |
tests/Unit/Services/*Test.php |
비즈니스 로직 |
app/Enums/*.php |
tests/Unit/Enums/*Test.php |
Enum 메서드 |
app/Http/Controllers/**/*.php |
tests/Feature/**/*Test.php |
API 엔드포인트 |
database/migrations/*.php |
해당 모델/서비스 테스트에서 검증 |
스키마 변경 |
templates/**/src/components/**/*.tsx |
templates/**/__tests__/*.test.tsx |
컴포넌트 |
resources/js/core/**/*.ts |
resources/js/core/__tests__/*.test.ts |
템플릿 엔진 |
resources/layouts/**/*.json |
resources/js/core/template-engine/__tests__/layouts/*.test.tsx |
코어 레이아웃 렌더링 |
modules/**/resources/layouts/**/*.json |
modules/_bundled/{id}/resources/js/__tests__/layouts/*.test.tsx |
모듈 레이아웃 렌더링 |
templates/**/layouts/**/*.json |
templates/_bundled/{id}/__tests__/layouts/*.test.tsx |
템플릿 레이아웃 렌더링 |
기능 구현 시 전 계층 테스트
| 작업 유형 |
백엔드 (PHPUnit) |
프론트엔드 (Vitest) |
레이아웃 렌더링 (Vitest) |
| 새 화면 구현 |
API 엔드포인트 테스트 |
컴포넌트 테스트 |
레이아웃 JSON 렌더링 테스트 |
| 기존 화면 수정 |
변경된 API 테스트 |
변경된 컴포넌트 테스트 |
레이아웃 렌더링 회귀 테스트 |
| 데이터 흐름 변경 |
Service/Repository 테스트 |
상태 관리 테스트 |
데이터 바인딩 렌더링 테스트 |
Windows 환경 테스트 규칙
프론트엔드 (템플릿 디렉토리에서 실행 권장):
백엔드:
_bundled 확장 테스트 (활성 디렉토리 복사 불필요):
필수 준수 사항
상세: testing-guide.md | layout-testing.md
핵심 원칙
1. 동적 로딩
2. 코어 수정 최소화
- 모든 확장은 모듈/플러그인으로 구현
- 훅 시스템을 통한 기능 추가
- 서비스 계층에서 훅 실행
3. 계층 분리
4. Repository 인터페이스
기술 스택
백엔드
- PHP: 8.2+
- Laravel: 12.x
- 데이터베이스: MySQL 8.0
- 인증: Laravel Sanctum 4.x
- 테스트: PHPUnit 11.x
- 코드 스타일: Laravel Pint (PSR-12)
아키텍처 패턴
디렉토리 구조 개요
네이밍 규칙
| 항목 |
디렉토리명 |
네임스페이스 |
| 모듈 |
sirsoft-ecommerce |
Modules\Sirsoft\Ecommerce\ |
| 플러그인 |
sirsoft-payment |
Plugins\Sirsoft\Payment\ |
| 템플릿 |
sirsoft-admin_basic |
- |
백엔드 개발 - 핵심 요약
상세: docs/backend/ | database-guide.md
상세 규칙 (API 리소스, ServiceProvider, validation, 인증, 활동 로그 등): docs/backend/ 각 문서 참조
컨트롤러 계층
파사드 사용
프론트엔드/템플릿 시스템
상세: docs/frontend/
확장 시스템 빠른 참조
상세: docs/extension/
상세 규칙 (플러그인 의존성, 훅 시스템, 버전 동기화, 업그레이드 스텝 등): docs/extension/ 각 문서 참조
확장 타입 요약
| 타입 |
네이밍 |
네임스페이스 |
예시 |
| 모듈 |
vendor-module |
Modules\Vendor\Module\ |
sirsoft-ecommerce |
| 플러그인 |
vendor-plugin |
Plugins\Vendor\Plugin\ |
sirsoft-payment |
| 템플릿 |
vendor-template |
- |
sirsoft-admin_basic |
한국어 사용 규칙
코드 품질
Laravel Pint
PHPDoc
빌드 vs 확장 업데이트
| 수정 파일 유형 |
필요한 작업 |
*.json (레이아웃만) |
{type}:update {id} --force 실행 |
*.tsx, *.ts + *.json |
{type}:build + {type}:update {id} --force |
*.tsx, *.ts만 |
{type}:build + {type}:update {id} --force |
빌드 명령어 (Artisan)
빌드 원칙: 기본값은 _bundled 디렉토리. 빌드 결과물은 빌드 경로 내에만 남음.
활성 디렉토리 반영은 update 커맨드로만 수행. --watch 모드는 실시간 개발용으로 활성 디렉토리를 자동 사용.
확장 시스템 Artisan 명령어
SEO Artisan 커맨드
코드 스타일/마이그레이션 명령어
파일 유형별 규정 확인
파일 수정 전 해당 규정 파일을 먼저 확인합니다:
참고 파일 위치
- AbstractModule:
app/Extension/AbstractModule.php
- HookManager:
app/Extension/HookManager.php
- ModuleManager:
app/Extension/ModuleManager.php
- PluginManager:
app/Extension/PluginManager.php
- TemplateManager:
app/Extension/TemplateManager.php
- CoreStorageDriver:
app/Extension/Storage/CoreStorageDriver.php
- ResponseHelper:
app/Helpers/ResponseHelper.php
- ExtensionStatusGuard:
app/Extension/Helpers/ExtensionStatusGuard.php
- ExtensionBackupHelper:
app/Extension/Helpers/ExtensionBackupHelper.php
- ExtensionPendingHelper:
app/Extension/Helpers/ExtensionPendingHelper.php
- ExtensionRoleSyncHelper:
app/Extension/Helpers/ExtensionRoleSyncHelper.php
- ExtensionMenuSyncHelper:
app/Extension/Helpers/ExtensionMenuSyncHelper.php
- SettingsMigrator:
app/Extension/Helpers/SettingsMigrator.php
- UpgradeStepInterface:
app/Contracts/Extension/UpgradeStepInterface.php
- UpgradeContext:
app/Extension/UpgradeContext.php
- SeoRenderer:
app/Seo/SeoRenderer.php
- SeoMiddleware:
app/Seo/SeoMiddleware.php
- SeoCacheManager:
app/Seo/SeoCacheManager.php
- SeoServiceProvider:
app/Seo/SeoServiceProvider.php
- SitemapContributorInterface:
app/Seo/Contracts/SitemapContributorInterface.php
- SitemapGenerator:
app/Seo/SitemapGenerator.php
- ActivityLogChannel:
app/ActivityLog/ActivityLogChannel.php
- ActivityLogHandler:
app/ActivityLog/ActivityLogHandler.php
- ActivityLogProcessor:
app/ActivityLog/ActivityLogProcessor.php
- ResolvesActivityLogType:
app/ActivityLog/Traits/ResolvesActivityLogType.php
- ChangeDetector:
app/ActivityLog/ChangeDetector.php
- CoreActivityLogListener:
app/Listeners/CoreActivityLogListener.php