7.2 KiB
7.2 KiB
메타 컴포넌트 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 자동 생성
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"
}
}
}
테이블 컬럼 목록 조회
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"
}
}
]
}
}
레이아웃 저장
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 }
]
}
레이아웃 로드
GET /api/meta/layout/:screenId?layerId=1
Reactive Binding 저장
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 조회
GET /api/meta/bindings/:screenId
사용 예시
1. 간단한 Field 렌더링
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 렌더링
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 설정
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 클라이언트 (필수!)
// ❌ 금지: 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 예정 기능
- UnifiedConfigPanel: 통합 설정 패널 (5탭)
- 테이블 드롭 자동 생성: 테이블 이름 드롭 → 전체 CRUD 화면 자동 생성
- steps 파이프라인 완전 구현: validate, api, transform, condition, loop, parallel, error 타입
- 고급 Reactive Binding: 복잡한 조건, 다중 타겟, 비동기 변환
참고 문서
- docs/screen-designer-upgrade-plan.md - 전체 계획
- frontend/lib/meta-components/Field/fieldTypes.ts - Field 타입 정의
- frontend/lib/meta-components/DataView/dataViewTypes.ts - DataView 타입 정의
- frontend/lib/meta-components/Action/actionTypes.ts - Action 타입 정의
- frontend/lib/meta-components/bindings/bindingTypes.ts - Binding 타입 정의