Files
vexplor/docs/노드_구조_개선안.md
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

12 KiB

노드 구조 개선안 - FROM/TO 테이블 명확화

작성일: 2025-01-02
버전: 1.0
상태: 🤔 검토 중


📋 문제 인식

현재 설계의 한계

현재 플로우:
TableSource(user_info) → FieldMapping → InsertAction(targetTable: "orders")

문제점:

  1. 타겟 테이블(orders)이 노드로 표현되지 않음
  2. InsertAction의 속성으로만 존재 → 시각적으로 불명확
  3. FROM(user_info)과 TO(orders)의 관계가 직관적이지 않음
  4. 타겟 테이블의 스키마 정보를 참조하기 어려움

💡 개선 방안

옵션 1: TableTarget 노드 추가 (권장 )

새로운 플로우:

TableSource(user_info) → FieldMapping → TableTarget(orders) → InsertAction

노드 추가:

  • TableTarget - 타겟 테이블을 명시적으로 표현

장점:

  • FROM/TO가 시각적으로 명확
  • 타겟 테이블 스키마를 미리 로드 가능
  • FieldMapping에서 타겟 필드 자동 완성 가능
  • 데이터 흐름이 직관적

단점:

  • ⚠️ 노드 개수 증가 (복잡도 증가)
  • ⚠️ 기존 설계와 호환성 문제

옵션 2: Action 노드에 Target 속성 유지 (현재 방식)

현재 플로우 유지:

TableSource(user_info) → FieldMapping → InsertAction(targetTable: "orders")

개선 방법:

  • Action 노드에서 타겟 테이블을 더 명확히 표시
  • 노드 UI에 타겟 테이블명을 크게 표시
  • Properties Panel에서 타겟 테이블 선택 시 스키마 정보 제공

장점:

  • 기존 설계 유지 (구현 완료된 상태)
  • 노드 개수가 적음 (간결함)
  • 빠른 플로우 구성 가능

단점:

  • 시각적으로 FROM/TO 관계가 불명확
  • FieldMapping 단계에서 타겟 필드 정보 접근이 어려움

옵션 3: 가상 노드 자동 표시 (신규 제안 )

개념: Action 노드에서 targetTable 속성을 설정하면, 시각적으로만 타겟 테이블 노드를 자동 생성

실제 플로우 (저장되는 구조):

TableSource(user_info) → FieldMapping → InsertAction(targetTable: "orders")

시각적 표시 (화면에 보이는 모습):

TableSource(user_info)
  → FieldMapping
    → InsertAction(targetTable: "orders")
      → 👻 orders (가상 노드, 자동 생성)

특징:

  • 가상 노드는 선택/이동/삭제 불가능
  • 반투명하게 표시하여 가상임을 명확히 표시
  • Action 노드의 targetTable 속성 변경 시 자동 업데이트
  • 저장 시에는 가상 노드 제외

장점:

  • 사용자는 기존대로 사용 (노드 추가 불필요)
  • 시각적으로 FROM/TO 관계 명확
  • 기존 설계 100% 유지
  • 구현 복잡도 낮음
  • 기존 플로우와 완벽 호환

단점:

  • ⚠️ 가상 노드의 상호작용 제한 필요
  • ⚠️ "왜 클릭이 안 되지?" 혼란 가능성
  • ⚠️ 가상 노드 렌더링 로직 추가

옵션 4: 하이브리드 방식

조건부 사용:

// 단순 케이스: TableTarget 생략
TableSource → FieldMapping → InsertAction(targetTable 지정)

// 복잡한 케이스: TableTarget 사용
TableSource → FieldMapping → TableTarget → InsertAction

장점:

  • 유연성 제공
  • 단순/복잡한 케이스 모두 대응

단점:

  • 사용자 혼란 가능성
  • 검증 로직 복잡

🎯 권장 방안 비교

옵션 재평가

