S1 파일럿 3종(sirsoft-board · sirsoft-gdpr · sirsoft-admin_basic)에 이어
결제·본인인증 동형군 6종의 AGENTS.md · README.md · docs/ 5문서를 집필했다.
확장을 고치려는 쪽이 매번 src/ 를 훑어 구조를 재발견하지 않도록, 설계 의도와
확장점(발행·구독 훅)·수정 시 동반 의무·금지 패턴을 코드 근거로 서술했다.
생성기(ExtensionDocScaffolder)에서 표를 무의미하게 만들던 세 결함을 함께 고쳤다.
getLayoutExtensions 기본 구현이 돌려주는 절대경로가 파일 목록과 중복돼 로컬
머신 경로가 커밋 문서에 실리던 문제, getNotificationDefinitions 를 'key'/'event'
로 읽어 모든 행이 '-' 로 찍히던 문제, getSettingsLayout 절대경로가 정규화 없이
노출되던 문제다. 셋 다 예외를 남기지 않고 표만 조용히 망가뜨리므로
ExtensionDocContractTest 에 각각의 되돌림 red 를 확인한 단언을 두었다.
템플릿의 extensions/{id}/ 는 모듈·플러그인의 발행과 반대 방향(오버라이드)이라
별도 블록(template-overrides)으로 분리했다.
sirsoft-admin_basic 의 컴포넌트·핸들러·레이아웃 문서를 코어 docs/ 에서 그 템플릿
소유로 이관하고, 남은 참조 6축을 재는 가드를 추가했다. 이관 후 남은 옛 경로는
오류가 아니라 헛걸음으로만 나타나 드러나지 않는다. 의 상대 링크가
한 단계 얕아 공유 docs/ 대신 를 가리키던 문제도 함께 고쳤다.
README 상단의 확장명 이미지 배지를 평문 H1 로 바꿨다( 지시 2026-08-31).
루트 README.md · README.ko.md 도 같은 기준을 적용했다. 정보 배지는 유지한다.
sirsoft-gdpr: 회원탈퇴로 자동 철회된 동의가 관리자 동의 이력 화면의 출처 필터로
걸러지지 않던 문제를 고쳤다. Repository 가 'withdraw' 리터럴을 직접 UPDATE 에
싣는데 그 값이 ConsentSource enum 에 없어, 화면 필터 옵션·라벨 어느 쪽에도
도달하지 못했다. 어휘를 enum 단일 출처로 모으고 ko·en·ja 라벨과 필터 옵션을
함께 채웠으며, 어휘 대조 테스트의 모집단에 Repository 를 편입했다.
162 lines
7.1 KiB
Markdown
162 lines
7.1 KiB
Markdown
# 컴포넌트 개발 규칙
|
|
|
|
> **참조**: [프론트엔드 가이드 인덱스](./index.md)
|
|
|
|
---
|
|
|
|
## TL;DR (5초 요약)
|
|
|
|
```text
|
|
1. HTML 태그 직접 사용 금지 (<div> → Div, <button> → Button)
|
|
2. 타입: basic (HTML 래핑), composite (조합), layout (배치)
|
|
3. 집합 컴포넌트 재사용 우선 (새로 만들기 전 기존 확인)
|
|
4. G7Core.t() 함수로 다국어 처리
|
|
5. 다크 모드: light/dark variant 함께 지정
|
|
```
|
|
|
|
---
|
|
|
|
## 하위 문서 안내
|
|
|
|
| 하위 문서 | 주요 내용 | 설명 |
|
|
|----------|----------|------|
|
|
| [components-types.md](components-types.md) | basic, composite, layout | 컴포넌트 타입별 개발 규칙, 재사용 가이드라인 |
|
|
| [components-patterns.md](components-patterns.md) | 순환 의존성, G7Core.t, skipBindingKeys | 패턴 및 다국어 처리 |
|
|
| [components-advanced.md](components-advanced.md) | componentEvent, 아이콘, 체크리스트 | 이벤트 통신, 아이콘 규칙, 개발 체크리스트 |
|
|
|
|
<!-- AUTO-GENERATED-START: frontend-template-reference -->
|
|
### 템플릿별 레퍼런스
|
|
|
|
| 템플릿 식별자 | 컴포넌트 | 핸들러 | 레이아웃 |
|
|
|--------------|---------|--------|--------|
|
|
| `sirsoft-basic` | [components.md](templates/sirsoft-basic/components.md) | [handlers.md](templates/sirsoft-basic/handlers.md) | [layouts.md](templates/sirsoft-basic/layouts.md) |
|
|
|
|
<!-- AUTO-GENERATED-END: frontend-template-reference -->
|
|
|
|
> `sirsoft-admin_basic` 은 문서를 그 템플릿이 직접 소유합니다 — [templates/_bundled/sirsoft-admin_basic/docs/](../../templates/_bundled/sirsoft-admin_basic/docs/README.md).
|
|
> 템플릿별 문서 위치는 [templates/README.md](templates/README.md) 를 따릅니다.
|
|
|
|
---
|
|
|
|
## 목차
|
|
|
|
### 타입별 개발 규칙 ([상세 문서](components-types.md))
|
|
|
|
1. [핵심 원칙](components-types.md#핵심-원칙)
|
|
2. [기본 컴포넌트 (Basic Component)](components-types.md#1-기본-컴포넌트-basic-component)
|
|
3. [집합 컴포넌트 (Composite Component)](components-types.md#2-집합-컴포넌트-composite-component)
|
|
4. [집합 컴포넌트 재사용 가이드라인](components-types.md#3-집합-컴포넌트-재사용-가이드라인)
|
|
5. [레이아웃 컴포넌트 (Layout Component)](components-types.md#4-레이아웃-컴포넌트-layout-component)
|
|
|
|
### 패턴 및 다국어 ([상세 문서](components-patterns.md))
|
|
|
|
6. [순환 의존성 해결 패턴](components-patterns.md#순환-의존성-해결-패턴)
|
|
7. [다국어 번역 (G7Core.t)](components-patterns.md#다국어-번역-g7coret)
|
|
8. [skipBindingKeys (바인딩 지연 처리)](components-patterns.md#skipbindingkeys-바인딩-지연-처리)
|
|
|
|
### 고급 기능 ([상세 문서](components-advanced.md))
|
|
|
|
9. [컴포넌트 간 이벤트 통신 (G7Core.componentEvent)](components-advanced.md#컴포넌트-간-이벤트-통신-g7corecomponentevent)
|
|
10. [이벤트 생성 헬퍼](components-advanced.md#이벤트-생성-헬퍼)
|
|
11. [아이콘 사용 규칙 (Font Awesome)](components-advanced.md#아이콘-사용-규칙-font-awesome)
|
|
12. [Form 자동 바인딩 메타데이터 (bindingType)](components-advanced.md#form-자동-바인딩-메타데이터-bindingtype)
|
|
13. [컴포넌트 개발 체크리스트](components-advanced.md#컴포넌트-개발-체크리스트)
|
|
|
|
---
|
|
|
|
## 핵심 원칙
|
|
|
|
```
|
|
필수: 기본 컴포넌트 사용 (HTML 태그 직접 사용 금지)
|
|
필수: 기본 컴포넌트만 사용 (Div, Button, H2 등)
|
|
✅ 필수: 집합 컴포넌트 재사용 우선
|
|
```
|
|
|
|
→ [상세 문서](components-types.md#핵심-원칙)
|
|
|
|
---
|
|
|
|
## 기능 빠른 참조
|
|
|
|
### 컴포넌트 타입 요약
|
|
|
|
| 타입 | 정의 | 예시 |
|
|
|------|------|------|
|
|
| `basic` | HTML 태그 래핑 | Button, Input, Div, Icon, H1, Span |
|
|
| `composite` | 기본 컴포넌트 조합 | Card, DataGrid, Modal, Pagination |
|
|
| `layout` | 자식 요소 배치 | Container, Grid, Flex, SectionLayout |
|
|
|
|
→ [상세 문서](components-types.md)
|
|
|
|
### 다국어 처리 (G7Core.t)
|
|
|
|
```tsx
|
|
// G7Core.t() 번역 함수 참조
|
|
const t = (key: string, params?: Record<string, string | number>) =>
|
|
(window as any).G7Core?.t?.(key, params) ?? key;
|
|
|
|
// 사용
|
|
<Button>{t('common.confirm')}</Button>
|
|
<Span>{t('admin.users.pagination_info', { from: 1, to: 10, total: 100 })}</Span>
|
|
```
|
|
|
|
→ [상세 문서](components-patterns.md#다국어-번역-g7coret)
|
|
|
|
### 컴포넌트 이벤트 통신
|
|
|
|
```tsx
|
|
// 이벤트 구독
|
|
const unsubscribe = G7Core.componentEvent.on('eventName', callback);
|
|
|
|
// 이벤트 발생
|
|
G7Core.componentEvent.emit('triggerUpload:logo_uploader');
|
|
```
|
|
|
|
→ [상세 문서](components-advanced.md#컴포넌트-간-이벤트-통신-g7corecomponentevent)
|
|
|
|
### 아이콘 사용 (Font Awesome)
|
|
|
|
```tsx
|
|
import { Icon, IconName } from '../basic/Icon';
|
|
|
|
<Icon name={IconName.Check} />
|
|
<Icon name="fa-solid fa-user" />
|
|
```
|
|
|
|
```text
|
|
주의: Font Awesome Pro 전용 아이콘 사용 금지 (Light, Thin, Duotone)
|
|
주의: 다른 아이콘 라이브러리 직접 import 금지
|
|
```
|
|
|
|
→ [상세 문서](components-advanced.md#아이콘-사용-규칙-font-awesome)
|
|
|
|
### 컴포넌트 등록 체크리스트
|
|
|
|
```text
|
|
필수: 새 컴포넌트 생성 시 아래 4개 파일에 등록
|
|
□ 컴포넌트 파일 생성: templates/[vendor-template]/src/components/{type}/{Name}.tsx
|
|
□ index.ts export 추가: templates/[vendor-template]/src/components/{type}/index.ts
|
|
□ components.json 등록: templates/[vendor-template]/components.json
|
|
□ 테스트 파일 생성: templates/[vendor-template]/src/components/{type}/__tests__/{Name}.test.tsx
|
|
```
|
|
|
|
→ [상세 문서](components-advanced.md#컴포넌트-개발-체크리스트)
|
|
|
|
### 레이아웃 편집기 capability 선언 의무
|
|
|
|
새 draggable 컴포넌트(레이아웃 편집기 팔레트/캔버스에 노출)는 위 4개 파일에 더해 호스트 템플릿 `editor-spec/componentCapabilities.json` 에 capability 를 선언해야 편집기에서 "편집 불가(no-editable)"가 되지 않는다. 표시 텍스트/아이콘/select/목록·배열·표 데이터 prop 별로 `propControls`(속성 탭) / `dataProps`(데이터 연결) / `nodeEditor`·`canvasOverlay`(구조 에디터) / `styleControls`(스타일 탭) / `events`(동작 탭) 를 선언한다. 데이터 표면을 가진 컴포넌트가 편집 슬롯도 비대상 allowlist 도 없으면 정적 검사가 차단한다. composite/layout 컴포넌트는 `editorAttrs` spread + `id` 패스스루도 필요하다.
|
|
|
|
상세: [editor-spec.md "componentCapabilities"](../extension/editor-spec.md) · [components-types.md "편집기 attribute 패스스루"](components-types.md)
|
|
|
|
---
|
|
|
|
## 관련 문서
|
|
|
|
- [g7core-api.md](g7core-api.md) - G7Core 전역 API 레퍼런스
|
|
- [레이아웃 JSON 스키마](./layout-json.md) - 컴포넌트를 레이아웃 JSON에서 사용하는 방법
|
|
- [데이터 바인딩](./data-binding.md) - props에서 데이터 바인딩 사용법
|
|
- [sirsoft-admin_basic 컴포넌트](../../templates/_bundled/sirsoft-admin_basic/docs/components.md) - Admin 컴포넌트 목록
|
|
- [sirsoft-basic 컴포넌트](./templates/sirsoft-basic/components.md) - User 컴포넌트 목록 (58개)
|
|
- [다크 모드](./dark-mode.md) - 컴포넌트 다크 모드 지원 가이드
|
|
- [상태 관리](./state-management.md) - 전역/로컬 상태 관리 및 동기화 패턴
|