계측 축이 "목록 SELECT" 하나였고 프로파일 12종이 커맨드 파일에 하드코딩돼 있어 확장이 자기 대상을 추가할 수 없었다. 확장이 설치·제거되는 설치본마다 "실제로 존재하는 대상"이 달라지므로, 대상을 소유자가 선언하고 코어가 수집하도록 뒤집었다. - 선언 지점 두 곳, 스키마 하나: 코어 config/benchmark.php, 확장 getBenchmarkProfiles (모듈/플러그인). 수집은 method_exists 기반이라 인터페이스를 직접 구현한 서드파티 확장이 깨지지 않는다. - 축 4종(목록/화면/쓰기/배치)을 실행기로 분리하고 컨테이너 태그로 주입 — 축이 늘 때 커맨드를 고치지 않는다. - 화면 축은 HTTP 커널로 내부 요청을 처리한다. 라우트만 dispatch 하면 전역 미들웨어를 건너뛰어 화면과 다른 것을 재게 된다. 인증은 프로파일이 선언한 권한만 가진 임시 계정이 기본이며 --as 로 기존 계정을 지목할 수 있다. - 화면/쓰기 축은 계측 계정 생성부터 처리까지 롤백되는 트랜잭션 안에서 실행해 운영 DB 에도 잔여 데이터를 남기지 않는다. 배치 축은 내부 커밋·락 보유 때문에 감싸지 않고 --allow-write 로만 통제한다. - 잘못된 선언은 조용히 버리지 않고 사유를 경고로 남긴다. 버려진 선언이 곧 계측 사각이 되기 때문이다. 전부 건너뛴 실행은 종료 코드 1 로 끝난다. - 리포트는 환경 정보를 함께 적어 저장소 밖(storage/app/benchmarks)에 남긴다. 측정값이 실행 머신에 종속되므로 저장소에 축적하면 비교 불가능한 수치가 섞인다. 작업 중 발견해 함께 고친 것: - 이관 프로파일 3종의 soft_delete 선언이 실제 스키마와 어긋나 있었다 (users/product_inquiries/pages 에 deleted_at 없음). - 주문 목록이 상태 미지정 시 임시 주문 상태를 NOT IN 으로 제외하는데 선언에 빠져 있었다. filters 가 등가 비교만 지원한 것이 근본 원인이라 연산자 형태를 받도록 넓히고, 미허용 연산자는 측정 전에 거부한다. - 댓글 프로파일은 지배적 술어가 상관 서브쿼리라 선언형으로 재현할 수 없어 제거했다. 맨 테이블 스캔은 어느 화면도 내지 않는 수치가 된다. g7:bench:pagination → g7:bench 로 개명(4축을 재므로). 이전 이름은 별칭으로 남겼다. 테스트 61건 통과, 라이브 18종 전건 측정.
그누보드7 확장 시스템 개발 가이드
이 문서는 그누보드7의 확장 시스템 전체 개요와 각 상세 문서에 대한 링크를 제공합니다.
핵심 원칙
필수: /modules, /plugins 디렉토리 스캔으로 자동 발견 (composer.json 하드코딩 금지)
필수: 모든 확장 작업은 Artisan 커맨드로 수행
✅ 필수: 훅 시스템을 통한 코어 수정 최소화
확장 시스템 개요
G7은 동적 로딩 기반의 확장 시스템을 제공합니다:
- 모듈: 독립적인 비즈니스 기능 단위 (예: 이커머스, 블로그)
- 플러그인: 특정 기능 확장 (예: 결제, 배송)
- 템플릿: UI 렌더링 및 레이아웃 정의 (Admin, User)
- 훅 시스템: 코어 수정 없이 로직 확장
문서 구조
훅 시스템
| 문서 | 설명 |
|---|---|
| hooks.md | Action/Filter Hook, 리스너 구현, 우선순위 |
모듈 개발
| 문서 | 설명 |
|---|---|
| module-basics.md | AbstractModule, 디렉토리 구조, 네이밍 규칙 |
| module-routing.md | API/Web 라우트, 자동 Prefix, routes.json |
| module-layouts.md | 레이아웃 등록, 오버라이드, 상속 |
| module-commands.md | Artisan 커맨드 (install, activate, uninstall) |
| module-i18n.md | 백엔드/프론트엔드 다국어 분리 |
레이아웃 확장
| 문서 | 설명 |
|---|---|
| layout-extensions.md | 동적 UI 주입 (Overlay, Extension Point), 템플릿 오버라이드 |
플러그인 개발
| 문서 | 설명 |
|---|---|
| plugin-development.md | PluginInterface, 격리성, 의존성 원칙 |
확장 관리자
| 문서 | 설명 |
|---|---|
| extension-manager.md | Composer 오토로드, 서비스 등록, hidden 필터링 |
학습용 샘플
| 문서 | 설명 |
|---|---|
| sample-extensions.md | 학습용 최소 샘플 확장 4종 (gnuboard7-hello_*) — 계층 1:1 비교 레퍼런스 |
템플릿 시스템
| 문서 | 설명 |
|---|---|
| template-basics.md | Admin/User 템플릿, 메타데이터, 버전 히스토리 |
| template-routing.md | 라우트 정의, 언어 파일 경로 규칙 |
| template-security.md | API 서빙, 파일 확장자 화이트리스트 |
| template-caching.md | 캐시 계층, 무효화 전략 |
| template-commands.md | Artisan 커맨드 (install, activate) |
권한 및 메뉴 시스템
| 문서 | 설명 |
|---|---|
| permissions.md | Role, Permission, 자동 관리 |
| menus.md | 메뉴 권한, 시더 |
확장 타입별 네이밍 규칙
| 타입 | 디렉토리명 | 네임스페이스 | Composer 경로 |
|---|---|---|---|
| 모듈 | vendor-module |
Modules\Vendor\Module\ |
modules/vendor-module |
| 플러그인 | vendor-plugin |
Plugins\Vendor\Plugin\ |
plugins/vendor-plugin |
| 템플릿 | vendor-template |
- | templates/vendor-template |
예시:
- 모듈:
sirsoft-ecommerce→Modules\Sirsoft\Ecommerce\ - 플러그인:
sirsoft-payment→Plugins\Sirsoft\Payment\ - 템플릿:
sirsoft-admin_basic
훅 네이밍 규칙
[vendor-module].[entity].[action]_[timing]
타이밍 접미사:
before_*: 작업 실행 전after_*: 작업 실행 후on_*: 특정 이벤트 발생 시filter_*: 데이터 필터링
예시:
sirsoft-ecommerce.product.before_create
sirsoft-ecommerce.product.after_update
sirsoft-ecommerce.product.filter_create_data
sirsoft-ecommerce.order.on_payment_success
주요 Artisan 커맨드
모듈 관련
php artisan module:list # 모듈 목록 조회
php artisan module:install [identifier] # 모듈 설치
php artisan module:activate [identifier] # 모듈 활성화
php artisan module:deactivate [identifier] # 모듈 비활성화
php artisan module:uninstall [identifier] # 모듈 제거
php artisan module:cache-clear # 모듈 캐시 정리
템플릿 관련
php artisan template:list # 템플릿 목록 조회
php artisan template:install [identifier] # 템플릿 설치
php artisan template:activate [identifier] # 템플릿 활성화
php artisan template:deactivate [identifier] # 템플릿 비활성화
php artisan template:uninstall [identifier] # 템플릿 제거
php artisan template:cache-clear # 템플릿 캐시 정리
확장 관리자
php artisan extension:update-autoload # Composer 오토로드 업데이트
빠른 시작 가이드
새 모듈 개발 시
- module-basics.md - 기본 구조 이해
- module-routing.md - 라우트 설정
- module-i18n.md - 다국어 지원
- module-layouts.md - 레이아웃 등록 (필요시)
- hooks.md - 훅 리스너 구현 (필요시)
새 플러그인 개발 시
- plugin-development.md - 플러그인 구조 이해
- hooks.md - 훅 리스너 구현
템플릿 커스터마이징 시
- template-basics.md - 템플릿 타입 이해
- template-routing.md - 라우트/언어 파일
- template-security.md - 보안 규칙
관련 문서
- AGENTS.md - 프로젝트 개발 가이드
- backend/ - 백엔드 개발 가이드
- frontend/ - 프론트엔드 개발 가이드
- database-guide.md - 데이터베이스 가이드