Files
Gnuboard7/docs/backend
HeuJung 0c4f52fc96 fix(core): 업데이트 트리 argv 판정을 명령줄 SAPI 로 한정하고 매니페스트 삭제 실패를 로그에 남김
7.0.11 인스톨러·코어 업데이트 변경(e60a82d73)에 대해 과거 회귀 22건을 부류별로 대조한
결과, 신규 노출면 1건과 테스트 위생 1건이 나와 인터뷰 결정대로 조치했다.

1. argv 채널의 SAPI 게이트 — CGI/FPM 은 register_argc_argv=On 이면 $_SERVER['argv'] 를
 쿼리스트링을 '+' 로 쪼개 채우므로(`GET /?x+core:update` → argv[1]==='core:update', php-cgi
 실측) 비인증 웹 요청이 업데이트 트리로 판정되어 bootstrap/app.php 자가 치유가 요청마다
 패키지 매니페스트를 지우고 다시 만들었다. CoreUpdateContext 와 bootstrap/app.php 복제본
 모두 argv 를 cli·phpdbg 에서만 읽는다. env 플래그 채널은 웹에서 주입할 수 없으므로 그대로
 두어 웹 요청 안에서 시작하는 업데이트 흐름(7.1.0)에 영향이 없다. 동형성 테스트에 SAPI 축을
 더했다.

2. 매니페스트 삭제 실패 기록 — PackageManifestCacheHelper::clear 가 지우지 못한 파일의
 경로를 돌려주고, spawn 직전 호출부가 업그레이드 로그·콘솔에 경고로 남긴다. 권한·소유권
 불일치면 자식의 자가 치유도 같은 이유로 실패해 증상은 제보와 같은 「Class not found」 인데,
 이 경고가 원인이 권한이라는 유일한 흔적이다.

3. 테스트 격리 — tests/bootstrap.php 가 APP_PACKAGES_CACHE/APP_SERVICES_CACHE 를 테스트
 전용 경로로 돌린다. proc_open 으로 자식을 띄우는 기존 테스트 2종의 자식이 개발 클론의
 실제 bootstrap/cache 매니페스트를 지우고 다시 쓰던 것(stat 실측)을 부모·자식 함께 막는다.

관리자 [시스템 최적화] 경로(withPreservedContainer 파사드 복원의 미실측 형제 호출처)는
임시 설치본에서 API 로 실측했다 — 200, 설정·라우트 캐시 재생성, 후속 요청 200, 로그 오류 0.

4. 트러블슈팅 사례 ↔ 회귀 테스트 앵커 계약 — 신규 사례는 헤딩에 <!-- case:{영역}-{번호} -->
 앵커를 달고 같은 문자열을 그 사례를 잠그는 회귀 테스트에도 남겨야 한다. 사례 번호는
 문서마다 1부터 재시작하고 병합으로 중복되므로(이번 리베이스에서도 우리 사례가 develop 과
 같은 29 였다가 31 로 밀렸다), 개수만 대조하면 다른 사례를 덮는 테스트도 초록이 된다.

 그런데 판정기 check-troubleshooting-test-coverage.cjs 를 부르는 지점이 저장소에 하나도
 없었다 — 스크립트 자체 주석에만 실행법이 적혀 있어 아무도 부르지 않으면 영원히 돌지
 않았고, 그 사이 위반이 9건 쌓였다(backend 26~31, cache 17~19). 돌지 않는 대조는 아무것도
 잠그지 못하므로 위반 해소와 실행 지점 부여를 함께 한다.

 9건 전부에 앵커를 부착하고(각 사례가 선언한 회귀 테스트 중 가장 구체적인 파일에 배치,
 한 파일이 두 사례에 선언된 경우는 갈라 배치), stop-guard 7.2 에 앵커 계약 + 미커버
 baseline ratchet 두 축으로 등록했다. 트러블슈팅 사례 추가 프로토콜에 6단계를
 더하고 coverage 에 troubleshooting-case-anchor-contract(manual-only, 전용 판정기 위임)를
 등재했다. 판정기 종료코드 1 → 0, 미커버 건수는 전 문서 baseline 그대로다.
2026-09-08 10:42:19 +09:00
..
2026-04-01 10:30:52 +09:00
2026-04-01 10:30:52 +09:00
2026-05-11 11:29:41 +09:00
2026-05-11 11:29:41 +09:00
2026-04-01 10:30:52 +09:00
2026-04-20 20:37:49 +09:00
2026-05-11 11:29:41 +09:00

백엔드 개발 가이드

그누보드7 백엔드 개발을 위한 종합 가이드입니다.


