Files
vexplor/frontend/components/dataflow/node-editor/sidebar/nodePaletteConfig.ts
kjs 0743786f9b feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
  - TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
  - 드래그앤드롭 노드 추가 및 연결
  - 속성 패널을 통한 노드 설정
  - 실시간 필드 라벨 표시 (column_labels 테이블 연동)

- 데이터 변환 노드 (DataTransform) 기능
  - EXPLODE: 구분자로 1개 행 → 여러 행 확장
  - UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
  - In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
  - 변환된 필드가 하위 액션 노드에 자동 전달

- 노드 플로우 실행 엔진
  - 위상 정렬을 통한 노드 실행 순서 결정
  - 레벨별 병렬 실행 (Promise.allSettled)
  - 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
  - 트랜잭션 기반 안전한 데이터 처리

- UPSERT 액션 로직 구현
  - DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
  - 복합 충돌 키 지원 (예: sales_no + product_name)
  - 파라미터 인덱스 정확한 매핑

- 데이터 소스 자동 감지
  - 테이블 선택 데이터 (selectedRowsData) 자동 주입
  - 폼 입력 데이터 (formData) 자동 주입
  - TableSource 노드가 외부 데이터 우선 사용

- 버튼 컴포넌트 통합
  - 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
  - 노드 플로우 선택 UI 추가
  - API 클라이언트 통합 (Axios)

- 개발 문서 작성
  - 노드 기반 제어 시스템 개선 계획
  - 노드 연결 규칙 설계
  - 노드 실행 엔진 설계
  - 노드 구조 개선안
  - 버튼 통합 분석
2025-10-02 16:22:29 +09:00

157 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 노드 팔레트 설정
*/
import type { NodePaletteItem } from "@/types/node-editor";
export const NODE_PALETTE: NodePaletteItem[] = [
// ========================================================================
// 데이터 소스
// ========================================================================
{
type: "tableSource",
label: "테이블",
icon: "📊",
description: "내부 데이터베이스 테이블에서 데이터를 읽어옵니다",
category: "source",
color: "#3B82F6", // 파란색
},
{
type: "externalDBSource",
label: "외부 DB",
icon: "🔌",
description: "외부 데이터베이스에서 데이터를 읽어옵니다",
category: "source",
color: "#F59E0B", // 주황색
},
{
type: "restAPISource",
label: "REST API",
icon: "📁",
description: "REST API를 호출하여 데이터를 가져옵니다",
category: "source",
color: "#10B981", // 초록색
},
// ========================================================================
// 변환/조건
// ========================================================================
{
type: "condition",
label: "조건 분기",
icon: "⚡",
description: "조건에 따라 데이터 흐름을 분기합니다",
category: "transform",
color: "#EAB308", // 노란색
},
{
type: "fieldMapping",
label: "필드 매핑",
icon: "🔀",
description: "소스 필드를 타겟 필드로 매핑합니다",
category: "transform",
color: "#8B5CF6", // 보라색
},
{
type: "dataTransform",
label: "데이터 변환",
icon: "🔧",
description: "데이터를 변환하거나 가공합니다",
category: "transform",
color: "#06B6D4", // 청록색
},
// ========================================================================
// 액션
// ========================================================================
{
type: "insertAction",
label: "INSERT",
icon: "",
description: "데이터를 삽입합니다",
category: "action",
color: "#22C55E", // 초록색
},
{
type: "updateAction",
label: "UPDATE",
icon: "✏️",
description: "데이터를 수정합니다",
category: "action",
color: "#3B82F6", // 파란색
},
{
type: "deleteAction",
label: "DELETE",
icon: "❌",
description: "데이터를 삭제합니다",
category: "action",
color: "#EF4444", // 빨간색
},
{
type: "upsertAction",
label: "UPSERT",
icon: "🔄",
description: "데이터를 삽입하거나 수정합니다",
category: "action",
color: "#8B5CF6", // 보라색
},
// ========================================================================
// 유틸리티
// ========================================================================
{
type: "comment",
label: "주석",
icon: "💬",
description: "주석을 추가합니다",
category: "utility",
color: "#6B7280", // 회색
},
{
type: "log",
label: "로그",
icon: "🔍",
description: "로그를 출력합니다",
category: "utility",
color: "#6B7280", // 회색
},
];
export const NODE_CATEGORIES = [
{
id: "source",
label: "데이터 소스",
icon: "📂",
},
{
id: "transform",
label: "변환/조건",
icon: "🔀",
},
{
id: "action",
label: "액션",
icon: "⚡",
},
{
id: "utility",
label: "유틸리티",
icon: "🛠️",
},
] as const;
/**
* 노드 타입별 팔레트 아이템 조회
*/
export function getNodePaletteItem(type: string): NodePaletteItem | undefined {
return NODE_PALETTE.find((item) => item.type === type);
}
/**
* 카테고리별 노드 목록 조회
*/
export function getNodesByCategory(category: string): NodePaletteItem[] {
return NODE_PALETTE.filter((item) => item.category === category);
}