Files
Gnuboard7/docs/extension/changelog-rules.md
T
HeuJung b505ac7ba7 fix(core,board,ecommerce,page,gdpr): 목록 컨텍스트 왕복·엔진 렌더 파이프 결함 일괄 수정 + 공개문서 정리
세 갈래의 결함을 한 브랜치에서 정리한다.

## 목록 컨텍스트 왕복 시 URL 상태 소실 ( @jiwonpapa 님께서 제보해주셨습니다.)

목록에서 상세·형제 상세(이전/다음)·작성/수정 폼에 다녀오면 보고 있던
page/search/category/filters 가 사라지던 문제를 전 도메인에서 수정했다.

- 엔진(engine-v1.54.2): `mergeQuery: true` 만 적고 `query` 를 생략하면 병합이
 통째로 건너뛰어지던 함정을 교정 — `ActionDispatcher.handleNavigate`/`handleReplaceUrl`.
- 게시판·이커머스·페이지·회원·마이페이지·gdpr 등 9개 확장 레이아웃의 왕복 leg 전수
 적용(mergeQuery: true). 의도적 리셋(검색/필터 초기화·탭 전환·프리셋)은 면제 주석으로 구분.
- 무한스크롤 목록(브랜드·상품 공통정보·고시정보)의 새로고침이 URL 검색·정렬을 떨구던
 결함 수정.
- 재발 차단: audit 룰 `layout-list-context-navigate-merge-query`(목록 클러스터 자동 도출,
 page/필터 URL 신호 4종) + `layout-navigate-path-absolute`(navigate path 동작 키워드 금지).

## cellChildren 등 반복 렌더에서 단일 바인딩 파이프 미적용 ( @glitter-gim 님께서 제보해주셨습니다.)

목록 표의 각 칸에 넣은 날짜·숫자 서식(`{{row.x | datetime(...)}}`)이 빈 값이 되거나
서식 없는 원본으로 나오던 문제를, 표현식 판정 로직이 엔진 전역에 복제되며 갈라진
구조적 결함으로 진단하고 판정 경로를 단일화했다(engine-v1.54.3).

- `RenderHelpers`(renderItemChildren·evaluateIfCondition)·`ConditionEvaluator`·
 `DataBindingEngine.resolveObject`·`DynamicRenderer` props 5곳에 단일 바인딩 파이프 분기 추가.
- 계획: `g7-scalable-lobster.md`(렌더 경로 비대칭 결함 일괄 수정).

## 공개 문서 내부 도구 귀속 제거

release 에 포함되는 공개 문서(`docs/**`)에서 내부 audit 룰 ID 귀속 서술을
도구 비귀속 표현("정적 검사")으로 정리. 재발 차단 룰 `public-no-internal-audit-reference` 신설.

전 계층 테스트(PHPUnit·Vitest·Playwright)·회귀 테스트 동반, 버전/CHANGELOG/활성 디렉토리 동기 완료.
2026-07-26 15:17:56 +09:00

12 KiB

Changelog 규칙 (Changelog Rules)

코어 및 확장(모듈, 플러그인, 템플릿)의 변경사항을 CHANGELOG.md에 기록하는 규정

TL;DR (5초 요약)