핵심 원칙

필수: FormRequest + Custom Rule 사용 (Service에 검증 로직 금지)
필수: FormRequest + Custom Rule 패턴 사용
✅ 필수: __() 함수를 사용한 다국어 처리
✅ 필수: 상태/타입/분류는 Enum으로 정의

API 레퍼런스

엔드포인트별 요청 파라미터·응답 필드·요청/응답 예시는 api/README.md 에 있습니다. 공통 규약(Bearer 토큰 인증, 응답 봉투, 페이지네이션, 401/403/422/428 에러)도 그 문서 상단에 정리되어 있습니다. 확장(모듈·플러그인)이 소유한 API 문서 목록도 같은 문서에서 찾을 수 있습니다.

문서 작성·갱신 규정은 api-documentation.md 를 참고하세요.


문서 목록

문서 제목 핵심 내용
activity-log-hooks.md 활동 로그 훅 레퍼런스 (Activity Log Hooks Reference) 코어 66훅 + 확장 132훅 = 총 198훅 (확장별 목록은 그 확장이 소유)
activity-log.md 활동 로그 시스템 (Activity Log System) Monolog 기반: Service 훅 → Listener → Log::channel...
admin-settings-access.md Admin 환경설정 값 접근 (g7_core_settings vs config()) 동기화 SSoT: storage/app/settings/*.json → Setting...
api-documentation.md API 레퍼런스 문서 규정 (API Documentation) 모든 API 엔드포인트는 레퍼런스 문서 필수 — 메서드/URI/파라미터/응답 필드 +...
api-resources.md API 리소스 Resource: BaseApiResource 상속 필수 / Collection: B...
authentication.md 인증 및 세션 처리 Laravel Sanctum 토큰 전용 인증 (Bearer 토큰만 사용)
benchmark.md 성능 계측 시스템 (Benchmark) g7:bench 가 4축(list/screen/write/batch)을 잰다 — ...
broadcasting.md Broadcasting (실시간 이벤트) Laravel Reverb 사용 (WebSocket)
console-confirm.md 콘솔 yes/no 프롬프트 (ConsoleConfirm) 콘솔 커맨드의 yes/no 프롬프트는 $this->unifiedConfirm() 사용...
controllers.md 컨트롤러 계층 구조 AdminBaseController / AuthBaseController / Publ...
core-config.md 코어 설정 (config/core.php) config/core.php = 코어 권한/역할/메뉴/메일템플릿의 SSoT (Sing...
core-update-system.md 코어 업데이트 시스템 (Core Update System) 코어 업그레이드 스텝: upgrades/ 디렉토리 (프로젝트 루트), 네임스페이스 A...
data-sync-helpers.md 데이터 동기화 Helper (Data Sync Helpers) 모든 데이터 동기화는 Service/Seeder 가 Helper 를 호출해 수행 (직...
dto.md DTO (Data Transfer Object) 사용 규칙 DTO 두 패턴 — Value Object(불변 1회 전달) vs Data Carri...
enum.md Enum 사용 규칙 상태/타입/분류 = Enum 필수 (PHP 8.1+ Backed Enum)
exceptions.md Custom Exception 다국어 처리 예외 메시지 하드코딩 금지 → __() 함수 필수
geoip.md GeoIP 시스템 (MaxMind GeoLite2) MaxMind GeoLite2-City DB 기반 IP → 타임존 감지 (SetTim...
identity-messages.md 본인인증 메시지 템플릿 시스템 (Identity Messages) 알림 시스템(notification_*)과 완전 분리된 IDV 전용 템플릿 인프라
identity-policies.md 본인인증 정책 시스템 (Identity Policies) -
identity-providers.md IDV Provider 작성 가이드 (Identity Verification Providers) VerificationProviderInterface 구현 + IdentityProv...
language-pack-service.md LanguagePackService (백엔드 Service 레이어) LanguagePackService 가 install/activate/deactiva...
middleware.md 미들웨어 등록 규칙 인증 필요 미들웨어 → 전역 등록 금지!
notification-system.md 알림 시스템 (Notification System) GenericNotification 범용 클래스 1개로 모든 알림 처리 (개별 클래스...
pagination.md 대용량 목록 페이지네이션 (Pagination) 총 건수만 상한을 받는다 — 상한 이하면 정확, 초과면 "이상"(total_relat...
response-helper.md API 응답 규칙 (ResponseHelper) 모든 API 응답은 ResponseHelper 사용
reverse-proxy.md 리버스 프록시 환경 (Reverse Proxy) 프록시 뒤에서는 요청이 스스로 스킴·IP 를 증명하지 못한다 — 신뢰할 프록시를 지정...
routing.md 라우트 네이밍 및 경로 모든 라우트는 name() 필수: ->name('api.users.index')
search-system.md Scout 검색 엔진 시스템 (Search System) Laravel Scout + DatabaseFulltextEngine: MySQL F...
seo-system.md SEO 페이지 생성기 시스템 (SEO Page Generator) SeoMiddleware: 봇 요청 감지 → ?locale= 파라미터 해석 → Seo...
service-provider.md 서비스 프로바이더 안전성 DB 접근 전 .env 파일 존재 확인 필수
service-repository.md Service-Repository 패턴 RepositoryInterface 주입 필수 (구체 클래스 직접 주입 금지)
settings-multilingual-enrichment.md Settings 카탈로그 다국어 자동 보강 settings JSON 의 다국어 카탈로그 라벨(_cached_name 등)은 카탈...
static-asset-publishing.md 부트스트랩 리소스 정적 게시 (Static Asset Publishing) 게시물: public/build/ext/{cache_version}/ — 수명주기 이...
translatable-seeders.md 다국어 시더 인터페이스 (Translatable Seeders) 다국어 JSON 컬럼(name 등)을 시드하는 확장 entity 시더는 Transla...
user-overrides.md 사용자 수정 보존 (HasUserOverrides Trait) 모델에 use HasUserOverrides; + `protected array ...
validation.md 검증 (Validation) 필수: FormRequest에서 검증 (Service에 검증 로직 배치 금지)

아키텍처 개요

계층 분리

Controller → Request → Service → Repository → Model

컨트롤러 계층 구조

BaseApiController (최상위)
├── AdminBaseController (관리자 전용)
├── AuthBaseController (인증된 사용자)
└── PublicBaseController (공개 API)

Service-Repository 패턴

// Service에서 훅 실행
HookManager::doAction('module.entity.before_create', $data);
$data = HookManager::applyFilters('module.entity.filter_data', $data);
$result = $this->repository->create($data);
HookManager::doAction('module.entity.after_create', $result);

파사드 사용 규칙

// ✅ DO: 파사드 앞 역슬래시 제거
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;

Log::info('메시지');
Auth::user();

// ❌ DON'T: 역슬래시 사용
\Log::info('메시지');
auth()->user();

핵심 규칙 요약

1. 검증 로직 위치

  • ❌ Service 클래스에서 검증 금지
  • ✅ FormRequest에서 기본 검증
  • ✅ Custom Rule에서 복잡한 검증

2. 다국어 처리

  • ❌ 하드코딩된 메시지 금지
  • ✅ __() 함수 사용 필수
  • ✅ lang/ko/, lang/en/ 파일 관리

3. Enum 사용

  • ❌ 문자열/숫자 상수 직접 사용 금지
  • ✅ Backed Enum 정의
  • ✅ 타입 힌트 활용

4. 미들웨어 등록

  • ❌ 인증이 필요한 미들웨어를 글로벌 등록 금지
  • ✅ 그룹별 적절한 위치에 등록
  • ✅ 실행 순서 고려

5. 서비스 프로바이더 안전성

  • ❌ .env 없이 실패하는 코드 금지
  • ✅ 환경 검증 후 로직 실행
  • ✅ 인스톨러 안정성 확보

6. 외부 HTTP 호출

  • ❌ file_get_contents($url) / fopen($url, ...) / stream_context_create([...]) 로 원격 URL 직접 호출 금지
  • ✅ Illuminate\Support\Facades\Http (Laravel Http 파사드) 사용
  • ✅ GitHub 연동은 App\Extension\Helpers\GithubHelper 재사용
  • 이유: 공유 호스팅은 allow_url_fopen=Off 설정인 경우가 많아 URL 스트림 래퍼 기반 호출이 전부 실패합니다. Http 파사드는 cURL 기반이라 해당 설정의 영향을 받지 않습니다.

빠른 참조

자주 사용하는 클래스

클래스 위치 용도
ResponseHelper app/Helpers/ResponseHelper.php API 응답 표준화
BaseApiResource app/Http/Resources/BaseApiResource.php API 리소스 기본 클래스
AdminBaseController app/Http/Controllers/Api/Admin/AdminBaseController.php 관리자 컨트롤러

훅 네이밍 규칙

[vendor-module].[entity].[action]_[timing]

예시:
sirsoft-ecommerce.product.before_create
sirsoft-ecommerce.product.after_update
sirsoft-ecommerce.product.filter_create_data

관련 문서