Files
vexplor/제어관리_데이터소스_확장_가이드.md
2025-10-24 14:11:12 +09:00

14 KiB

제어관리 데이터 소스 확장 가이드

개요

제어관리(플로우) 실행 시 사용할 수 있는 데이터 소스가 확장되었습니다. 이제 폼 데이터, 테이블 선택 항목, 테이블 전체 데이터, 플로우 선택 항목, 플로우 스텝 전체 데이터 등 다양한 소스에서 데이터를 가져와 제어를 실행할 수 있습니다.

지원 데이터 소스

1. form - 폼 데이터

  • 설명: 현재 화면의 폼 입력값을 사용합니다.
  • 사용 시나리오: 단일 레코드 생성/수정 시
  • 데이터 형태: 단일 객체
{
  name: "홍길동",
  age: 30,
  email: "test@example.com"
}

2. table-selection - 테이블 선택 항목

  • 설명: 테이블에서 사용자가 선택한 행의 데이터를 사용합니다.
  • 사용 시나리오: 선택된 항목에 대한 일괄 처리
  • 데이터 형태: 배열 (선택된 행들)
[
  { id: 1, name: "항목1", status: "대기" },
  { id: 2, name: "항목2", status: "대기" }
]

3. table-all - 테이블 전체 데이터 🆕

  • 설명: 테이블의 모든 데이터를 사용합니다 (페이징 무관).
  • 사용 시나리오:
    • 전체 데이터에 대한 일괄 처리
    • 통계/집계 작업
    • 대량 데이터 마이그레이션
  • 데이터 형태: 배열 (전체 행)
  • 주의사항: 데이터가 많을 경우 성능 이슈가 있을 수 있습니다.
[
  { id: 1, name: "항목1", status: "대기" },
  { id: 2, name: "항목2", status: "진행중" },
  { id: 3, name: "항목3", status: "완료" },
  // ... 수천 개의 행
]

4. flow-selection - 플로우 선택 항목

  • 설명: 플로우 위젯에서 사용자가 선택한 데이터를 사용합니다.
  • 사용 시나리오: 플로우 단계별로 선택된 항목 처리
  • 데이터 형태: 배열 (선택된 행들)
[
  { id: 10, taskName: "작업1", stepId: 2 },
  { id: 11, taskName: "작업2", stepId: 2 }
]

5. flow-step-all - 플로우 스텝 전체 데이터 🆕

  • 설명: 현재 선택된 플로우 단계의 모든 데이터를 사용합니다.
  • 사용 시나리오:
    • 특정 단계의 모든 항목 일괄 처리
    • 단계별 완료율 계산
    • 단계 이동 시 전체 데이터 마이그레이션
  • 데이터 형태: 배열 (해당 스텝의 전체 행)
[
  { id: 10, taskName: "작업1", stepId: 2, assignee: "홍길동" },
  { id: 11, taskName: "작업2", stepId: 2, assignee: "김철수" },
  { id: 12, taskName: "작업3", stepId: 2, assignee: "이영희" },
  // ... 해당 스텝의 모든 데이터
]

6. both - 폼 + 테이블 선택

  • 설명: 폼 데이터와 테이블 선택 항목을 결합하여 사용합니다.
  • 사용 시나리오: 폼의 공통 정보 + 개별 항목 처리
  • 데이터 형태: 배열 (폼 데이터 + 선택된 행들)
[
  { name: "홍길동", age: 30 }, // 폼 데이터
  { id: 1, name: "항목1", status: "대기" },
  { id: 2, name: "항목2", status: "대기" }
]

7. all-sources - 모든 소스 결합 🆕

  • 설명: 폼, 테이블 전체, 플로우 등 모든 소스의 데이터를 결합하여 사용합니다.
  • 사용 시나리오:
    • 복잡한 데이터 통합 작업
    • 다중 소스 동기화
    • 전체 시스템 상태 업데이트
  • 데이터 형태: 배열 (모든 소스의 데이터 병합)
  • 주의사항: 매우 많은 데이터가 전달될 수 있으므로 신중히 사용하세요.
[
  { name: "홍길동", age: 30 }, // 폼 데이터
  { id: 1, name: "테이블1" },   // 테이블 선택
  { id: 2, name: "테이블2" },   // 테이블 선택
  { id: 3, name: "테이블3" },   // 테이블 전체
  { id: 10, taskName: "작업1" }, // 플로우 선택
  // ... 모든 소스의 데이터
]

설정 방법

1. 버튼 상세 설정에서 데이터 소스 선택

  1. 화면 디자이너에서 버튼 선택
  2. 우측 패널 > 상세 설정
  3. 제어관리 활성화 체크
  4. 제어 데이터 소스 드롭다운에서 원하는 소스 선택

2. 데이터 소스 옵션

┌─────────────────────────────────────┐
│ 제어 데이터 소스                    │
├─────────────────────────────────────┤
│ 📄 폼 데이터                        │
│ 📊 테이블 선택 항목                 │
│ 📊 테이블 전체 데이터 🆕            │
│ 🔄 플로우 선택 항목                 │
│ 🔄 플로우 스텝 전체 데이터 🆕       │
│ 📋 폼 + 테이블 선택                 │
│ 🌐 모든 소스 결합 🆕                │
└─────────────────────────────────────┘

