1921 lines
62 KiB
Markdown
1921 lines
62 KiB
Markdown
|
|
# 🎯 노드 기반 데이터 제어 시스템 개선 계획
|
|||
|
|
|
|||
|
|
## 📋 문서 정보
|
|||
|
|
|
|||
|
|
- **작성일**: 2025-10-02
|
|||
|
|
- **최종 수정일**: 2025-10-02
|
|||
|
|
- **버전**: 1.5
|
|||
|
|
- **상태**: 🎉 Phase 1 완료! (100%)
|
|||
|
|
- **담당**: 개발팀
|
|||
|
|
|
|||
|
|
## 📈 구현 진행 상황
|
|||
|
|
|
|||
|
|
### ✅ 완료된 작업 (Phase 1)
|
|||
|
|
|
|||
|
|
#### Week 1 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ React Flow 11.10.4 통합 및 기본 설정
|
|||
|
|
- ✅ 라이브러리 설치 및 설정
|
|||
|
|
- ✅ 기본 캔버스 구현
|
|||
|
|
- ✅ 그리드 배경 및 줌/팬 기능
|
|||
|
|
- ✅ 기본 노드 타입 구현 (3개/3개)
|
|||
|
|
- ✅ 테이블 소스 노드 (TableSourceNode)
|
|||
|
|
- ✅ INSERT 액션 노드 (InsertActionNode)
|
|||
|
|
- ✅ 필드 매핑 노드 (FieldMappingNode)
|
|||
|
|
- ✅ 핵심 인프라
|
|||
|
|
- ✅ TypeScript 타입 정의 완료 (types/node-editor.ts)
|
|||
|
|
- ✅ Zustand 상태 관리 스토어 (flowEditorStore.ts)
|
|||
|
|
- ✅ 노드 팔레트 설정 (nodePaletteConfig.ts)
|
|||
|
|
|
|||
|
|
#### Week 2 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ 드래그 앤 드롭 기능
|
|||
|
|
- ✅ 도구 패널에서 캔버스로 드래그
|
|||
|
|
- ✅ 노드 이동 및 재배치
|
|||
|
|
- ✅ 다중 선택 및 그룹 이동
|
|||
|
|
- ✅ 연결선 그리기
|
|||
|
|
- ✅ 기본 연결 생성
|
|||
|
|
- ✅ 연결 검증 (타입 호환성, 순환 참조, 중복 연결)
|
|||
|
|
- ✅ 연결 스타일링 (smoothstep)
|
|||
|
|
- ✅ 추가 노드 타입 구현 (4개 완료)
|
|||
|
|
- ✅ 조건 분기 노드 (ConditionNode) - TRUE/FALSE 2개 출력
|
|||
|
|
- ✅ 외부 DB 소스 노드 (ExternalDBSourceNode) - DB 타입별 색상
|
|||
|
|
- ✅ UPDATE 액션 노드 (UpdateActionNode) - WHERE 조건 포함
|
|||
|
|
- ✅ DELETE 액션 노드 (DeleteActionNode) - 경고 메시지
|
|||
|
|
|
|||
|
|
**마일스톤 1 완료**: 7개 노드 타입 구현 완료 (58%)
|
|||
|
|
|
|||
|
|
#### Week 3 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ 속성 편집 기능 (완료)
|
|||
|
|
- ✅ 노드 선택 이벤트 핸들러 (onSelectionChange)
|
|||
|
|
- ✅ 속성 패널 프레임워크 (PropertiesPanel)
|
|||
|
|
- ✅ 노드 타입별 속성 라우팅
|
|||
|
|
- ✅ 7개 노드 속성 편집 UI 완성
|
|||
|
|
- ✅ TableSource: 테이블명, 스키마, 출력 필드
|
|||
|
|
- ✅ InsertAction: 필드 매핑, 배치 크기, 옵션
|
|||
|
|
- ✅ FieldMapping: 소스→타겟 매핑, 변환 함수
|
|||
|
|
- ✅ Condition: 12가지 연산자, AND/OR 로직
|
|||
|
|
- ✅ UpdateAction: WHERE 조건, 업데이트 필드
|
|||
|
|
- ✅ DeleteAction: WHERE 조건, 위험 경고 UI
|
|||
|
|
- ✅ ExternalDBSource: DB 타입별 색상, 연결 정보
|
|||
|
|
|
|||
|
|
**마일스톤 2 완료**: 속성 편집 기능 100% 완료 (7/7 노드)
|
|||
|
|
|
|||
|
|
#### Week 4 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ 저장/불러오기 기능 (완료)
|
|||
|
|
- ✅ 플로우 저장 API (신규/수정)
|
|||
|
|
- ✅ 플로우 목록 조회 API
|
|||
|
|
- ✅ 플로우 상세 조회 API
|
|||
|
|
- ✅ 플로우 삭제 API
|
|||
|
|
- ✅ JSON 직렬화/역직렬화
|
|||
|
|
- ✅ 불러오기 다이얼로그 UI
|
|||
|
|
- ✅ JSON 파일 내보내기
|
|||
|
|
- ✅ node_flows 테이블 생성
|
|||
|
|
- ✅ API 클라이언트 통합
|
|||
|
|
- ✅ JSONB 타입 처리 (문자열/객체 자동 변환)
|
|||
|
|
- ✅ **실제 저장/불러오기 동작 검증 완료**
|
|||
|
|
|
|||
|
|
**마일스톤 3 완료**: 저장/불러오기 100% 완료 및 검증
|
|||
|
|
|
|||
|
|
## 🎉 Phase 1 & Phase 2 완료!
|
|||
|
|
|
|||
|
|
모든 핵심 기능이 구현 및 테스트 완료되었습니다:
|
|||
|
|
|
|||
|
|
**Phase 1 (완료)**
|
|||
|
|
|
|||
|
|
- ✅ 7개 노드 타입 구현
|
|||
|
|
- ✅ 7개 속성 편집 UI
|
|||
|
|
- ✅ 저장/불러오기 시스템 (DB + JSON)
|
|||
|
|
- ✅ 검증 시스템
|
|||
|
|
- ✅ 드래그앤드롭 에디터
|
|||
|
|
- ✅ **실제 저장/불러오기 테스트 완료**
|
|||
|
|
|
|||
|
|
**Phase 2 (완료)**
|
|||
|
|
|
|||
|
|
- ✅ 12개 노드 타입 구현 (100%)
|
|||
|
|
- ✅ 12개 속성 편집 UI (100%)
|
|||
|
|
- ✅ REST API, UPSERT, 데이터 변환, 주석, 로그 노드 추가
|
|||
|
|
|
|||
|
|
### 🎯 다음 작업 (Phase 3)
|
|||
|
|
|
|||
|
|
#### Week 5 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ 남은 노드 타입 구현 (5개)
|
|||
|
|
|
|||
|
|
- ✅ UpsertAction: INSERT + UPDATE 결합 (ON CONFLICT)
|
|||
|
|
- ✅ DataTransform: 데이터 변환 (UPPERCASE, LOWERCASE, TRIM 등)
|
|||
|
|
- ✅ RestAPISource: REST API 호출
|
|||
|
|
- ✅ Comment: 주석 노드
|
|||
|
|
- ✅ Log: 로그 출력 노드
|
|||
|
|
|
|||
|
|
- ✅ 남은 속성 편집 패널 구현 (5개)
|
|||
|
|
- ✅ UpsertActionProperties: 충돌 키, 필드 매핑, 옵션
|
|||
|
|
- ✅ DataTransformProperties: 변환 규칙, 표현식
|
|||
|
|
- ✅ RestAPISourceProperties: URL, 메서드, 헤더, 인증
|
|||
|
|
- ✅ CommentProperties: 메모 내용
|
|||
|
|
- ✅ LogProperties: 로그 레벨, 메시지, 데이터 포함
|
|||
|
|
|
|||
|
|
**마일스톤 4 완료**: 노드 타입 100% 완료 (12/12)
|
|||
|
|
**마일스톤 5 완료**: 속성 패널 100% 완료 (12/12)
|
|||
|
|
|
|||
|
|
## 🎉 Phase 2 완료!
|
|||
|
|
|
|||
|
|
모든 노드 타입과 속성 패널이 구현되었습니다!
|
|||
|
|
|
|||
|
|
### 🎯 Phase 3 계획: 검증 및 실행 시스템
|
|||
|
|
|
|||
|
|
#### Week 6 - 완료 ✓
|
|||
|
|
|
|||
|
|
- ✅ 검증 시스템 강화
|
|||
|
|
- ✅ 순환 참조 검증 (DFS 알고리즘)
|
|||
|
|
- ✅ 노드별 필수 속성 검증 (12개 노드 타입)
|
|||
|
|
- ✅ Comment/Log 노드 독립 허용
|
|||
|
|
- ✅ 상세한 오류 메시지 및 노드 ID 포함
|
|||
|
|
|
|||
|
|
**마일스톤 6 완료**: 검증 시스템 100% 완료
|
|||
|
|
|
|||
|
|
#### 우선순위 1: 검증 시스템 강화 ✅ 완료
|
|||
|
|
|
|||
|
|
#### 우선순위 2: 플로우 실행 엔진 (추후 구현)
|
|||
|
|
|
|||
|
|
- ⏳ 노드 실행 로직
|
|||
|
|
- ⏳ 데이터 흐름 처리
|
|||
|
|
- ⏳ 에러 핸들링
|
|||
|
|
- ⏳ 트랜잭션 관리
|
|||
|
|
- ⏳ 플로우 목록 조회
|
|||
|
|
|
|||
|
|
### 📦 구현된 컴포넌트
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
frontend/
|
|||
|
|
├── types/
|
|||
|
|
│ └── node-editor.ts ✅ (완료)
|
|||
|
|
├── lib/
|
|||
|
|
│ └── stores/
|
|||
|
|
│ └── flowEditorStore.ts ✅ (완료)
|
|||
|
|
├── components/dataflow/node-editor/
|
|||
|
|
│ ├── FlowEditor.tsx ✅ (완료)
|
|||
|
|
│ ├── FlowToolbar.tsx ✅ (완료)
|
|||
|
|
│ ├── nodes/
|
|||
|
|
│ │ ├── TableSourceNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── ExternalDBSourceNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── ConditionNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── FieldMappingNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── InsertActionNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── UpdateActionNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── DeleteActionNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── RestAPISourceNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── DataTransformNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── UpsertActionNode.tsx ✅ (완료)
|
|||
|
|
│ │ ├── CommentNode.tsx ✅ (완료)
|
|||
|
|
│ │ └── LogNode.tsx ✅ (완료)
|
|||
|
|
│ ├── sidebar/
|
|||
|
|
│ │ ├── NodePalette.tsx ✅ (완료)
|
|||
|
|
│ │ └── nodePaletteConfig.ts ✅ (완료)
|
|||
|
|
│ └── panels/
|
|||
|
|
│ ├── PropertiesPanel.tsx ✅ (완료)
|
|||
|
|
│ └── properties/
|
|||
|
|
│ ├── TableSourceProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── ExternalDBSourceProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── ConditionProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── FieldMappingProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── InsertActionProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── UpdateActionProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── DeleteActionProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── UpsertActionProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── DataTransformProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── RestAPISourceProperties.tsx ✅ (완료)
|
|||
|
|
│ ├── CommentProperties.tsx ✅ (완료)
|
|||
|
|
│ └── LogProperties.tsx ✅ (완료)
|
|||
|
|
└── app/(main)/admin/dataflow/
|
|||
|
|
└── node-editor/
|
|||
|
|
└── page.tsx ✅ (완료)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 🎮 현재 사용 가능한 기능
|
|||
|
|
|
|||
|
|
- ✅ 노드 드래그 앤 드롭으로 캔버스에 추가
|
|||
|
|
- ✅ 노드 간 연결선 그리기
|
|||
|
|
- ✅ 노드 선택 및 속성 편집 (100%)
|
|||
|
|
- ✅ 줌/팬 컨트롤 (확대/축소/전체보기)
|
|||
|
|
- ✅ 미니맵 표시
|
|||
|
|
- ✅ 플로우 검증 (소스/액션 체크, 고아 노드 감지)
|
|||
|
|
- ✅ 반응형 레이아웃 (250px 사이드바 + 캔버스 + 350px 속성)
|
|||
|
|
- ✅ 7개 노드 타입 구현 (58%)
|
|||
|
|
- 데이터 소스: 테이블, 외부 DB
|
|||
|
|
- 변환/조건: 필드 매핑, 조건 분기 (TRUE/FALSE 출력)
|
|||
|
|
- 액션: INSERT, UPDATE, DELETE
|
|||
|
|
- ✅ 7개 노드 속성 편집 완성 (100%)
|
|||
|
|
- TableSource: 테이블/스키마 설정
|
|||
|
|
- InsertAction: 필드 매핑, 배치 옵션
|
|||
|
|
- FieldMapping: 소스→타겟, 변환 함수
|
|||
|
|
- Condition: 12가지 연산자, AND/OR
|
|||
|
|
- UpdateAction: WHERE 조건, 업데이트 필드
|
|||
|
|
- DeleteAction: WHERE 조건, 위험 경고
|
|||
|
|
- ExternalDBSource: DB 타입별 UI
|
|||
|
|
- ✅ 저장/불러오기 시스템 (100%)
|
|||
|
|
- DB 저장 (신규/수정)
|
|||
|
|
- 플로우 목록 조회
|
|||
|
|
- 플로우 불러오기
|
|||
|
|
- 플로우 삭제
|
|||
|
|
- JSON 파일 내보내기
|
|||
|
|
|
|||
|
|
### 📍 테스트 URL
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
http://localhost:3000/admin/dataflow/node-editor
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 현재 시스템 분석
|
|||
|
|
|
|||
|
|
### 현재 구조
|
|||
|
|
|
|||
|
|
현재 데이터 제어 시스템은 4단계 마법사 방식을 사용합니다:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Step 1: 연결 설정 (FROM/TO 테이블 선택)
|
|||
|
|
↓
|
|||
|
|
Step 2: 데이터 선택 (컬럼 매핑)
|
|||
|
|
↓
|
|||
|
|
Step 3: 조건 설정 (제어 조건)
|
|||
|
|
↓
|
|||
|
|
Step 4: 액션 설정 (INSERT/UPDATE/DELETE)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 문제점
|
|||
|
|
|
|||
|
|
#### 1. 사용성 문제
|
|||
|
|
|
|||
|
|
- ❌ **전체 흐름 파악 어려움**: 4단계를 모두 거쳐야 전체 구조 이해 가능
|
|||
|
|
- ❌ **수정 불편**: 이전 단계로 돌아가서 수정하기 번거로움
|
|||
|
|
- ❌ **복잡한 로직 표현 제한**: 다중 분기, 조건부 실행 등 표현 어려움
|
|||
|
|
- ❌ **시각화 제한**: "흐름 미리보기" 탭에서만 전체 구조 확인 가능
|
|||
|
|
|
|||
|
|
#### 2. 기능적 제한
|
|||
|
|
|
|||
|
|
- 단선형 흐름만 지원 (A → B → C)
|
|||
|
|
- 복잡한 데이터 변환 로직 구현 어려움
|
|||
|
|
- 디버깅 시 어느 단계에서 문제가 발생했는지 파악 어려움
|
|||
|
|
- 재사용 가능한 로직 패턴 저장 불가
|
|||
|
|
|
|||
|
|
#### 3. 학습 곡선
|
|||
|
|
|
|||
|
|
- 새로운 사용자가 4단계 프로세스를 이해하는데 시간 소요
|
|||
|
|
- 각 단계의 설정이 최종 결과에 어떤 영향을 주는지 직관적이지 않음
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 제안: 노드 기반 비주얼 에디터
|
|||
|
|
|
|||
|
|
### 핵심 개념
|
|||
|
|
|
|||
|
|
**블루프린트 스타일 노드 프로그래밍**
|
|||
|
|
|
|||
|
|
- 언리얼 엔진, N8N, Node-RED와 같은 비주얼 프로그래밍 방식 채택
|
|||
|
|
- 드래그 앤 드롭으로 노드 배치
|
|||
|
|
- 노드 간 연결선으로 데이터 흐름 표현
|
|||
|
|
- 실시간 시각적 피드백
|
|||
|
|
|
|||
|
|
### 주요 장점
|
|||
|
|
|
|||
|
|
#### 1. 직관성
|
|||
|
|
|
|||
|
|
- ✅ 전체 데이터 흐름을 한 화면에서 파악
|
|||
|
|
- ✅ 시각적으로 로직 구조 이해
|
|||
|
|
- ✅ 노드 간 관계가 명확하게 표현됨
|
|||
|
|
|
|||
|
|
#### 2. 유연성
|
|||
|
|
|
|||
|
|
- ✅ 자유로운 노드 배치 및 재배치
|
|||
|
|
- ✅ 복잡한 분기 로직 쉽게 구현
|
|||
|
|
- ✅ 동적으로 노드 추가/제거
|
|||
|
|
|
|||
|
|
#### 3. 생산성
|
|||
|
|
|
|||
|
|
- ✅ 드래그 앤 드롭으로 빠른 구성
|
|||
|
|
- ✅ 템플릿 시스템으로 재사용
|
|||
|
|
- ✅ 실시간 검증으로 오류 조기 발견
|
|||
|
|
|
|||
|
|
#### 4. 디버깅
|
|||
|
|
|
|||
|
|
- ✅ 각 노드별 실행 상태 시각화
|
|||
|
|
- ✅ 데이터 흐름 추적 가능
|
|||
|
|
- ✅ 병목 지점 쉽게 파악
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 UI/UX 디자인
|
|||
|
|
|
|||
|
|
### 전체 레이아웃
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌───────────────────────────────────────────────────────────────────────────┐
|
|||
|
|
│ 📋 제어 관리: 오라클 테스트2 [저장] [테스트 실행] [닫기] │
|
|||
|
|
├────────────────┬──────────────────────────────────────────────────────────┤
|
|||
|
|
│ 🔧 도구 패널 │ 🎨 캔버스 (노드 배치 영역) │
|
|||
|
|
│ (250px) │ (나머지 영역) │
|
|||
|
|
│ │ │
|
|||
|
|
│ ┌─ 데이터 소스 │ ┌────────────────────────────────────────────────────┐ │
|
|||
|
|
│ │ 📊 테이블 │ │ │ │
|
|||
|
|
│ │ 🔌 외부 DB │ │ 노드를 여기에 드래그 앤 드롭하세요 │ │
|
|||
|
|
│ │ 📁 REST API │ │ │ │
|
|||
|
|
│ │ 🌐 GraphQL │ │ [빈 캔버스] │ │
|
|||
|
|
│ └──────────────│ │ │ │
|
|||
|
|
│ │ └────────────────────────────────────────────────────┘ │
|
|||
|
|
│ ┌─ 변환/조건 │ │
|
|||
|
|
│ │ 🔀 필드 매핑 │ ┌─────────────────┐ │
|
|||
|
|
│ │ ⚡ 조건 분기 │ │ 미니맵 │ │
|
|||
|
|
│ │ 🔧 데이터 변환│ │ ┌───────────┐ │ │
|
|||
|
|
│ │ 🔄 루프 │ │ │ ▪ ▪ ▪ │ │ 150x100px │
|
|||
|
|
│ └──────────────│ │ │ ▪ ▪ │ │ │
|
|||
|
|
│ │ │ └───────────┘ │ │
|
|||
|
|
│ ┌─ 액션 │ └─────────────────┘ │
|
|||
|
|
│ │ ➕ INSERT │ │
|
|||
|
|
│ │ ✏️ UPDATE │ 컨트롤 바: [확대/축소] [전체보기] [그리드 ON/OFF] │
|
|||
|
|
│ │ ❌ DELETE │ │
|
|||
|
|
│ │ 🔄 UPSERT │ │
|
|||
|
|
│ └──────────────│ │
|
|||
|
|
│ │ │
|
|||
|
|
│ ┌─ 유틸리티 │ │
|
|||
|
|
│ │ 💬 주석 │ │
|
|||
|
|
│ │ 📦 그룹 │ │
|
|||
|
|
│ │ 🔍 로그 │ │
|
|||
|
|
│ └──────────────│ │
|
|||
|
|
└────────────────┴──────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 도구 패널 상세
|
|||
|
|
|
|||
|
|
#### 데이터 소스 섹션
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─ 데이터 소스 ─────────────────┐
|
|||
|
|
│ │
|
|||
|
|
│ 📊 내부 테이블 │
|
|||
|
|
│ ┌─────────────────────────┐ │
|
|||
|
|
│ │ [끌어서 캔버스에 배치] │ │
|
|||
|
|
│ └─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 🔌 외부 DB 연결 │
|
|||
|
|
│ ┌─────────────────────────┐ │
|
|||
|
|
│ │ [외부 데이터베이스] │ │
|
|||
|
|
│ └─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 📁 REST API │
|
|||
|
|
│ ┌─────────────────────────┐ │
|
|||
|
|
│ │ [HTTP 요청 노드] │ │
|
|||
|
|
│ └─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 🌐 GraphQL │
|
|||
|
|
│ ┌─────────────────────────┐ │
|
|||
|
|
│ │ [GraphQL 쿼리 노드] │ │
|
|||
|
|
│ └─────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
└───────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 노드 타입 정의
|
|||
|
|
|
|||
|
|
### 1. 데이터 소스 노드
|
|||
|
|
|
|||
|
|
#### 1.1 테이블 소스 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 📊 사용자정보 │ ← 파란색 헤더 (#3B82F6)
|
|||
|
|
│ user_info │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 📍 연결: 메인 DB │
|
|||
|
|
│ 📋 스키마: public │
|
|||
|
|
│ │
|
|||
|
|
│ 출력 필드: [모두 보기 ▼] │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ ○ user_id (integer) → │ │ ← 필드별 연결 포인트
|
|||
|
|
│ │ ○ user_name (varchar) → │ │
|
|||
|
|
│ │ ○ email (varchar) → │ │
|
|||
|
|
│ │ ○ created_at (timestamp) → │ │
|
|||
|
|
│ │ ○ updated_at (timestamp) → │ │
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ [설정 ⚙️] [프리뷰 👁️] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
노드 데이터 구조:
|
|||
|
|
{
|
|||
|
|
type: 'tableSource',
|
|||
|
|
data: {
|
|||
|
|
connectionId: 0,
|
|||
|
|
tableName: 'user_info',
|
|||
|
|
schema: 'public',
|
|||
|
|
fields: [
|
|||
|
|
{ name: 'user_id', type: 'integer', nullable: false },
|
|||
|
|
{ name: 'user_name', type: 'varchar', nullable: false },
|
|||
|
|
// ...
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 1.2 외부 DB 소스 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 🔌 Oracle DB │ ← 주황색 헤더 (#F59E0B)
|
|||
|
|
│ USERS 테이블 │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 📍 연결: Oracle 운영 서버 │
|
|||
|
|
│ 🔐 상태: 연결됨 ✅ │
|
|||
|
|
│ │
|
|||
|
|
│ 출력 필드: │
|
|||
|
|
│ ○ SALT (VARCHAR2) → │
|
|||
|
|
│ ○ USERNAME (VARCHAR2) → │
|
|||
|
|
│ ○ EMAIL (VARCHAR2) → │
|
|||
|
|
│ │
|
|||
|
|
│ [연결 테스트] [새로고침] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 1.3 REST API 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 📁 HTTP 요청 │ ← 초록색 헤더 (#10B981)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 메서드: [GET ▼] │
|
|||
|
|
│ URL: https://api.example.com/users │
|
|||
|
|
│ │
|
|||
|
|
│ 헤더: │
|
|||
|
|
│ Authorization: Bearer {token} │
|
|||
|
|
│ │
|
|||
|
|
│ 응답 필드: │
|
|||
|
|
│ ○ data.users → │
|
|||
|
|
│ ○ data.total → │
|
|||
|
|
│ │
|
|||
|
|
│ [요청 테스트] [저장] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 변환/조건 노드
|
|||
|
|
|
|||
|
|
#### 2.1 조건 분기 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ ⚡ 조건 검사 │ ← 노란색 헤더 (#EAB308)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ ← 입력 데이터 │
|
|||
|
|
│ │
|
|||
|
|
│ 조건식: │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ [user_id] [IS NOT NULL] [✓] │ │
|
|||
|
|
│ │ [AND] │ │
|
|||
|
|
│ │ [email] [LIKE] [%@%] [✓] │ │
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ [+ 조건 추가] │
|
|||
|
|
│ │
|
|||
|
|
│ 분기: │
|
|||
|
|
│ ✅ TRUE → │ ← 조건 충족 시
|
|||
|
|
│ ❌ FALSE → │ ← 조건 불충족 시
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
노드 데이터 구조:
|
|||
|
|
{
|
|||
|
|
type: 'condition',
|
|||
|
|
data: {
|
|||
|
|
conditions: [
|
|||
|
|
{ field: 'user_id', operator: 'IS_NOT_NULL', value: null },
|
|||
|
|
{ field: 'email', operator: 'LIKE', value: '%@%' }
|
|||
|
|
],
|
|||
|
|
logic: 'AND'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.2 필드 매핑 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 🔀 필드 매핑 │ ← 보라색 헤더 (#8B5CF6)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 입력: │
|
|||
|
|
│ ← user_id │
|
|||
|
|
│ ← user_name │
|
|||
|
|
│ ← email │
|
|||
|
|
│ ← created_at │
|
|||
|
|
│ │
|
|||
|
|
│ 매핑 규칙: │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ user_id → SALT │ │
|
|||
|
|
│ │ user_name → USERNAME │ │
|
|||
|
|
│ │ email → EMAIL │ │
|
|||
|
|
│ │ NOW() → CREATED_AT │ │ ← 함수/상수
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ [+ 매핑 추가] [자동 매핑] │
|
|||
|
|
│ │
|
|||
|
|
│ 출력 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
노드 데이터 구조:
|
|||
|
|
{
|
|||
|
|
type: 'fieldMapping',
|
|||
|
|
data: {
|
|||
|
|
mappings: [
|
|||
|
|
{ source: 'user_id', target: 'SALT', transform: null },
|
|||
|
|
{ source: 'user_name', target: 'USERNAME', transform: null },
|
|||
|
|
{ source: 'email', target: 'EMAIL', transform: null },
|
|||
|
|
{ source: null, target: 'CREATED_AT', transform: 'NOW()' }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.3 데이터 변환 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 🔧 데이터 변환 │ ← 청록색 헤더 (#06B6D4)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ ← 입력 데이터 │
|
|||
|
|
│ │
|
|||
|
|
│ 변환 규칙: │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ UPPER(user_name) │ │
|
|||
|
|
│ │ TRIM(email) │ │
|
|||
|
|
│ │ CONCAT(first_name, last_name) │ │
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ [+ 변환 추가] [함수 도움말] │
|
|||
|
|
│ │
|
|||
|
|
│ 출력 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 액션 노드
|
|||
|
|
|
|||
|
|
#### 3.1 INSERT 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ ➕ INSERT │ ← 초록색 헤더 (#22C55E)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 타겟: USERS │
|
|||
|
|
│ 연결: Oracle 운영 서버 │
|
|||
|
|
│ │
|
|||
|
|
│ ← 매핑 데이터 입력 │
|
|||
|
|
│ │
|
|||
|
|
│ 삽입 필드: │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ • SALT ← user_id │ │
|
|||
|
|
│ │ • USERNAME ← user_name │ │
|
|||
|
|
│ │ • EMAIL ← email │ │
|
|||
|
|
│ │ • PASSWORD ← [미매핑] ⚠️ │ │
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 옵션: │
|
|||
|
|
│ ☑ 중복 시 무시 │
|
|||
|
|
│ ☐ 배치 처리 (1000건) │
|
|||
|
|
│ │
|
|||
|
|
│ ✅ 완료 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2 UPDATE 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ ✏️ UPDATE │ ← 파란색 헤더 (#3B82F6)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 타겟: user_info │
|
|||
|
|
│ 연결: 메인 DB │
|
|||
|
|
│ │
|
|||
|
|
│ ← 데이터 입력 │
|
|||
|
|
│ │
|
|||
|
|
│ 조건 (WHERE): │
|
|||
|
|
│ user_id = {input.user_id} │
|
|||
|
|
│ │
|
|||
|
|
│ 업데이트 필드: │
|
|||
|
|
│ ┌─────────────────────────────────┐ │
|
|||
|
|
│ │ • user_name ← new_name │ │
|
|||
|
|
│ │ • updated_at ← NOW() │ │
|
|||
|
|
│ └─────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ ✅ 완료 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3 DELETE 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ ❌ DELETE │ ← 빨간색 헤더 (#EF4444)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 타겟: temp_data │
|
|||
|
|
│ 연결: 메인 DB │
|
|||
|
|
│ │
|
|||
|
|
│ ← 데이터 입력 │
|
|||
|
|
│ │
|
|||
|
|
│ 조건 (WHERE): │
|
|||
|
|
│ created_at < DATE_SUB(NOW(), 7) │
|
|||
|
|
│ │
|
|||
|
|
│ ⚠️ 경고: │
|
|||
|
|
│ 삭제 작업은 되돌릴 수 없습니다 │
|
|||
|
|
│ │
|
|||
|
|
│ ☑ 삭제 전 확인 │
|
|||
|
|
│ │
|
|||
|
|
│ ✅ 완료 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 유틸리티 노드
|
|||
|
|
|
|||
|
|
#### 4.1 주석 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 💬 주석 │ ← 회색 헤더 (#6B7280)
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ 사용자 데이터를 Oracle DB로 동기화 │
|
|||
|
|
│ │
|
|||
|
|
│ 작성자: 김주석 │
|
|||
|
|
│ 날짜: 2025-10-02 │
|
|||
|
|
│ │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2 로그 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 🔍 로그 출력 │ ← 회색 헤더
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ ← 입력 데이터 │
|
|||
|
|
│ │
|
|||
|
|
│ 로그 레벨: [INFO ▼] │
|
|||
|
|
│ 메시지: "데이터 처리 완료: {count}" │
|
|||
|
|
│ │
|
|||
|
|
│ 출력 → │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📐 실제 사용 예시
|
|||
|
|
|
|||
|
|
### 예시 1: 간단한 데이터 복사
|
|||
|
|
|
|||
|
|
#### 현재 시스템
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Step 1: user_info 선택
|
|||
|
|
Step 2: USERS (Oracle) 선택
|
|||
|
|
Step 3: 조건 없음
|
|||
|
|
Step 4: INSERT + 필드 매핑 4개
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 노드 기반 시스템
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
캔버스 뷰:
|
|||
|
|
|
|||
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ 📊 user_info │ │ 🔀 필드 매핑 │ │ ➕ INSERT │
|
|||
|
|
│ │═══════>│ │═══════>│ USERS │
|
|||
|
|
│ user_id ○─┼───────>│ 4개 매핑 │ │ (Oracle) │
|
|||
|
|
│ user_name ○─┼───────>│ │ │ │
|
|||
|
|
│ email ○─┼───────>│ │ │ │
|
|||
|
|
└──────────────┘ └──────────────┘ └──────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 예시 2: 조건부 데이터 처리
|
|||
|
|
|
|||
|
|
#### 시나리오
|
|||
|
|
|
|||
|
|
- user_info에서 데이터 읽기
|
|||
|
|
- user_id가 NULL이 아니고 email이 유효한 경우만 처리
|
|||
|
|
- 조건 통과 시 Oracle DB에 INSERT
|
|||
|
|
|
|||
|
|
#### 노드 배치
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────┐ ┌──────────────┐ TRUE ┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ 📊 user_info │ │ ⚡ 조건 검사 │═══════>│ 🔀 필드 매핑 │ │ ➕ INSERT │
|
|||
|
|
│ │═══════>│ │ │ │═══════>│ USERS │
|
|||
|
|
│ user_id ○─┼───────>│ user_id │ │ 4개 매핑 │ │ │
|
|||
|
|
│ user_name ○─┼─┐ │ IS NOT NULL │ │ │ │ │
|
|||
|
|
│ email ○─┼─┼─────>│ AND │ │ │ │ │
|
|||
|
|
└──────────────┘ │ │ email LIKE │ FALSE │ │ │ │
|
|||
|
|
│ │ '%@%' │═══════>│ [중단] │ │ │
|
|||
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘
|
|||
|
|
│ ↑
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 예시 3: 복잡한 다중 분기
|
|||
|
|
|
|||
|
|
#### 시나리오
|
|||
|
|
|
|||
|
|
- 사용자 타입에 따라 다른 테이블에 저장
|
|||
|
|
- 관리자 → admin_users
|
|||
|
|
- 일반 사용자 → regular_users
|
|||
|
|
- 게스트 → guest_logs
|
|||
|
|
|
|||
|
|
#### 노드 배치
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ 🔀 매핑1 │ │ ➕ INSERT │
|
|||
|
|
admin ═══>│ │═══════>│ admin_users │
|
|||
|
|
╱ └──────────────┘ └──────────────┘
|
|||
|
|
┌──────────────┐ ┌──╱───────────┐
|
|||
|
|
│ 📊 user_info │ │ ⚡ 타입 분기 │ ┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ │═══════>│ │ user ═══>│ 🔀 매핑2 │ │ ➕ INSERT │
|
|||
|
|
│ user_type ○─┼───────>│ user_type │ │ │═══════>│ regular_users│
|
|||
|
|
└──────────────┘ │ │ └──────────────┘ └──────────────┘
|
|||
|
|
└──╲───────────┘
|
|||
|
|
╲ ┌──────────────┐ ┌──────────────┐
|
|||
|
|
guest ════>│ 🔀 매핑3 │ │ ➕ INSERT │
|
|||
|
|
│ │═══════>│ guest_logs │
|
|||
|
|
└──────────────┘ └──────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎮 주요 기능 명세
|
|||
|
|
|
|||
|
|
### 1. 드래그 앤 드롭
|
|||
|
|
|
|||
|
|
#### 1.1 노드 추가
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 사용자 액션
|
|||
|
|
1. 좌측 도구 패널에서 노드 아이템 클릭
|
|||
|
|
2. 캔버스로 드래그
|
|||
|
|
3. 원하는 위치에 드롭
|
|||
|
|
|
|||
|
|
// 시스템 동작
|
|||
|
|
- 마우스 커서를 따라 노드 프리뷰 표시
|
|||
|
|
- 드롭 가능 영역 하이라이트
|
|||
|
|
- 드롭 시 새 노드 생성 및 배치
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 1.2 노드 이동
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 사용자 액션
|
|||
|
|
1. 캔버스의 노드 헤더 클릭
|
|||
|
|
2. 원하는 위치로 드래그
|
|||
|
|
3. 드롭하여 재배치
|
|||
|
|
|
|||
|
|
// 시스템 동작
|
|||
|
|
- 연결된 선들이 함께 움직임
|
|||
|
|
- 그리드 스냅 옵션 (10px 단위)
|
|||
|
|
- 다중 선택 시 여러 노드 동시 이동
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 1.3 다중 선택
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 방법 1: Shift + 클릭
|
|||
|
|
노드를 하나씩 Shift + 클릭하여 선택
|
|||
|
|
|
|||
|
|
// 방법 2: 드래그 영역 선택
|
|||
|
|
빈 공간을 드래그하여 사각형 영역 내 노드 선택
|
|||
|
|
|
|||
|
|
// 방법 3: Ctrl + A
|
|||
|
|
전체 노드 선택
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 연결선 그리기
|
|||
|
|
|
|||
|
|
#### 2.1 연결 생성
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 단계별 프로세스
|
|||
|
|
1. 출력 포인트(○) 클릭
|
|||
|
|
2. 마우스를 드래그하여 선 그리기
|
|||
|
|
3. 입력 포인트에 드롭하여 연결
|
|||
|
|
|
|||
|
|
// 시각적 피드백
|
|||
|
|
- 드래그 중 임시 선 표시
|
|||
|
|
- 호환되는 입력 포인트 하이라이트
|
|||
|
|
- 호환되지 않는 포인트 비활성화
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.2 연결 검증
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 타입 검증
|
|||
|
|
const validateConnection = (source, target) => {
|
|||
|
|
// 데이터 타입 호환성 체크
|
|||
|
|
if (!isCompatibleType(source.dataType, target.dataType)) {
|
|||
|
|
return { valid: false, error: "데이터 타입 불일치" };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 순환 참조 체크
|
|||
|
|
if (hasCircularReference(source, target)) {
|
|||
|
|
return { valid: false, error: "순환 참조 감지" };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 중복 연결 체크
|
|||
|
|
if (isDuplicateConnection(source, target)) {
|
|||
|
|
return { valid: false, error: "이미 연결되어 있음" };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return { valid: true };
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.3 연결 스타일
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 연결선 종류
|
|||
|
|
1. 데이터 흐름: 굵은 곡선 (베지어 커브)
|
|||
|
|
2. 필드 연결: 가는 직선
|
|||
|
|
3. 조건 분기: 점선 (TRUE/FALSE)
|
|||
|
|
|
|||
|
|
// 색상 코딩
|
|||
|
|
- 정상: #3B82F6 (파란색)
|
|||
|
|
- 경고: #F59E0B (주황색)
|
|||
|
|
- 오류: #EF4444 (빨간색)
|
|||
|
|
- 비활성: #9CA3AF (회색)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 실시간 검증
|
|||
|
|
|
|||
|
|
#### 3.1 구문 검증
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 필드명 검증
|
|||
|
|
validateFieldName(fieldName) {
|
|||
|
|
// 존재하지 않는 필드
|
|||
|
|
if (!sourceFields.includes(fieldName)) {
|
|||
|
|
return error('필드를 찾을 수 없습니다');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// SQL 표현식 검증
|
|||
|
|
validateSQLExpression(expression) {
|
|||
|
|
try {
|
|||
|
|
// 기본 SQL 파싱
|
|||
|
|
parseSQLExpression(expression);
|
|||
|
|
return success();
|
|||
|
|
} catch (e) {
|
|||
|
|
return error('잘못된 SQL 표현식');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2 논리 검증
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 필수 연결 체크
|
|||
|
|
validateRequiredConnections(node) {
|
|||
|
|
if (node.type === 'action' && !node.hasInput) {
|
|||
|
|
return error('입력 데이터가 필요합니다');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 고아 노드 감지
|
|||
|
|
findOrphanNodes() {
|
|||
|
|
return nodes.filter(node =>
|
|||
|
|
!node.hasInput &&
|
|||
|
|
!node.hasOutput &&
|
|||
|
|
node.type !== 'source'
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3 시각적 피드백
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
노드 상태 표시:
|
|||
|
|
✅ 정상: 초록색 체크마크
|
|||
|
|
⚠️ 경고: 노란색 경고 아이콘
|
|||
|
|
❌ 오류: 빨간색 X 아이콘
|
|||
|
|
⏳ 미완성: 회색 점선 테두리
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 그룹화 및 주석
|
|||
|
|
|
|||
|
|
#### 4.1 그룹 노드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─ 사용자 데이터 처리 그룹 ─────────────────────────────────┐
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|||
|
|
│ │ 소스 │═══════>│ 변환 │═══════>│ 액션 │ │
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ 💬 주석: Oracle DB 동기화 로직 │
|
|||
|
|
└────────────────────────────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
기능:
|
|||
|
|
- 그룹 단위 이동
|
|||
|
|
- 그룹 접기/펼치기
|
|||
|
|
- 그룹 색상 지정
|
|||
|
|
- 그룹 내보내기/가져오기
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2 주석 시스템
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
주석 타입:
|
|||
|
|
1. 노드 주석: 특정 노드에 첨부
|
|||
|
|
2. 플로팅 주석: 캔버스에 독립적으로 배치
|
|||
|
|
3. 연결선 주석: 연결선에 레이블 추가
|
|||
|
|
|
|||
|
|
표시 옵션:
|
|||
|
|
- 항상 표시
|
|||
|
|
- 마우스 오버 시 표시
|
|||
|
|
- 클릭 시 표시
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 기술 스택
|
|||
|
|
|
|||
|
|
### 1. 노드 에디터 라이브러리 비교
|
|||
|
|
|
|||
|
|
| 라이브러리 | 장점 | 단점 | 추천도 |
|
|||
|
|
| ----------------- | ---------------------------------------------------------------------------- | ----------------------------------------- | ---------- |
|
|||
|
|
| **React Flow** | • 가장 인기있음<br>• 풍부한 예제<br>• TypeScript 지원<br>• 커스터마이징 용이 | • 복잡한 로직은 직접 구현 | ⭐⭐⭐⭐⭐ |
|
|||
|
|
| **Rete.js** | • 강력한 플러그인 시스템<br>• 자동 레이아웃 | • 학습 곡선 높음<br>• React 통합 까다로움 | ⭐⭐⭐⭐ |
|
|||
|
|
| **react-diagram** | • 간단한 구조 | • 기능 제한적<br>• 업데이트 느림 | ⭐⭐⭐ |
|
|||
|
|
|
|||
|
|
### 2. React Flow 선택 이유
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 1. 쉬운 설치 및 설정
|
|||
|
|
npm install reactflow
|
|||
|
|
|
|||
|
|
// 2. 간단한 초기 설정
|
|||
|
|
import ReactFlow, { MiniMap, Controls, Background } from 'reactflow';
|
|||
|
|
import 'reactflow/dist/style.css';
|
|||
|
|
|
|||
|
|
function FlowEditor() {
|
|||
|
|
return (
|
|||
|
|
<ReactFlow nodes={nodes} edges={edges}>
|
|||
|
|
<MiniMap />
|
|||
|
|
<Controls />
|
|||
|
|
<Background />
|
|||
|
|
</ReactFlow>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 커스텀 노드 쉽게 구현
|
|||
|
|
const nodeTypes = {
|
|||
|
|
tableSource: TableSourceNode,
|
|||
|
|
condition: ConditionNode,
|
|||
|
|
action: ActionNode,
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
<ReactFlow nodeTypes={nodeTypes} ... />
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 핵심 컴포넌트 구조
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
frontend/components/dataflow/node-editor/
|
|||
|
|
├── FlowEditor.tsx # 메인 에디터 컴포넌트
|
|||
|
|
├── nodes/ # 노드 컴포넌트들
|
|||
|
|
│ ├── TableSourceNode.tsx
|
|||
|
|
│ ├── ExternalDBNode.tsx
|
|||
|
|
│ ├── ConditionNode.tsx
|
|||
|
|
│ ├── FieldMappingNode.tsx
|
|||
|
|
│ ├── InsertActionNode.tsx
|
|||
|
|
│ ├── UpdateActionNode.tsx
|
|||
|
|
│ ├── DeleteActionNode.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── edges/ # 커스텀 엣지
|
|||
|
|
│ ├── DataFlowEdge.tsx
|
|||
|
|
│ ├── ConditionEdge.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── sidebar/ # 도구 패널
|
|||
|
|
│ ├── NodePalette.tsx
|
|||
|
|
│ ├── NodeLibrary.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── panels/ # 설정 패널
|
|||
|
|
│ ├── NodePropertiesPanel.tsx
|
|||
|
|
│ ├── ValidationPanel.tsx
|
|||
|
|
│ └── index.ts
|
|||
|
|
├── hooks/ # 커스텀 훅
|
|||
|
|
│ ├── useNodeValidation.ts
|
|||
|
|
│ ├── useAutoLayout.ts
|
|||
|
|
│ └── useFlowExecution.ts
|
|||
|
|
└── utils/ # 유틸리티
|
|||
|
|
├── nodeFactory.ts
|
|||
|
|
├── flowValidator.ts
|
|||
|
|
└── flowSerializer.ts
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 데이터 구조
|
|||
|
|
|
|||
|
|
#### 4.1 노드 데이터 모델
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 기본 노드 인터페이스
|
|||
|
|
interface BaseNode {
|
|||
|
|
id: string;
|
|||
|
|
type: string;
|
|||
|
|
position: { x: number; y: number };
|
|||
|
|
data: any;
|
|||
|
|
style?: CSSProperties;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 테이블 소스 노드
|
|||
|
|
interface TableSourceNode extends BaseNode {
|
|||
|
|
type: "tableSource";
|
|||
|
|
data: {
|
|||
|
|
connectionId: number;
|
|||
|
|
tableName: string;
|
|||
|
|
schema: string;
|
|||
|
|
fields: Array<{
|
|||
|
|
name: string;
|
|||
|
|
type: string;
|
|||
|
|
nullable: boolean;
|
|||
|
|
primaryKey: boolean;
|
|||
|
|
}>;
|
|||
|
|
filters?: Array<{
|
|||
|
|
field: string;
|
|||
|
|
operator: string;
|
|||
|
|
value: any;
|
|||
|
|
}>;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 조건 노드
|
|||
|
|
interface ConditionNode extends BaseNode {
|
|||
|
|
type: "condition";
|
|||
|
|
data: {
|
|||
|
|
conditions: Array<{
|
|||
|
|
field: string;
|
|||
|
|
operator:
|
|||
|
|
| "EQUALS"
|
|||
|
|
| "NOT_EQUALS"
|
|||
|
|
| "GREATER_THAN"
|
|||
|
|
| "LESS_THAN"
|
|||
|
|
| "LIKE"
|
|||
|
|
| "IN"
|
|||
|
|
| "IS_NULL"
|
|||
|
|
| "IS_NOT_NULL";
|
|||
|
|
value: any;
|
|||
|
|
}>;
|
|||
|
|
logic: "AND" | "OR";
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 액션 노드
|
|||
|
|
interface ActionNode extends BaseNode {
|
|||
|
|
type: "insertAction" | "updateAction" | "deleteAction" | "upsertAction";
|
|||
|
|
data: {
|
|||
|
|
targetConnection: number;
|
|||
|
|
targetTable: string;
|
|||
|
|
fieldMappings: Array<{
|
|||
|
|
sourceField: string;
|
|||
|
|
targetField: string;
|
|||
|
|
transform?: string;
|
|||
|
|
}>;
|
|||
|
|
options?: {
|
|||
|
|
batchSize?: number;
|
|||
|
|
ignoreErrors?: boolean;
|
|||
|
|
upsertKey?: string[];
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2 연결선 데이터 모델
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface Edge {
|
|||
|
|
id: string;
|
|||
|
|
source: string; // 출발 노드 ID
|
|||
|
|
target: string; // 도착 노드 ID
|
|||
|
|
sourceHandle?: string; // 출발 핸들 ID (필드별 연결 시)
|
|||
|
|
targetHandle?: string; // 도착 핸들 ID
|
|||
|
|
type?: "default" | "smoothstep" | "step" | "straight";
|
|||
|
|
animated?: boolean;
|
|||
|
|
label?: string;
|
|||
|
|
style?: CSSProperties;
|
|||
|
|
data?: {
|
|||
|
|
dataType?: string;
|
|||
|
|
validation?: {
|
|||
|
|
valid: boolean;
|
|||
|
|
errors?: string[];
|
|||
|
|
};
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 조건 분기 엣지
|
|||
|
|
interface ConditionalEdge extends Edge {
|
|||
|
|
data: {
|
|||
|
|
condition: "TRUE" | "FALSE";
|
|||
|
|
label: string;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.3 전체 플로우 데이터
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
interface DataFlow {
|
|||
|
|
id: number;
|
|||
|
|
name: string;
|
|||
|
|
description: string;
|
|||
|
|
companyCode: string;
|
|||
|
|
nodes: BaseNode[];
|
|||
|
|
edges: Edge[];
|
|||
|
|
viewport: {
|
|||
|
|
x: number;
|
|||
|
|
y: number;
|
|||
|
|
zoom: number;
|
|||
|
|
};
|
|||
|
|
metadata: {
|
|||
|
|
createdAt: string;
|
|||
|
|
updatedAt: string;
|
|||
|
|
createdBy: string;
|
|||
|
|
version: number;
|
|||
|
|
tags?: string[];
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. 상태 관리
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// Zustand를 사용한 플로우 상태 관리
|
|||
|
|
import create from "zustand";
|
|||
|
|
|
|||
|
|
interface FlowState {
|
|||
|
|
nodes: Node[];
|
|||
|
|
edges: Edge[];
|
|||
|
|
selectedNodes: string[];
|
|||
|
|
selectedEdges: string[];
|
|||
|
|
|
|||
|
|
// 노드 관리
|
|||
|
|
addNode: (node: Node) => void;
|
|||
|
|
updateNode: (id: string, data: Partial<Node>) => void;
|
|||
|
|
removeNode: (id: string) => void;
|
|||
|
|
|
|||
|
|
// 엣지 관리
|
|||
|
|
addEdge: (edge: Edge) => void;
|
|||
|
|
updateEdge: (id: string, data: Partial<Edge>) => void;
|
|||
|
|
removeEdge: (id: string) => void;
|
|||
|
|
|
|||
|
|
// 선택 관리
|
|||
|
|
selectNode: (id: string, multi?: boolean) => void;
|
|||
|
|
clearSelection: () => void;
|
|||
|
|
|
|||
|
|
// 검증
|
|||
|
|
validateFlow: () => ValidationResult;
|
|||
|
|
|
|||
|
|
// 실행
|
|||
|
|
executeFlow: () => Promise<ExecutionResult>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const useFlowStore = create<FlowState>((set, get) => ({
|
|||
|
|
// ... 구현
|
|||
|
|
}));
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 비교 분석
|
|||
|
|
|
|||
|
|
### 현재 시스템 vs 노드 기반 시스템
|
|||
|
|
|
|||
|
|
| 측면 | 현재 시스템 | 노드 기반 시스템 | 개선도 |
|
|||
|
|
| --------------- | --------------------- | -------------------- | ------ |
|
|||
|
|
| **학습 곡선** | 중간 (4단계 프로세스) | 쉬움 (시각적 직관성) | +40% |
|
|||
|
|
| **전체 파악** | 어려움 (단계별 분리) | 쉬움 (한눈에 파악) | +60% |
|
|||
|
|
| **수정 편의성** | 불편 (단계 이동 필요) | 편리 (직접 수정) | +50% |
|
|||
|
|
| **복잡한 로직** | 제한적 (선형 흐름) | 우수 (다중 분기) | +80% |
|
|||
|
|
| **재사용성** | 낮음 (수동 복사) | 높음 (템플릿 시스템) | +70% |
|
|||
|
|
| **디버깅** | 어려움 (로그 확인) | 쉬움 (시각적 추적) | +65% |
|
|||
|
|
| **협업** | 보통 (설명 필요) | 우수 (자체 문서화) | +55% |
|
|||
|
|
| **성능** | 양호 | 양호 (동일) | 0% |
|
|||
|
|
|
|||
|
|
### 사용자 시나리오별 비교
|
|||
|
|
|
|||
|
|
#### 시나리오 1: 간단한 테이블 복사
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
현재: 4단계 × 평균 2분 = 8분
|
|||
|
|
노드: 드래그 3개 + 연결 2개 = 3분
|
|||
|
|
개선: 62.5% 단축
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 시나리오 2: 조건부 다중 액션
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
현재: 4단계 × 5분 + 조건 설정 5분 = 25분
|
|||
|
|
노드: 드래그 7개 + 연결 8개 + 설정 5분 = 12분
|
|||
|
|
개선: 52% 단축
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 시나리오 3: 복잡한 데이터 변환
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
현재: 여러 제어를 순차적으로 생성 = 45분
|
|||
|
|
노드: 하나의 플로우에서 모두 처리 = 20분
|
|||
|
|
개선: 55.5% 단축
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 구현 로드맵
|
|||
|
|
|
|||
|
|
### Phase 1: 기본 노드 에디터 (2주)
|
|||
|
|
|
|||
|
|
#### Week 1
|
|||
|
|
|
|||
|
|
- [ ] React Flow 통합 및 기본 설정
|
|||
|
|
- [ ] 라이브러리 설치 및 설정
|
|||
|
|
- [ ] 기본 캔버스 구현
|
|||
|
|
- [ ] 그리드 배경 및 줌/팬 기능
|
|||
|
|
- [ ] 기본 노드 타입 구현
|
|||
|
|
- [ ] 테이블 소스 노드
|
|||
|
|
- [ ] INSERT 액션 노드
|
|||
|
|
- [ ] 필드 매핑 노드
|
|||
|
|
|
|||
|
|
#### Week 2
|
|||
|
|
|
|||
|
|
- [ ] 드래그 앤 드롭 기능
|
|||
|
|
- [ ] 도구 패널에서 캔버스로 드래그
|
|||
|
|
- [ ] 노드 이동 및 재배치
|
|||
|
|
- [ ] 다중 선택 및 그룹 이동
|
|||
|
|
- [ ] 연결선 그리기
|
|||
|
|
- [ ] 기본 연결 생성
|
|||
|
|
- [ ] 연결 검증
|
|||
|
|
- [ ] 연결 스타일링
|
|||
|
|
- [ ] 데이터 저장/불러오기
|
|||
|
|
- [ ] JSON 직렬화
|
|||
|
|
- [ ] 백엔드 API 연동
|
|||
|
|
|
|||
|
|
**마일스톤 1**: 기본적인 테이블 → 필드 매핑 → INSERT 플로우 구현
|
|||
|
|
|
|||
|
|
### Phase 2: 고급 기능 (2주)
|
|||
|
|
|
|||
|
|
#### Week 3
|
|||
|
|
|
|||
|
|
- [ ] 추가 노드 타입
|
|||
|
|
- [ ] 외부 DB 소스 노드
|
|||
|
|
- [ ] 조건 분기 노드
|
|||
|
|
- [ ] UPDATE/DELETE 액션 노드
|
|||
|
|
- [ ] 데이터 변환 노드
|
|||
|
|
- [ ] SQL 함수 지원
|
|||
|
|
- [ ] 커스텀 표현식
|
|||
|
|
- [ ] 노드 설정 패널
|
|||
|
|
- [ ] 우측 속성 패널
|
|||
|
|
- [ ] 인라인 편집
|
|||
|
|
- [ ] 필드 자동 완성
|
|||
|
|
|
|||
|
|
#### Week 4
|
|||
|
|
|
|||
|
|
- [ ] 실시간 검증 시스템
|
|||
|
|
- [ ] 구문 검증
|
|||
|
|
- [ ] 논리 검증
|
|||
|
|
- [ ] 타입 검증
|
|||
|
|
- [ ] 조건부 실행
|
|||
|
|
- [ ] TRUE/FALSE 분기
|
|||
|
|
- [ ] 다중 조건 처리
|
|||
|
|
- [ ] 오류 표시 및 해결
|
|||
|
|
- [ ] 오류 하이라이트
|
|||
|
|
- [ ] 오류 메시지 툴팁
|
|||
|
|
- [ ] 자동 수정 제안
|
|||
|
|
|
|||
|
|
**마일스톤 2**: 조건 분기 및 다중 액션을 포함한 복잡한 플로우 구현
|
|||
|
|
|
|||
|
|
### Phase 3: UX 개선 (1주)
|
|||
|
|
|
|||
|
|
#### Week 5
|
|||
|
|
|
|||
|
|
- [ ] 미니맵
|
|||
|
|
- [ ] 전체 플로우 미리보기
|
|||
|
|
- [ ] 현재 뷰포트 표시
|
|||
|
|
- [ ] 미니맵 클릭 네비게이션
|
|||
|
|
- [ ] 줌/팬 컨트롤
|
|||
|
|
- [ ] 줌 인/아웃 버튼
|
|||
|
|
- [ ] 전체 보기 버튼
|
|||
|
|
- [ ] 선택된 노드로 포커스
|
|||
|
|
- [ ] 노드 템플릿 시스템
|
|||
|
|
- [ ] 자주 사용하는 패턴 저장
|
|||
|
|
- [ ] 템플릿 갤러리
|
|||
|
|
- [ ] 드래그로 템플릿 적용
|
|||
|
|
- [ ] 키보드 단축키
|
|||
|
|
- [ ] Ctrl+C/V: 복사/붙여넣기
|
|||
|
|
- [ ] Delete: 삭제
|
|||
|
|
- [ ] Ctrl+Z/Y: 실행 취소/다시 실행
|
|||
|
|
- [ ] Ctrl+A: 전체 선택
|
|||
|
|
- [ ] Space + Drag: 팬
|
|||
|
|
- [ ] 튜토리얼 및 도움말
|
|||
|
|
- [ ] 첫 방문자 가이드
|
|||
|
|
- [ ] 인터랙티브 튜토리얼
|
|||
|
|
- [ ] 컨텍스트 도움말
|
|||
|
|
|
|||
|
|
**마일스톤 3**: 사용자 친화적인 인터페이스 완성
|
|||
|
|
|
|||
|
|
### Phase 4: 고급 기능 (1주)
|
|||
|
|
|
|||
|
|
#### Week 6
|
|||
|
|
|
|||
|
|
- [ ] 그룹화 기능
|
|||
|
|
- [ ] 노드 그룹 생성
|
|||
|
|
- [ ] 그룹 접기/펼치기
|
|||
|
|
- [ ] 그룹 색상 및 라벨
|
|||
|
|
- [ ] 주석 시스템
|
|||
|
|
- [ ] 노드 주석
|
|||
|
|
- [ ] 플로팅 주석
|
|||
|
|
- [ ] 연결선 라벨
|
|||
|
|
- [ ] 실행 추적 (디버그 모드)
|
|||
|
|
- [ ] 노드별 실행 상태 표시
|
|||
|
|
- [ ] 데이터 흐름 애니메이션
|
|||
|
|
- [ ] 실행 로그 패널
|
|||
|
|
- [ ] 중단점 설정
|
|||
|
|
- [ ] 버전 관리
|
|||
|
|
- [ ] 플로우 버전 히스토리
|
|||
|
|
- [ ] 버전 비교
|
|||
|
|
- [ ] 이전 버전 복원
|
|||
|
|
- [ ] 내보내기/가져오기
|
|||
|
|
- [ ] JSON 파일 내보내기
|
|||
|
|
- [ ] JSON 파일 가져오기
|
|||
|
|
- [ ] 이미지 내보내기 (PNG/SVG)
|
|||
|
|
- [ ] 템플릿 공유
|
|||
|
|
|
|||
|
|
**마일스톤 4**: 프로덕션 레디 기능 완성
|
|||
|
|
|
|||
|
|
### Phase 5: 최적화 및 테스트 (1주)
|
|||
|
|
|
|||
|
|
#### Week 7
|
|||
|
|
|
|||
|
|
- [ ] 성능 최적화
|
|||
|
|
- [ ] 대규모 플로우 렌더링 최적화
|
|||
|
|
- [ ] 가상 스크롤링
|
|||
|
|
- [ ] 레이지 로딩
|
|||
|
|
- [ ] 단위 테스트
|
|||
|
|
- [ ] 노드 컴포넌트 테스트
|
|||
|
|
- [ ] 검증 로직 테스트
|
|||
|
|
- [ ] 플로우 실행 테스트
|
|||
|
|
- [ ] 통합 테스트
|
|||
|
|
- [ ] E2E 시나리오 테스트
|
|||
|
|
- [ ] 크로스 브라우저 테스트
|
|||
|
|
- [ ] 사용자 테스트
|
|||
|
|
- [ ] 베타 테스터 모집
|
|||
|
|
- [ ] 피드백 수집 및 반영
|
|||
|
|
- [ ] 문서화
|
|||
|
|
- [ ] 사용자 가이드
|
|||
|
|
- [ ] API 문서
|
|||
|
|
- [ ] 개발자 문서
|
|||
|
|
|
|||
|
|
**최종 마일스톤**: 프로덕션 배포 준비 완료
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 💡 추가 기능 아이디어
|
|||
|
|
|
|||
|
|
### 1. 템플릿 갤러리
|
|||
|
|
|
|||
|
|
#### 1.1 내장 템플릿
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
📚 템플릿 카테고리:
|
|||
|
|
|
|||
|
|
1️⃣ 데이터 동기화
|
|||
|
|
- 테이블 → 테이블 복사
|
|||
|
|
- 테이블 → 외부 DB 동기화
|
|||
|
|
- 양방향 동기화
|
|||
|
|
- 증분 동기화 (변경분만)
|
|||
|
|
|
|||
|
|
2️⃣ 데이터 정제
|
|||
|
|
- 중복 제거
|
|||
|
|
- NULL 값 처리
|
|||
|
|
- 데이터 형식 변환
|
|||
|
|
- 데이터 검증
|
|||
|
|
|
|||
|
|
3️⃣ 데이터 집계
|
|||
|
|
- 그룹별 집계
|
|||
|
|
- 시계열 집계
|
|||
|
|
- 피벗 테이블 생성
|
|||
|
|
|
|||
|
|
4️⃣ 외부 연동
|
|||
|
|
- REST API → DB
|
|||
|
|
- DB → REST API
|
|||
|
|
- 파일 → DB
|
|||
|
|
- DB → 파일
|
|||
|
|
|
|||
|
|
5️⃣ 배치 처리
|
|||
|
|
- 일일 배치
|
|||
|
|
- 대용량 데이터 처리
|
|||
|
|
- 에러 핸들링
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 1.2 사용자 정의 템플릿
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 템플릿 저장
|
|||
|
|
const saveAsTemplate = () => {
|
|||
|
|
const template = {
|
|||
|
|
name: "사용자 데이터 동기화",
|
|||
|
|
description: "user_info를 Oracle USERS로 동기화",
|
|||
|
|
category: "custom",
|
|||
|
|
nodes: currentNodes,
|
|||
|
|
edges: currentEdges,
|
|||
|
|
thumbnail: generateThumbnail(),
|
|||
|
|
parameters: extractParameters(), // 매개변수화
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
saveTemplate(template);
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 템플릿 적용
|
|||
|
|
const applyTemplate = (template) => {
|
|||
|
|
// 매개변수 입력 받기
|
|||
|
|
const params = promptParameters(template.parameters);
|
|||
|
|
|
|||
|
|
// 노드 생성
|
|||
|
|
const nodes = template.nodes.map((node) => replaceParameters(node, params));
|
|||
|
|
|
|||
|
|
addNodes(nodes);
|
|||
|
|
addEdges(template.edges);
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. AI 어시스턴트
|
|||
|
|
|
|||
|
|
#### 2.1 자연어 플로우 생성
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
사용자: "사용자 테이블을 Oracle DB로 복사하고 싶어요"
|
|||
|
|
|
|||
|
|
AI 분석:
|
|||
|
|
1. 소스: user_info 테이블
|
|||
|
|
2. 타겟: Oracle USERS 테이블
|
|||
|
|
3. 액션: INSERT
|
|||
|
|
|
|||
|
|
AI 제안:
|
|||
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ 📊 user_info │═══════>│ 🔀 필드 매핑 │═══════>│ ➕ INSERT │
|
|||
|
|
│ │ │ 자동 매핑 │ │ USERS │
|
|||
|
|
└──────────────┘ └──────────────┘ └──────────────┘
|
|||
|
|
|
|||
|
|
"이 플로우를 생성할까요? [생성] [수정]"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.2 오류 자동 수정
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
오류 감지:
|
|||
|
|
❌ user_name 필드가 매핑되지 않았습니다
|
|||
|
|
|
|||
|
|
AI 제안:
|
|||
|
|
"user_name을 USERNAME으로 자동 매핑할까요?"
|
|||
|
|
[자동 수정] [무시] [수동 수정]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2.3 최적화 제안
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
AI 분석:
|
|||
|
|
⚠️ 현재 플로우는 10,000건 이상의 데이터를 처리합니다.
|
|||
|
|
|
|||
|
|
AI 제안:
|
|||
|
|
1. 배치 처리 활성화 (1000건씩)
|
|||
|
|
2. 인덱스가 없는 필드 조건 제거
|
|||
|
|
3. 불필요한 필드 변환 최적화
|
|||
|
|
|
|||
|
|
예상 성능 개선: 3배
|
|||
|
|
[적용하기] [상세 보기]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 실행 추적 (디버그 모드)
|
|||
|
|
|
|||
|
|
#### 3.1 실시간 실행 상태
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
실행 중 노드 상태:
|
|||
|
|
|
|||
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|||
|
|
│ 📊 user_info │ │ 🔀 필드 매핑 │ │ ➕ INSERT │
|
|||
|
|
│ ✅ 완료 │═══════>│ ⚡ 실행 중 │═══════>│ ⏳ 대기 중 │
|
|||
|
|
│ 100건 읽음 │ │ 47/100 │ │ │
|
|||
|
|
└──────────────┘ └──────────────┘ └──────────────┘
|
|||
|
|
|
|||
|
|
진행률: ████████░░ 80%
|
|||
|
|
소요 시간: 00:00:23
|
|||
|
|
예상 완료: 00:00:29
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2 데이터 미리보기
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
노드 클릭 시 데이터 샘플:
|
|||
|
|
|
|||
|
|
┌─ user_info 출력 데이터 ─────────────┐
|
|||
|
|
│ Row 1: │
|
|||
|
|
│ user_id: 1001 │
|
|||
|
|
│ user_name: "홍길동" │
|
|||
|
|
│ email: "hong@example.com" │
|
|||
|
|
│ │
|
|||
|
|
│ Row 2: │
|
|||
|
|
│ user_id: 1002 │
|
|||
|
|
│ user_name: "김철수" │
|
|||
|
|
│ ... │
|
|||
|
|
│ │
|
|||
|
|
│ [전체 보기] [CSV 다운로드] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3 중단점 설정
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
디버그 기능:
|
|||
|
|
|
|||
|
|
1. 중단점 설정
|
|||
|
|
- 노드에서 우클릭 → "중단점 설정"
|
|||
|
|
- 해당 노드에서 실행 일시 정지
|
|||
|
|
|
|||
|
|
2. 단계별 실행
|
|||
|
|
[▶️ 다음 노드] [⏭️ 완료까지] [⏹️ 중지]
|
|||
|
|
|
|||
|
|
3. 변수 감시
|
|||
|
|
- 특정 필드 값 추적
|
|||
|
|
- 조건 변화 모니터링
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 협업 기능
|
|||
|
|
|
|||
|
|
#### 4.1 실시간 공동 편집
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
사용자 표시:
|
|||
|
|
- 👤 김주석 (나)
|
|||
|
|
- 👤 이철수 (편집 중) ← 빨간색 커서
|
|||
|
|
- 👤 박영희 (보기만) ← 초록색 커서
|
|||
|
|
|
|||
|
|
동시 편집:
|
|||
|
|
- 각 사용자의 커서 위치 표시
|
|||
|
|
- 노드 잠금 (편집 중인 노드)
|
|||
|
|
- 충돌 방지 메커니즘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2 변경 이력 및 댓글
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────┐
|
|||
|
|
│ 필드 매핑 │
|
|||
|
|
│ │ 💬 3
|
|||
|
|
│ │
|
|||
|
|
└──────────────┘
|
|||
|
|
|
|||
|
|
댓글:
|
|||
|
|
김주석: "user_id를 SALT로 매핑하는게 맞나요?"
|
|||
|
|
이철수: "네, 맞습니다. 보안을 위한 필드입니다."
|
|||
|
|
박영희: "문서에 추가했습니다."
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.3 승인 워크플로우
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
플로우 변경 승인 프로세스:
|
|||
|
|
|
|||
|
|
1. 개발자: 플로우 수정
|
|||
|
|
↓
|
|||
|
|
2. 검토 요청
|
|||
|
|
↓
|
|||
|
|
3. 관리자: 변경 사항 검토
|
|||
|
|
- 변경 전/후 비교
|
|||
|
|
- 영향도 분석
|
|||
|
|
↓
|
|||
|
|
4. 승인/반려
|
|||
|
|
↓
|
|||
|
|
5. 배포 또는 재작업
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎓 학습 리소스 및 온보딩
|
|||
|
|
|
|||
|
|
### 1. 인터랙티브 튜토리얼
|
|||
|
|
|
|||
|
|
#### 단계별 가이드
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
튜토리얼 1: 첫 번째 플로우 만들기 (5분)
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 1단계: 데이터 소스 추가 │
|
|||
|
|
│ "좌측에서 '테이블' 노드를 드래그" │
|
|||
|
|
│ │
|
|||
|
|
│ [다음] [건너뛰기] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
튜토리얼 2: 조건 분기 사용하기 (7분)
|
|||
|
|
튜토리얼 3: 복잡한 변환 구현하기 (10분)
|
|||
|
|
튜토리얼 4: 디버깅 및 최적화 (8분)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 도움말 시스템
|
|||
|
|
|
|||
|
|
#### 컨텍스트 도움말
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
노드 위에 마우스 오버:
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 💡 필드 매핑 노드 │
|
|||
|
|
│ │
|
|||
|
|
│ 소스 필드를 타겟 필드로 매핑합니다.│
|
|||
|
|
│ │
|
|||
|
|
│ 사용 방법: │
|
|||
|
|
│ 1. 입력 데이터 연결 │
|
|||
|
|
│ 2. 매핑 규칙 정의 │
|
|||
|
|
│ 3. 출력을 다음 노드로 연결 │
|
|||
|
|
│ │
|
|||
|
|
│ [자세히 보기] [튜토리얼 보기] │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 예제 갤러리
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
📚 예제 플로우 갤러리
|
|||
|
|
|
|||
|
|
초급:
|
|||
|
|
- 단순 테이블 복사
|
|||
|
|
- 필드명 변경하여 복사
|
|||
|
|
- 특정 레코드만 복사
|
|||
|
|
|
|||
|
|
중급:
|
|||
|
|
- 조건부 데이터 처리
|
|||
|
|
- 다중 테이블 병합
|
|||
|
|
- 데이터 형식 변환
|
|||
|
|
|
|||
|
|
고급:
|
|||
|
|
- 복잡한 데이터 정제
|
|||
|
|
- 다중 분기 처리
|
|||
|
|
- 배치 최적화
|
|||
|
|
|
|||
|
|
[예제 열기] [템플릿으로 저장]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📈 성공 지표 (KPI)
|
|||
|
|
|
|||
|
|
### 사용자 경험 지표
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 학습 시간
|
|||
|
|
- 목표: 기존 대비 40% 단축
|
|||
|
|
- 측정: 첫 플로우 완성까지 소요 시간
|
|||
|
|
- 현재: 평균 15분
|
|||
|
|
- 목표: 평균 9분
|
|||
|
|
|
|||
|
|
2. 작업 효율성
|
|||
|
|
- 목표: 플로우 생성 시간 50% 단축
|
|||
|
|
- 측정: 동일 기능 구현 소요 시간
|
|||
|
|
- 현재: 평균 20분
|
|||
|
|
- 목표: 평균 10분
|
|||
|
|
|
|||
|
|
3. 오류 감소
|
|||
|
|
- 목표: 설정 오류 60% 감소
|
|||
|
|
- 측정: 실행 실패율
|
|||
|
|
- 현재: 12%
|
|||
|
|
- 목표: 4.8%
|
|||
|
|
|
|||
|
|
4. 사용자 만족도
|
|||
|
|
- 목표: NPS 40점 이상
|
|||
|
|
- 측정: 설문 조사
|
|||
|
|
- 주기: 분기별
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 기술 성능 지표
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 렌더링 성능
|
|||
|
|
- 목표: 100개 노드 렌더링 < 100ms
|
|||
|
|
- 측정: React Profiler
|
|||
|
|
|
|||
|
|
2. 메모리 사용
|
|||
|
|
- 목표: 대규모 플로우 < 100MB
|
|||
|
|
- 측정: Chrome DevTools
|
|||
|
|
|
|||
|
|
3. 저장/로드 속도
|
|||
|
|
- 목표: 플로우 저장 < 500ms
|
|||
|
|
- 측정: Network 탭
|
|||
|
|
|
|||
|
|
4. 검증 속도
|
|||
|
|
- 목표: 실시간 검증 < 50ms
|
|||
|
|
- 측정: Performance API
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 비즈니스 지표
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 도입률
|
|||
|
|
- 목표: 신규 사용자 60% 이상이 노드 에디터 선택
|
|||
|
|
- 측정: 사용 통계
|
|||
|
|
|
|||
|
|
2. 재사용률
|
|||
|
|
- 목표: 템플릿 재사용 40% 이상
|
|||
|
|
- 측정: 템플릿 사용 횟수
|
|||
|
|
|
|||
|
|
3. 생산성
|
|||
|
|
- 목표: 플로우 생성 수 2배 증가
|
|||
|
|
- 측정: 월별 생성된 플로우 수
|
|||
|
|
|
|||
|
|
4. 유지보수
|
|||
|
|
- 목표: 플로우 수정 시간 30% 단축
|
|||
|
|
- 측정: 평균 수정 소요 시간
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔒 보안 및 권한
|
|||
|
|
|
|||
|
|
### 1. 접근 제어
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 플로우 권한 레벨
|
|||
|
|
enum FlowPermission {
|
|||
|
|
VIEW = "view", // 보기만
|
|||
|
|
EDIT = "edit", // 편집 가능
|
|||
|
|
EXECUTE = "execute", // 실행 가능
|
|||
|
|
ADMIN = "admin", // 모든 권한
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 권한 체크
|
|||
|
|
const checkPermission = (
|
|||
|
|
userId: string,
|
|||
|
|
flowId: number,
|
|||
|
|
permission: FlowPermission
|
|||
|
|
) => {
|
|||
|
|
const userPermissions = getUserFlowPermissions(userId, flowId);
|
|||
|
|
return userPermissions.includes(permission);
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 민감 정보 보호
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 비밀번호 등 민감 정보 마스킹
|
|||
|
|
const renderSensitiveField = (value: string, fieldType: string) => {
|
|||
|
|
if (fieldType === "password" || fieldType === "secret") {
|
|||
|
|
return "••••••••";
|
|||
|
|
}
|
|||
|
|
return value;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 실행 로그에서 민감 정보 제외
|
|||
|
|
const sanitizeLog = (log: string) => {
|
|||
|
|
return log
|
|||
|
|
.replace(/password=\w+/gi, "password=***")
|
|||
|
|
.replace(/token=\w+/gi, "token=***");
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 감사 로그
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 모든 플로우 변경 기록
|
|||
|
|
interface AuditLog {
|
|||
|
|
timestamp: Date;
|
|||
|
|
userId: string;
|
|||
|
|
flowId: number;
|
|||
|
|
action: "create" | "update" | "delete" | "execute";
|
|||
|
|
changes: {
|
|||
|
|
before: any;
|
|||
|
|
after: any;
|
|||
|
|
};
|
|||
|
|
ipAddress: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 로그 기록
|
|||
|
|
const logFlowChange = (log: AuditLog) => {
|
|||
|
|
saveAuditLog(log);
|
|||
|
|
|
|||
|
|
if (isCriticalChange(log)) {
|
|||
|
|
notifyAdmins(log);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🌐 국제화 (i18n)
|
|||
|
|
|
|||
|
|
### 지원 언어
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
- 한국어 (ko) - 기본
|
|||
|
|
- 영어 (en)
|
|||
|
|
- 일본어 (ja)
|
|||
|
|
- 중국어 간체 (zh-CN)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 번역 대상
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. UI 라벨 및 버튼
|
|||
|
|
2. 노드 타입명 및 설명
|
|||
|
|
3. 오류 메시지
|
|||
|
|
4. 도움말 및 튜토리얼
|
|||
|
|
5. 템플릿명 및 설명
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📱 반응형 디자인
|
|||
|
|
|
|||
|
|
### 화면 크기별 대응
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 데스크톱 (1920px+)
|
|||
|
|
- 전체 기능 사용 가능
|
|||
|
|
- 3열 레이아웃 (도구-캔버스-속성)
|
|||
|
|
|
|||
|
|
2. 노트북 (1366px ~ 1920px)
|
|||
|
|
- 속성 패널 접기 가능
|
|||
|
|
- 2열 레이아웃
|
|||
|
|
|
|||
|
|
3. 태블릿 (768px ~ 1366px)
|
|||
|
|
- 도구 패널 오버레이
|
|||
|
|
- 1열 레이아웃 + 플로팅 패널
|
|||
|
|
|
|||
|
|
4. 모바일 (~ 768px)
|
|||
|
|
- 뷰어 모드만 지원 (편집 불가)
|
|||
|
|
- 플로우 실행 및 모니터링 가능
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎉 결론
|
|||
|
|
|
|||
|
|
노드 기반 데이터 제어 시스템은 현재의 단계별 마법사 방식에 비해 다음과 같은 혁신적인 개선을 제공합니다:
|
|||
|
|
|
|||
|
|
### 핵심 가치
|
|||
|
|
|
|||
|
|
1. **직관성**: 비개발자도 쉽게 이해하고 사용
|
|||
|
|
2. **효율성**: 작업 시간 50% 이상 단축
|
|||
|
|
3. **유연성**: 복잡한 로직도 쉽게 표현
|
|||
|
|
4. **협업**: 팀 간 소통 및 협업 향상
|
|||
|
|
5. **품질**: 실시간 검증으로 오류 감소
|
|||
|
|
|
|||
|
|
### 기대 효과
|
|||
|
|
|
|||
|
|
- 사용자 만족도 향상
|
|||
|
|
- 개발 생산성 증가
|
|||
|
|
- 유지보수 비용 감소
|
|||
|
|
- 시스템 안정성 향상
|
|||
|
|
|
|||
|
|
### 다음 단계
|
|||
|
|
|
|||
|
|
1. 이해관계자 리뷰 및 피드백
|
|||
|
|
2. 프로토타입 개발 (1주)
|
|||
|
|
3. 사용자 테스트 (1주)
|
|||
|
|
4. 본격 개발 시작
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📚 참고 자료
|
|||
|
|
|
|||
|
|
### 유사 시스템
|
|||
|
|
|
|||
|
|
1. **n8n**: 워크플로우 자동화 플랫폼
|
|||
|
|
- https://n8n.io/
|
|||
|
|
2. **Node-RED**: IoT 플로우 기반 프로그래밍
|
|||
|
|
- https://nodered.org/
|
|||
|
|
3. **Unreal Blueprint**: 게임 개발 비주얼 스크립팅
|
|||
|
|
- https://docs.unrealengine.com/en-US/ProgrammingAndScripting/Blueprints/
|
|||
|
|
|
|||
|
|
### 기술 문서
|
|||
|
|
|
|||
|
|
1. **React Flow 공식 문서**
|
|||
|
|
- https://reactflow.dev/
|
|||
|
|
2. **React Flow 예제**
|
|||
|
|
- https://reactflow.dev/examples
|
|||
|
|
3. **TypeScript 베스트 프랙티스**
|
|||
|
|
- https://www.typescriptlang.org/docs/
|
|||
|
|
|
|||
|
|
### 디자인 가이드
|
|||
|
|
|
|||
|
|
1. **Material Design - Data Visualization**
|
|||
|
|
- https://material.io/design/communication/data-visualization.html
|
|||
|
|
2. **Blueprint UI Framework**
|
|||
|
|
- https://blueprintjs.com/
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**문서 버전**: 1.0
|
|||
|
|
**최종 수정**: 2025-10-02
|
|||
|
|
**작성자**: 개발팀
|
|||
|
|
**검토자**: 제품팀, 디자인팀
|
|||
|
|
**승인자**: CTO
|