1. 확장/코어 버전 업 시 CHANGELOG.md에 변경사항 기록 필수 (미기록 시 버전 업 불가)
2. 형식: Keep a Changelog 표준 (## [버전] - 날짜 / ### 카테고리 / - 항목)
3. 허용 카테고리: Added, Changed, Deprecated, Removed, Fixed, Security
4. 확장 위치: 각 확장의 루트 디렉토리 (modules/_bundled/vendor-module/CHANGELOG.md)
5. 코어 위치: 프로젝트 루트 /CHANGELOG.md (코어 버전 변경 시 필수)

목차

  1. CHANGELOG.md 작성 규칙
  2. 카테고리 정의
  3. 파일 위치
  4. ChangelogParser 헬퍼
  5. API 엔드포인트
  6. 관리 화면 표시
  7. 템플릿 예시
  8. 코어 버전 제약 정책
  9. 다국어 파일 변경과 CHANGELOG

1. CHANGELOG.md 작성 규칙

필수 사항

확장 버전 업 시 CHANGELOG.md에 변경사항 기록 필수
미기록 시 버전 업 작업 불완전으로 간주
릴리스 태깅 전 composer test-smoke 통과 필수 (Installation 스위트)
  • 형식: Keep a Changelog 표준 준수
  • 버전 관리: Semantic Versioning 준수
  • 작성 언어: 한국어 (확장 대상이 한국어 사용자)
  • 날짜 형식: YYYY-MM-DD (ISO 8601)
  • 최신 버전: 파일 상단에 위치 (역순)

릴리스 전 Smoke Suite 통과

코어 또는 번들 확장의 버전 bump 시 다음을 충족해야 합니다:

# 릴리스 전 필수 검증
composer test-smoke

# 첫 실패에서 중단 (CI 모드)
composer test-smoke-ci
  • composer test-smoke는 tests/Feature/Installation/ 및 각 번들 확장의 tests/Feature/Installation/ 디렉토리를 실행합니다.
  • 스모크 통과 없이 릴리스 태깅을 진행하면 beta.2 #12 유형(마이그레이션–Repository 결합 누락) 회귀를 놓칠 수 있습니다.
  • 상세: testing-guide.md#pre-release-smoke-suite

버전 섹션 형식

## [버전] - YYYY-MM-DD

예: ## [0.1.2] - 2026-02-25

항목 형식

### 카테고리
- 변경사항 설명

2. 카테고리 정의

카테고리 설명 사용 시점
Added 새 기능 추가 새로운 기능, 화면, API 엔드포인트 추가
Changed 기존 기능 변경 기존 동작 수정, 성능 개선, UI 변경
Deprecated 향후 제거 예정 향후 삭제될 기능 경고
Removed 기능 제거 기존 기능/API 삭제
Fixed 버그 수정 기존 버그, 오류 수정
Security 보안 취약점 수정 보안 관련 수정

3. 파일 위치

확장 (모듈/플러그인/템플릿)

modules/_bundled/vendor-module/CHANGELOG.md     # 모듈 (예: sirsoft-board)
plugins/_bundled/vendor-plugin/CHANGELOG.md     # 플러그인 (예: sirsoft-tosspayments)
templates/_bundled/vendor-template/CHANGELOG.md # 템플릿 (예: sirsoft-admin_basic)
  • _bundled 디렉토리에서 작업 (활성 디렉토리 직접 수정 금지)
  • 업데이트 프로세스를 통해 활성 디렉토리로 복사

코어

/CHANGELOG.md                                   # 프로젝트 루트
  • 코어 버전 변경 시 CHANGELOG.md에 변경사항 기록 필수 (미기록 시 버전 업 불가)
  • 확장과 동일한 Keep a Changelog 형식 사용
  • 코어 버전 변경 대상 파일: config/app.php, .env.example, .env.testing
  • 버전 변경 시 반드시 CHANGELOG.md에 해당 버전 섹션 추가 후 버전 파일 수정

4. ChangelogParser 헬퍼

파일: app/Extension/Helpers/ChangelogParser.php

주요 메서드

메서드 설명 반환
parse(string $filePath) CHANGELOG.md 전체 파싱 array (버전별 구조화 배열)
getVersionRange(string $filePath, string $from, string $to) 특정 범위 엔트리 추출 array (from 초과 ~ to 이하)
resolveChangelogPath(string $basePath, string $identifier, ?string $source) 소스별 경로 결정 ?string

반환 형식

[
  [
    'version' => '0.1.2',
    'date' => '2026-02-25',
    'categories' => [
      ['name' => 'Added', 'items' => ['새 기능 A']],
      ['name' => 'Fixed', 'items' => ['버그 B 수정']],
    ],
  ],
]

5. API 엔드포인트

GET /api/admin/modules/{identifier}/changelog
GET /api/admin/plugins/{identifier}/changelog
GET /api/admin/templates/{identifier}/changelog

쿼리 파라미터

파라미터 설명 기본값
source CHANGELOG.md 읽을 위치 active
from_version 이 버전 초과 항목만 반환 -
to_version 이 버전 이하만 반환 -

사용 시나리오

  • 상세 모달: GET .../changelog (전체 조회)
  • 업데이트 모달: GET .../changelog?source=bundled&from_version=0.1.1&to_version=0.1.2 (변경분)

6. 관리 화면 표시

업데이트 모달

  • 전역 상태: _global.updateChangelog (3개 확장 타입 공통)
  • 표시 조건: updateChangelog && updateChangelog.length > 0
  • 표시 위치: 버전 정보 아래, 외부 링크(github_changelog_url) 위
  • 스타일: blue 배경 (bg-blue-50 dark:bg-blue-900/20)
  • 우선순위: 인라인 changelog > 외부 링크 (둘 다 있으면 둘 다 표시)

상세 모달

  • 전역 상태: _global.moduleChangelog, _global.pluginChangelog, _global.templateChangelog (타입별)
  • 섹션 ID: changelog_section
  • 아이콘: clock-rotate-left
  • empty state: _global.xxxChangelog가 비어있으면 "변경 내역 정보가 없습니다." 표시

메인 리스트 액션 흐름

# 업데이트 버튼 클릭 시:
setState(selectedX) → apiCall(changelog?source=bundled&from_version=...&to_version=...)
  → onSuccess: setState(updateChangelog) + openModal(update_modal)
  → onError: setState(updateChangelog=[]) + openModal(update_modal)

# 상세 보기 버튼 클릭 시:
setState(selectedX) → apiCall(changelog)
  → onSuccess: setState(xChangelog) + openModal(detail_modal)
  → onError: setState(xChangelog=[]) + openModal(detail_modal)

7. 템플릿 예시

새 확장을 만들 때 아래 템플릿을 사용합니다:

# Changelog

이 프로젝트의 모든 주요 변경사항을 기록합니다.
형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며,
[Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다.

## [0.1.0] - YYYY-MM-DD

### Added
- 초기 기능 구현

8. 코어 버전 제약 정책

확장 manifest(module.json, plugin.json, template.json)의 g7_version 과 dependencies.{modules|plugins} 버전 제약 작성 규칙.

표기 규칙

  • 형식: >=X.Y.Z[-prerelease] 통일 (공백 없음). 예: >=7.0.0-beta.2, >=1.0.0-beta.2
  • 캐럿(^), 틸드(~), 엄격 일치(=) 사용 금지
  • placeholder 금지: 실존하지 않는 버전(0.1.0, 0.0.1 등) 을 적어 사실상 "아무 버전이나 허용" 상태로 두지 않음

g7_version — 코어 최소 요구 버전

  • 확장이 실제로 의존하는 코어 API/기능의 최초 도입 버전을 최소값으로 기재
  • 확장 version 이 bump 될 때 g7_version 재검토 필수
  • 번들 확장은 일반적으로 코어의 현재 릴리스와 같은 단계(beta.X, rc.X, X.Y.Z)를 하한으로 둠
  • 예: 알림 시스템 3계층(NotificationDefinition/Template) 을 사용하는 모듈은 최소 >=7.0.0-beta.2

dependencies.{modules|plugins} — 확장 간 버전 제약

  • A 확장이 B 확장의 공개 Service/Contract/Model/Route/훅을 사용한다면 dependencies.{type}.B: ">=X.Y.Z" 기재
  • B 에서 공개 표면이 변경되거나 새 API 가 도입되어 A 가 그것을 소비하게 되면 A 의 최소 버전 제약을 그 API 최초 도입 버전으로 상향
  • 실존하지 않는 placeholder 버전(>=0.1.0 등)은 금지 — 버전 게이팅 무효화 유발

버전 제약 재검토 트리거

다음 이벤트 발생 시 관련 확장 manifest 를 전수 재검토한다.

이벤트 재검토 대상
코어 공개 확장 표면 변경 (AbstractModule/AbstractPlugin/HookManager/Contracts 등) 모든 번들 확장의 g7_version
코어 minor/major/beta 번호 변경 번들 확장 전체 g7_version
번들 모듈/플러그인의 공개 Service/Contract/Model/Route/훅/CHANGELOG 변경 해당 확장을 dependencies 에 선언한 모든 확장

CHANGELOG 기재

  • g7_version 상향: ### Changed 에 - 코어 최소 요구 버전을 X.Y.Z 로 상향
  • dependencies.{id} 상향: ### Changed 에 - {id} 의존성 버전 제약을 실제 릴리스 버전에 맞춰 정비 또는 - {id} 최소 버전을 X.Y.Z 로 상향 (변경 이유에 따라)

9. 다국어 파일 변경과 CHANGELOG

호스트(코어/모듈/플러그인/템플릿)의 다국어 파일을 변경하면 그 호스트의 CHANGELOG 에도 사용자 관점 항목을 기재한다.

다국어 변경은 대부분 사용자가 화면에서 읽는 문장의 변경이다.

변경 유형 사용자에게 보이는 결과
누락 키 추가 원문 키(sirsoft-ecommerce::messages.settings.fetch_success)가 그대로 보이던 화면이 정상 문구로 바뀐다
문구 정정 잘못된 안내(예: 실제 입력 한도와 다른 글자 수)가 고쳐진다
오탈자 정정 화면 용어가 바뀐다

이들 변경은 diff 상 lang/ 아래에만 남아 CHANGELOG 를 쓰는 시점에 눈에 띄지 않는다. 실제로 이슈 #78 에서 코어·이커머스·게시판·kginicis 4개 호스트의 문구 수정이 기록 없이 누락됐고, 그중에는 로그인/역할 권한 거절 응답에 원문 키가 노출되던 사용자 관점 결함도 있었다.

기재 예시

### Fixed

- 일부 안내가 실제 문장 대신 내부 식별자로 표시되던 문제를 수정했습니다. 로그인하지 않았거나 역할 권한이 없어 요청이 거절될 때가 해당됩니다.

면제

사용자에게 노출되지 않는 문구(내부 커맨드 출력, 테스트 픽스처 등)는 변경 파일 상단에 사유와 함께 면제 주석을 둔다.

// changelog:allow 개발용 Artisan 커맨드 출력 문구 — 사용자 화면 비노출

자동 검증

정적 검사가 다음 두 가지를 본다.

  • 변경셋에 호스트 lang 파일이 있는데 그 호스트 CHANGELOG 가 없으면 경고한다.
  • 같은 레벨의 중복 배열 키는 차단한다. 뒤 선언이 앞을 덮어 앞 블록 전용 키가 런타임에 소실되고 원문 키가 노출되기 때문이다. 정정은 항상 두 블록 병합 — 한쪽만 삭제하면 그쪽 키가 사라진다.

언어팩 패키지(lang-packs/_bundled/**)는 별도 검사가 담당하므로 본 절의 대상이 아니다.


관련 파일

  • app/Extension/Helpers/ChangelogParser.php — Changelog 파서
  • app/Http/Requests/Extension/ChangelogRequest.php — FormRequest 검증
  • app/Http/Controllers/Api/Admin/ModuleController.php — changelog() 메서드
  • app/Http/Controllers/Api/Admin/PluginController.php — changelog() 메서드
  • app/Http/Controllers/Api/Admin/TemplateController.php — changelog() 메서드
  • app/Services/ModuleService.php — getModuleChangelog() 메서드
  • app/Services/PluginService.php — getPluginChangelog() 메서드
  • app/Services/TemplateService.php — getTemplateChangelog() 메서드