실제 사용 예시

예시 1: 테이블 전체 데이터로 일괄 상태 업데이트

// 제어 설정
{
  controlDataSource: "table-all",
  flowConfig: {
    flowId: 10,
    flowName: "전체 항목 승인 처리",
    executionTiming: "replace"
  }
}

// 실행 시 전달되는 데이터
{
  buttonId: "btn_approve_all",
  sourceData: [
    { id: 1, name: "항목1", status: "대기" },
    { id: 2, name: "항목2", status: "대기" },
    { id: 3, name: "항목3", status: "대기" },
    // ... 테이블의 모든 행 (1000개)
  ]
}

예시 2: 플로우 스텝 전체를 다음 단계로 이동

// 제어 설정
{
  controlDataSource: "flow-step-all",
  flowConfig: {
    flowId: 15,
    flowName: "단계 일괄 이동",
    executionTiming: "replace"
  }
}

// 실행 시 전달되는 데이터
{
  buttonId: "btn_move_all",
  flowStepId: 2,
  sourceData: [
    { id: 10, taskName: "작업1", stepId: 2 },
    { id: 11, taskName: "작업2", stepId: 2 },
    { id: 12, taskName: "작업3", stepId: 2 },
    // ... 해당 스텝의 모든 데이터
  ]
}

예시 3: 선택된 항목만 처리

// 제어 설정
{
  controlDataSource: "table-selection",
  flowConfig: {
    flowId: 5,
    flowName: "선택 항목 승인",
    executionTiming: "replace"
  }
}

// 실행 시 전달되는 데이터 (사용자가 2개 선택한 경우)
{
  buttonId: "btn_approve_selected",
  sourceData: [
    { id: 1, name: "항목1", status: "대기" },
    { id: 5, name: "항목5", status: "대기" }
  ]
}

데이터 로딩 방식

자동 로딩 vs 수동 로딩

  1. 테이블 선택 항목 (table-selection)

    • 자동 로딩: 사용자가 이미 선택한 데이터 사용
    • 별도 로딩 불필요
  2. 테이블 전체 데이터 (table-all)

    • 지연 로딩: 버튼 클릭 시 필요한 경우만 로드
    • 부모 컴포넌트에서 onRequestTableAllData 콜백 제공 필요
  3. 플로우 스텝 전체 데이터 (flow-step-all)

    • 지연 로딩: 버튼 클릭 시 필요한 경우만 로드
    • 부모 컴포넌트에서 onRequestFlowStepAllData 콜백 제공 필요

부모 컴포넌트 구현 예시

<OptimizedButtonComponent
  component={buttonComponent}
  selectedRowsData={selectedRowsData}
  
  // 테이블 전체 데이터 로드 콜백
  onRequestTableAllData={async () => {
    const response = await fetch(`/api/data/table/${tableId}?all=true`);
    const data = await response.json();
    return data.records;
  }}
  
  // 플로우 스텝 전체 데이터 로드 콜백
  onRequestFlowStepAllData={async (stepId) => {
    const response = await fetch(`/api/flow/step/${stepId}/all-data`);
    const data = await response.json();
    return data.records;
  }}
/>

성능 고려사항

1. 대량 데이터 처리

  • 테이블 전체 데이터: 수천 개의 행이 있을 경우 메모리 및 네트워크 부담
  • 해결 방법:
    • 배치 처리 사용
    • 페이징 처리
    • 서버 사이드 처리

2. 로딩 시간

// ❌ 나쁜 예: 모든 데이터를 항상 미리 로드
useEffect(() => {
  loadTableAllData(); // 버튼을 누르지 않아도 로드됨
}, []);

// ✅ 좋은 예: 필요할 때만 로드 (지연 로딩)
const onRequestTableAllData = async () => {
  return await loadTableAllData(); // 버튼 클릭 시에만 로드
};

3. 캐싱

// 전체 데이터를 캐싱하여 재사용
const [cachedTableAllData, setCachedTableAllData] = useState<any[]>([]);

const onRequestTableAllData = async () => {
  if (cachedTableAllData.length > 0) {
    console.log("캐시된 데이터 사용");
    return cachedTableAllData;
  }
  
  const data = await loadTableAllData();
  setCachedTableAllData(data);
  return data;
};

노드 플로우에서 데이터 사용

contextData 구조

노드 플로우 실행 시 전달되는 contextData는 다음과 같은 구조를 가집니다:

{
  buttonId: "btn_approve",
  screenId: 123,
  companyCode: "DEFAULT",
  userId: "user001",
  controlDataSource: "table-all",
  
  // 공통 데이터
  formData: { name: "홍길동" },
  
  // 소스별 데이터
  selectedRowsData: [...],      // table-selection
  tableAllData: [...],           // table-all
  flowSelectedData: [...],       // flow-selection
  flowStepAllData: [...],        // flow-step-all
  flowStepId: 2,                 // 현재 플로우 스텝 ID
  
  // 통합 데이터 (모든 노드에서 사용 가능)
  sourceData: [...]              // controlDataSource에 따라 결정된 데이터
}

