코드에만 존재하던 REST API 계약(약 663 엔드포인트)을 코어/확장 책임별로
분리된 마크다운 레퍼런스로 전면 문서화한다. 674개 규모에서 수기 문서는
반드시 drift 하므로 "코드 추출 → 스캐폴딩 → 사람이 서술 채움 → 하네스가
커버리지 강제" 하이브리드로 구성했다.
추출 파이프라인 (app/Support/ApiDoc):
- ApiRouteInventory / FormRequestIntrospector / ApiEndpointProbe(실측 HTTP) /
ResponseSchemaInferrer / ApiDocScaffolder / ColumnCommentResolver /
ResourceFieldDescriber / ParameterDescriber
- api:docgen 커맨드(--scope/--seed/--check/--dry-run/--base-url/--user) +
응답/파라미터 in-place 백필 커맨드 2종(재생성 없이 TODO 셀만 치환, 멱등)
- ApiDocSampleSeeder 계약 + 코어/확장 시더로 실측용 완전 샘플 멱등 생성
문서화 (실측 기반, GET read-only 실호출):
- 코어 291엔드포인트 35파일(docs/backend/api) + 규정 docs/backend/api-documentation.md
- 확장: ecommerce(231)·board(80)·page(17)·hello_module(2)·pay_kginicis(22)·
gdpr(15)·ckeditor5(2)·marketing(2)·verification_kginicis(1)
- 표준 4구성(헤더·요청 파라미터·응답 필드·에러 표) + 엔드포인트 용도 서술
- 파라미터 용도·응답 필드 설명 셀 전수 채움(도메인 지식 수기)
하네스:
- audit 룰 api-doc-coverage — API 표면(라우트/컨트롤러/FormRequest/Resource)
변경 시 대응 문서 미동반이면 차단. 전 대상 문서 완비로 error 승격
- file-rules 리마인더(컨트롤러/라우트 편집 시), coverage.json, dev-dashboard 카드
- docs/backend/routing.md 확장 공개 API URL 스킴 정정(/api/modules|plugins/{id})
- /AGENTS.md/docs-index 동기
72 lines
2.0 KiB
PHP
72 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Support\ApiDoc;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
/**
|
|
* 컬럼 주석 해석기
|
|
*
|
|
* 모델 테이블의 컬럼 주석(한국어 comment) 을 조회해 응답 필드 설명의 기본값으로
|
|
* 제공합니다. G7 은 마이그레이션 한국어 comment 를 필수화하므로, 이 주석이 필드
|
|
* 설명의 SSoT 가 됩니다. 정적 스키마 조회이므로 실측 없이도 동작합니다.
|
|
*/
|
|
class ColumnCommentResolver
|
|
{
|
|
/**
|
|
* @var array<string, array<string, string>> 테이블별 컬럼 주석 캐시
|
|
*/
|
|
private array $cache = [];
|
|
|
|
/**
|
|
* 모델 테이블의 컬럼명 => 주석 맵을 반환합니다.
|
|
*
|
|
* @param class-string|null $modelClass 모델 FQCN
|
|
* @return array<string, string> 컬럼명 => 주석
|
|
*/
|
|
public function forModel(?string $modelClass): array
|
|
{
|
|
if (! $modelClass || ! class_exists($modelClass) || ! is_subclass_of($modelClass, Model::class)) {
|
|
return [];
|
|
}
|
|
|
|
try {
|
|
$table = (new $modelClass)->getTable();
|
|
} catch (\Throwable) {
|
|
return [];
|
|
}
|
|
|
|
return $this->forTable($table);
|
|
}
|
|
|
|
/**
|
|
* 테이블의 컬럼명 => 주석 맵을 반환합니다 (캐시).
|
|
*
|
|
* @param string $table 테이블명
|
|
* @return array<string, string> 컬럼명 => 주석
|
|
*/
|
|
public function forTable(string $table): array
|
|
{
|
|
if (isset($this->cache[$table])) {
|
|
return $this->cache[$table];
|
|
}
|
|
|
|
$map = [];
|
|
|
|
try {
|
|
foreach (Schema::getColumns($table) as $column) {
|
|
$comment = $column['comment'] ?? null;
|
|
|
|
if (is_string($comment) && $comment !== '') {
|
|
$map[$column['name']] = $comment;
|
|
}
|
|
}
|
|
} catch (\Throwable) {
|
|
// 테이블 부재/드라이버 미지원 시 빈 맵
|
|
}
|
|
|
|
return $this->cache[$table] = $map;
|
|
}
|
|
}
|