항목 옵션 1
(TableTarget)
옵션 2
(현재 방식)
옵션 3
(가상 노드)
시각적 명확성
구현 복잡도
사용자 편의성
기존 호환성
자동 완성
유지보수성
학습 곡선

최종 권장: 옵션 3 (가상 노드 자동 표시)

선택 이유:

  1. 최고의 시각적 명확성 - FROM/TO 관계가 한눈에 보임
  2. 사용자 편의성 - 기존 방식 그대로, 노드 추가 불필요
  3. 완벽한 호환성 - 기존 플로우 수정 불필요
  4. 낮은 학습 곡선 - 새로운 노드 타입 학습 불필요
  5. 적절한 구현 복잡도 - React Flow의 커스텀 렌더링 활용

구현 방식:

// Action 노드가 있으면 자동으로 가상 타겟 노드 생성
function generateVirtualTargetNodes(nodes: FlowNode[]): VirtualNode[] {
  return nodes
    .filter((node) => isActionNode(node.type) && node.data.targetTable)
    .map((actionNode) => ({
      id: `virtual-target-${actionNode.id}`,
      type: "virtualTarget",
      position: {
        x: actionNode.position.x,
        y: actionNode.position.y + 150,
      },
      data: {
        tableName: actionNode.data.targetTable,
        sourceActionId: actionNode.id,
        isVirtual: true,
      },
    }));
}

🎯 대안: 옵션 1 (TableTarget 추가)

새로운 노드 타입 추가

TableTarget 노드

타입: tableTarget

데이터 구조:

interface TableTargetNodeData {
  tableName: string; // 타겟 테이블명
  schema?: string; // 스키마 (선택)
  columns?: Array<{
    // 타겟 컬럼 정보
    name: string;
    type: string;
    nullable: boolean;
    primaryKey: boolean;
  }>;
  displayName?: string;
}

특징:

  • 입력: FieldMapping, DataTransform 등에서 받음
  • 출력: Action 노드로 전달
  • 타겟 테이블 스키마를 미리 로드하여 검증 가능

시각적 표현:

┌────────────────────┐
│ 📊 Table Target    │
├────────────────────┤
│ orders             │
│ schema: public     │
├────────────────────┤
│ 컬럼:              │
│ • order_id (PK)    │
│ • customer_id      │
│ • order_date       │
│ • total_amount     │
└────────────────────┘

개선된 연결 규칙

TableTarget 추가 시 연결 규칙

허용되는 연결:

✅ FieldMapping → TableTarget
✅ DataTransform → TableTarget
✅ Condition → TableTarget
✅ TableTarget → InsertAction
✅ TableTarget → UpdateAction
✅ TableTarget → UpsertAction

금지되는 연결:

❌ TableSource → TableTarget (직접 연결 불가)
❌ TableTarget → DeleteAction (DELETE는 타겟 불필요)
❌ TableTarget → TableTarget

새로운 검증 규칙:

  1. Action 노드는 TableTarget 또는 targetTable 속성 중 하나 필수
  2. TableTarget이 있으면 Action의 targetTable 속성 무시
  3. FieldMapping 이후에 TableTarget이 오면 자동 필드 매칭 제안

실제 사용 예시

예시 1: 단순 데이터 복사

기존 방식:

TableSource(user_info)
  → FieldMapping(user_id → customer_id, user_name → name)
    → InsertAction(targetTable: "customers")

개선 방식:

TableSource(user_info)
  → FieldMapping(user_id → customer_id)
    → TableTarget(customers)
      → InsertAction

장점:

  • customers 테이블 스키마를 FieldMapping에서 참조 가능
  • 필드 자동 완성 제공

예시 2: 조건부 데이터 처리

개선 방식:

TableSource(user_info)
  → Condition(age >= 18)
    ├─ TRUE → TableTarget(adult_users) → InsertAction
    └─ FALSE → TableTarget(minor_users) → InsertAction

장점:

  • TRUE/FALSE 분기마다 다른 타겟 테이블 명확히 표시