노드에서 데이터 접근

// External Call 노드
{
  nodeType: "external-call",
  config: {
    url: "https://api.example.com/bulk-approve",
    method: "POST",
    body: {
      // sourceData를 사용하여 데이터 전달
      items: "{{sourceData}}",
      approver: "{{formData.approver}}"
    }
  }
}

// DDL 노드
{
  nodeType: "ddl",
  config: {
    sql: `
      UPDATE tasks 
      SET status = 'approved' 
      WHERE id IN ({{sourceData.map(d => d.id).join(',')}})
    `
  }
}

디버깅 및 로그

콘솔 로그 확인

버튼 클릭 시 다음과 같은 로그가 출력됩니다:

📊 데이터 소스 모드: {
  controlDataSource: "table-all",
  hasFormData: true,
  hasTableSelection: false,
  hasFlowSelection: false
}

📊 테이블 전체 데이터 로드 중...
✅ 테이블 전체 데이터 1,234건 로드 완료

🚀 노드 플로우 실행 시작: {
  flowId: 10,
  flowName: "전체 항목 승인",
  timing: "replace",
  sourceDataCount: 1234
}

에러 처리

// 데이터 로드 실패 시
 테이블 전체 데이터 로드 실패: Network error
🔔 Toast: "테이블 전체 데이터를 불러오지 못했습니다"

// 플로우 실행 실패 시
 플로우 실행 실패: 조건 불만족
🔔 Toast: "테이블 전체 조건 불만족: status === 'pending' (실제값: approved)"

마이그레이션 가이드

기존 설정에서 업그레이드

기존에 table-selection을 사용하던 버튼을 table-all로 변경하는 경우:

  1. 버튼 설정 변경: table-selectiontable-all
  2. 부모 컴포넌트 업데이트: onRequestTableAllData 콜백 추가
  3. 노드 플로우 업데이트: 대량 데이터 처리 로직 추가
  4. 테스트: 소량 데이터로 먼저 테스트 후 전체 적용

하위 호환성

  • 기존 form, table-selection, both 설정은 그대로 동작
  • 새로운 데이터 소스는 선택적으로 사용 가능
  • 기존 노드 플로우는 수정 없이 동작

베스트 프랙티스

1. 적절한 데이터 소스 선택

시나리오 권장 데이터 소스
단일 레코드 생성/수정 form
선택된 항목 일괄 처리 table-selection
전체 항목 일괄 처리 table-all
플로우 단계별 선택 처리 flow-selection
플로우 단계 전체 이동 flow-step-all
복잡한 통합 작업 all-sources

2. 성능 최적화

// ✅ 좋은 예: 배치 처리
const batchSize = 100;
for (let i = 0; i < sourceData.length; i += batchSize) {
  const batch = sourceData.slice(i, i + batchSize);
  await processBatch(batch);
}

// ❌ 나쁜 예: 동기 처리
for (const item of sourceData) {
  await processItem(item); // 1000개면 1000번 API 호출
}

3. 사용자 피드백

// 대량 데이터 처리 시 진행률 표시
toast.info(`${processed}/${total} 항목 처리 중...`, {
  id: "batch-progress"
});

문제 해결

Q1: 테이블 전체 데이터가 로드되지 않습니다

A: 부모 컴포넌트에 onRequestTableAllData 콜백이 구현되어 있는지 확인하세요.

// InteractiveScreenViewer.tsx 확인
<OptimizedButtonComponent
  onRequestTableAllData={async () => {
    // 이 함수가 구현되어 있어야 함
    return await fetchAllData();
  }}
/>

Q2: 플로우 스텝 전체 데이터가 빈 배열입니다

A:

  1. 플로우 스텝이 선택되어 있는지 확인
  2. flowSelectedStepId가 올바르게 전달되는지 확인
  3. onRequestFlowStepAllData 콜백이 구현되어 있는지 확인

Q3: 데이터가 너무 많아 브라우저가 느려집니다

A:

  1. 서버 사이드 처리 고려
  2. 배치 처리 사용
  3. 페이징 적용
  4. table-selection 사용 권장 (전체 대신 선택)

관련 파일

타입 정의

  • frontend/types/control-management.ts - ControlDataSource 타입

핵심 로직

  • frontend/lib/utils/nodeFlowButtonExecutor.ts - 데이터 준비 및 전달
  • frontend/components/screen/OptimizedButtonComponent.tsx - 버튼 컴포넌트

UI 설정

  • frontend/components/screen/config-panels/ButtonDataflowConfigPanel.tsx - 설정 패널

서비스

  • frontend/lib/services/optimizedButtonDataflowService.ts - 데이터 검증 및 처리

업데이트 이력

  • 2025-01-24: 초기 문서 작성
    • table-all 데이터 소스 추가
    • flow-step-all 데이터 소스 추가
    • all-sources 데이터 소스 추가
    • 지연 로딩 메커니즘 구현