279 lines
7.2 KiB
Markdown
279 lines
7.2 KiB
Markdown
# 메타 컴포넌트 V3 사용 가이드 (Phase A)
|
|
|
|
## 개요
|
|
|
|
화면 디자이너 V3 메타 컴포넌트는 기존 70개+ 컴포넌트를 7개 메타 컴포넌트로 통합하는 시스템입니다.
|
|
Phase A에서는 핵심 3개 메타 컴포넌트(Field, DataView, Action)를 구현했습니다.
|
|
|
|
## Phase A 구현 범위
|
|
|
|
### 1. Field 메타 컴포넌트
|
|
- **자동 생성**: `table_type_columns`의 `webType` 기반
|
|
- **지원 타입**: text, number, date, select, entity, checkbox, textarea, email, file
|
|
- **자동 감지**: FK 관계 자동 감지 → `entity` 타입 + `join` 설정
|
|
- **유효성 검사**: webType별 기본 validation 내장
|
|
|
|
### 2. DataView 메타 컴포넌트
|
|
- **뷰 모드**: table, card, list (전환 가능)
|
|
- **기본 기능**: 페이징, 정렬, 필터링
|
|
- **액션**: 등록, 수정, 삭제 버튼
|
|
- **반응형**: 모바일/데스크톱 최적화
|
|
|
|
### 3. Action 메타 컴포넌트
|
|
- **버튼 렌더링**: buttonType별 shadcn/ui variant 자동 매핑
|
|
- **확인 대화상자**: 위험한 작업 시 확인 요청
|
|
- **steps 파이프라인**: Phase B에서 완전 구현 예정 (Phase A에서는 onClick 콜백만 실행)
|
|
|
|
### 4. Reactive Binding Engine
|
|
- **이벤트 발행/구독**: 컴포넌트 간 동적 연동
|
|
- **조건부 실행**: condition 평가 지원
|
|
- **데이터 변환**: transform 로직 적용
|
|
- **우선순위**: priority 기반 실행 순서 제어
|
|
|
|
## 백엔드 API 엔드포인트
|
|
|
|
### Field Config 자동 생성
|
|
```typescript
|
|
GET /api/meta/field-config/:tableName/:columnName
|
|
|
|
// 응답 예시
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"webType": "entity",
|
|
"label": "부서",
|
|
"placeholder": "부서를 선택하세요",
|
|
"required": true,
|
|
"join": {
|
|
"referenceTable": "dept_info",
|
|
"referenceColumn": "dept_code",
|
|
"displayColumn": "dept_name"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 테이블 컬럼 목록 조회
|
|
```typescript
|
|
GET /api/meta/table-columns/:tableName
|
|
|
|
// 응답 예시
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"tableName": "user_info",
|
|
"columns": [
|
|
{
|
|
"columnName": "user_id",
|
|
"columnComment": "사용자 ID",
|
|
"webType": "text",
|
|
"required": true
|
|
},
|
|
{
|
|
"columnName": "dept_code",
|
|
"columnComment": "부서",
|
|
"webType": "entity",
|
|
"required": false,
|
|
"join": {
|
|
"referenceTable": "dept_info",
|
|
"referenceColumn": "dept_code",
|
|
"displayColumn": "dept_name"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### 레이아웃 저장
|
|
```typescript
|
|
POST /api/meta/layout/save
|
|
|
|
// 요청 예시
|
|
{
|
|
"version": "3.0",
|
|
"screenId": 123,
|
|
"layerId": 1,
|
|
"components": [
|
|
{
|
|
"id": "field_user_name",
|
|
"type": "meta-field",
|
|
"webType": "text",
|
|
"label": "사용자명",
|
|
"binding": "user_name",
|
|
"required": true
|
|
},
|
|
{
|
|
"id": "dataview_user_list",
|
|
"type": "meta-dataview",
|
|
"viewMode": "table",
|
|
"tableName": "user_info"
|
|
}
|
|
],
|
|
"layers": [
|
|
{ "id": 1, "name": "기본", "visible": true, "order": 1 }
|
|
]
|
|
}
|
|
```
|
|
|
|
### 레이아웃 로드
|
|
```typescript
|
|
GET /api/meta/layout/:screenId?layerId=1
|
|
```
|
|
|
|
### Reactive Binding 저장
|
|
```typescript
|
|
POST /api/meta/bindings/save
|
|
|
|
// 요청 예시
|
|
{
|
|
"screenId": 123,
|
|
"bindings": [
|
|
{
|
|
"id": "binding_dept_filter",
|
|
"sourceComponent": "field_dept_code",
|
|
"sourceEvent": "onChange",
|
|
"targetComponent": "dataview_user_list",
|
|
"targetAction": "filter",
|
|
"condition": {
|
|
"type": "expression",
|
|
"expression": "source.value !== ''"
|
|
},
|
|
"transform": {
|
|
"config": {
|
|
"filterField": "dept_code",
|
|
"filterValue": "{{source.value}}"
|
|
}
|
|
},
|
|
"priority": 10,
|
|
"enabled": true
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Reactive Binding 조회
|
|
```typescript
|
|
GET /api/meta/bindings/:screenId
|
|
```
|
|
|
|
## 사용 예시
|
|
|
|
### 1. 간단한 Field 렌더링
|
|
|
|
```tsx
|
|
import { FieldRenderer } from "@/lib/meta-components/Field/FieldRenderer";
|
|
|
|
<FieldRenderer
|
|
config={{
|
|
id: "field_user_name",
|
|
type: "meta-field",
|
|
webType: "text",
|
|
label: "사용자명",
|
|
binding: "user_name",
|
|
required: true,
|
|
maxLength: 50,
|
|
}}
|
|
value={userName}
|
|
onChange={(value) => setUserName(value)}
|
|
/>
|
|
```
|
|
|
|
### 2. DataView 렌더링
|
|
|
|
```tsx
|
|
import { DataViewRenderer } from "@/lib/meta-components/DataView/DataViewRenderer";
|
|
|
|
<DataViewRenderer
|
|
config={{
|
|
id: "dataview_user_list",
|
|
type: "meta-dataview",
|
|
viewMode: "table",
|
|
tableName: "user_info",
|
|
columns: [
|
|
{ field: "user_id", header: "사용자 ID", webType: "text" },
|
|
{ field: "user_name", header: "사용자명", webType: "text" },
|
|
{ field: "dept_code", header: "부서", webType: "entity" },
|
|
],
|
|
pagination: {
|
|
enabled: true,
|
|
pageSize: 20,
|
|
},
|
|
}}
|
|
data={users}
|
|
onActionClick={(action, rowData) => {
|
|
console.log("액션:", action, "데이터:", rowData);
|
|
}}
|
|
/>
|
|
```
|
|
|
|
### 3. Reactive Binding 설정
|
|
|
|
```tsx
|
|
import { ReactiveBindingEngine } from "@/lib/meta-components/bindings/ReactiveBindingEngine";
|
|
|
|
const bindingEngine = new ReactiveBindingEngine();
|
|
|
|
// 바인딩 설정
|
|
bindingEngine.setBindings([
|
|
{
|
|
id: "binding_1",
|
|
sourceComponent: "field_dept_code",
|
|
sourceEvent: "onChange",
|
|
targetComponent: "dataview_user_list",
|
|
targetAction: "filter",
|
|
transform: {
|
|
config: {
|
|
filterField: "dept_code",
|
|
filterValue: "{{source.value}}",
|
|
},
|
|
},
|
|
priority: 10,
|
|
enabled: true,
|
|
},
|
|
]);
|
|
|
|
// 이벤트 발행 (Field onChange 시)
|
|
bindingEngine.emitEvent("field_dept_code", "onChange", { value: "IT" });
|
|
```
|
|
|
|
## 주의사항
|
|
|
|
### 1. API 클라이언트 (필수!)
|
|
```typescript
|
|
// ❌ 금지: fetch() 직접 사용
|
|
const response = await fetch("/api/meta/field-config/user_info/user_name");
|
|
|
|
// ✅ 올바른 방법: apiClient 사용
|
|
import { getFieldConfig } from "@/lib/api/metaComponent";
|
|
const response = await getFieldConfig("user_info", "user_name");
|
|
```
|
|
|
|
### 2. 멀티테넌시
|
|
- 모든 API 호출 시 `req.user.companyCode` 자동 필터링
|
|
- 프론트엔드에서는 company_code를 직접 전달하지 않음
|
|
|
|
### 3. 버전 관리
|
|
- V3 레이아웃은 반드시 `version: "3.0"` 명시
|
|
- screen_layouts_v3 테이블에 CHECK 제약조건 있음
|
|
|
|
### 4. shadcn/ui 스타일 가이드
|
|
- CSS 변수 사용: `bg-primary`, `text-muted-foreground`
|
|
- 중첩 박스 금지: Card 안에 Card 넣지 않기
|
|
- 반응형 디자인: 모바일 우선 접근
|
|
|
|
## Phase B 예정 기능
|
|
|
|
1. **UnifiedConfigPanel**: 통합 설정 패널 (5탭)
|
|
2. **테이블 드롭 자동 생성**: 테이블 이름 드롭 → 전체 CRUD 화면 자동 생성
|
|
3. **steps 파이프라인 완전 구현**: validate, api, transform, condition, loop, parallel, error 타입
|
|
4. **고급 Reactive Binding**: 복잡한 조건, 다중 타겟, 비동기 변환
|
|
|
|
## 참고 문서
|
|
|
|
- [docs/screen-designer-upgrade-plan.md](../../../docs/screen-designer-upgrade-plan.md) - 전체 계획
|
|
- [frontend/lib/meta-components/Field/fieldTypes.ts](../Field/fieldTypes.ts) - Field 타입 정의
|
|
- [frontend/lib/meta-components/DataView/dataViewTypes.ts](../DataView/dataViewTypes.ts) - DataView 타입 정의
|
|
- [frontend/lib/meta-components/Action/actionTypes.ts](../Action/actionTypes.ts) - Action 타입 정의
|
|
- [frontend/lib/meta-components/bindings/bindingTypes.ts](../bindings/bindingTypes.ts) - Binding 타입 정의
|