예시 3: 멀티 소스 + 단일 타겟

개선 방식:

┌─ TableSource(users) ────┐
│                          ↓
└─ ExternalDB(orders) ─→ FieldMapping → TableTarget(user_orders) → InsertAction

장점:

  • 여러 소스에서 데이터를 받아 하나의 타겟으로 통합
  • 타겟 테이블이 시각적으로 명확

🔧 구현 계획

Phase 1: TableTarget 노드 구현

작업 항목:

  1. TableTargetNodeData 인터페이스 정의
  2. TableTargetNode.tsx 컴포넌트 생성
  3. TableTargetProperties.tsx 속성 패널 생성
  4. Node Palette에 추가
  5. FlowEditor에 등록

예상 시간: 2시간


Phase 2: 연결 규칙 업데이트

작업 항목:

  1. validateConnection에 TableTarget 규칙 추가
  2. Action 노드가 TableTarget 입력을 받도록 수정
  3. 검증 로직 업데이트

예상 시간: 1시간


Phase 3: 자동 필드 매핑 개선

작업 항목:

  1. TableTarget이 연결되면 타겟 스키마 자동 로드
  2. FieldMapping에서 타겟 필드 자동 완성 제공
  3. 필드 타입 호환성 검증

예상 시간: 2시간


Phase 4: 기존 플로우 마이그레이션

작업 항목:

  1. 기존 InsertAction의 targetTable을 TableTarget으로 변환
  2. 자동 마이그레이션 스크립트 작성
  3. 호환성 유지 모드 제공

예상 시간: 2시간


🤔 고려사항

1. 기존 플로우와의 호환성

문제: 이미 저장된 플로우는 TableTarget 없이 구성됨

해결 방안:

  • 옵션 A: 자동 마이그레이션

    • 플로우 로드 시 InsertAction의 targetTable을 TableTarget 노드로 변환
    • 기존 데이터는 보존
  • 옵션 B: 호환성 모드

    • TableTarget 없이도 동작하도록 유지
    • 새 플로우만 TableTarget 사용 권장

권장: 옵션 B (호환성 모드)


2. 사용자 경험

우려: 노드가 하나 더 추가되어 복잡해짐

완화 방안:

  • 템플릿 제공: "TableSource → FieldMapping → TableTarget → InsertAction" 세트를 템플릿으로 제공
  • 자동 생성: InsertAction 생성 시 TableTarget 자동 생성 옵션
  • 가이드: 처음 사용자를 위한 튜토리얼

3. 성능

우려: TableTarget이 스키마를 로드하면 성능 저하 가능성

완화 방안:

  • 캐싱: 한 번 로드한 스키마는 캐싱
  • 지연 로딩: 필요할 때만 스키마 로드
  • 백그라운드 로딩: 비동기로 스키마 로드

📊 비교 분석

항목 옵션 1 (TableTarget) 옵션 2 (현재 방식)
시각적 명확성
구현 복잡도
사용자 학습곡선
자동 완성 지원
유지보수성
기존 호환성

🎯 결론

권장 사항: 옵션 1 (TableTarget 추가)

이유:

  1. 데이터 흐름이 시각적으로 명확
  2. 스키마 기반 자동 완성 가능
  3. 향후 확장성 우수
  4. 복잡한 데이터 흐름에서 특히 유용

단계적 도입:

  • Phase 1: TableTarget 노드 추가 (선택 사항)
  • Phase 2: 기존 방식과 공존
  • Phase 3: 사용자 피드백 수집
  • Phase 4: 장기적으로 TableTarget 방식 권장

📝 다음 단계

  1. 의사 결정: 옵션 1 vs 옵션 2 선택
  2. 프로토타입: TableTarget 노드 간단히 구현
  3. 테스트: 실제 사용 시나리오로 검증
  4. 문서화: 사용 가이드 작성
  5. 배포: 단계적 릴리스

피드백 환영: 이 설계에 대한 의견을 주시면 개선하겠습니다! 💬