ERP-node/docs/화면간_데이터_관계_설정_시스템_설계.md

720 lines
23 KiB
Markdown
Raw Normal View History

2025-09-05 18:00:18 +09:00
# 테이블 간 데이터 관계 설정 시스템 설계
2025-09-05 10:54:34 +09:00
## 📋 목차
1. [시스템 개요](#시스템-개요)
2. [핵심 기능](#핵심-기능)
3. [데이터베이스 설계](#데이터베이스-설계)
4. [프론트엔드 설계](#프론트엔드-설계)
5. [API 설계](#api-설계)
6. [사용 시나리오](#사용-시나리오)
7. [구현 계획](#구현-계획)
## 🎯 시스템 개요
2025-09-05 18:00:18 +09:00
### 테이블 간 데이터 관계 설정 시스템이란?
2025-09-05 10:54:34 +09:00
2025-09-05 18:00:18 +09:00
테이블 간 데이터 관계 설정 시스템은 회사별로 데이터베이스 테이블들 간의 데이터 관계를 시각적으로 설계하고 관리할 수 있는 시스템입니다. React Flow 라이브러리를 활용하여 직관적인 노드 기반 인터페이스로 1:1, 1:N, N:1, N:N 관계를 지원하며, 다양한 연결 방식과 종류로 복합적인 데이터 관계를 설계할 수 있습니다.
2025-09-05 10:54:34 +09:00
### 주요 특징
- **React Flow 기반 인터페이스**: 직관적인 노드와 엣지 기반 시각적 설계
2025-09-05 18:00:18 +09:00
- **회사별 관계 관리**: 사용자 회사 코드에 따른 테이블 관계 접근 제어
- **시각적 관계 설계**: 드래그앤드롭으로 테이블 노드 배치 및 컬럼 간 연결
2025-09-05 10:54:34 +09:00
- **다양한 관계 타입**: 1:1, 1:N, N:1, N:N 관계 지원
- **연결 종류별 세부 설정**: 단순 키값, 데이터 저장, 외부 호출
- **실시간 시뮬레이션**: 설계한 관계의 데이터 흐름 시뮬레이션
- **중계 테이블 자동 생성**: N:N 관계에서 중계 테이블 자동 생성
- **인터랙티브 캔버스**: 줌, 팬, 미니맵 등 React Flow의 고급 기능 활용
### 지원하는 관계 타입
2025-09-05 18:00:18 +09:00
- **1:1 (One to One)**: 한 테이블의 컬럼과 다른 테이블의 컬럼이 1:1로 연결
- **1:N (One to Many)**: 한 테이블의 컬럼이 여러 테이블의 컬럼과 연결
- **N:1 (Many to One)**: 여러 테이블의 컬럼이 한 테이블의 컬럼과 연결
- **N:N (Many to Many)**: 여러 테이블의 컬럼이 여러 테이블의 컬럼과 연결
2025-09-05 10:54:34 +09:00
### 지원하는 연결 종류
- **단순 키값 연결**: 중계 테이블을 통한 참조 관계
2025-09-05 18:00:18 +09:00
- **데이터 저장**: 컬럼 매핑을 통한 데이터 저장
2025-09-05 10:54:34 +09:00
- **외부 호출**: API, 이메일, 웹훅 등을 통한 외부 시스템 연동
## 🚀 핵심 기능
2025-09-05 18:00:18 +09:00
### 1. React Flow 기반 테이블 노드 관리
2025-09-05 10:54:34 +09:00
2025-09-05 18:00:18 +09:00
- **테이블 추가**: 데이터베이스 테이블 목록에서 관계를 설정할 테이블들을 React Flow 캔버스에 추가
- **테이블 배치**: 드래그앤드롭으로 테이블 노드를 원하는 위치에 배치
- **테이블 이동**: React Flow의 내장 기능으로 테이블 노드 자유롭게 이동
2025-09-05 10:54:34 +09:00
- **노드 선택**: 단일 또는 다중 노드 선택 지원
- **자동 정렬**: React Flow의 레이아웃 알고리즘을 활용한 자동 정렬
2025-09-05 18:00:18 +09:00
### 2. React Flow 기반 컬럼 간 연결 설정
2025-09-05 10:54:34 +09:00
2025-09-05 18:00:18 +09:00
- **컬럼 선택**: 첫 번째 테이블의 컬럼을 클릭하여 연결 시작
- **대상 컬럼 선택**: 두 번째 테이블의 컬럼을 클릭하여 연결 대상 지정
2025-09-05 10:54:34 +09:00
- **드래그 연결**: React Flow의 핸들(Handle)을 드래그하여 시각적 연결
- **관계 타입 선택**: 1:1, 1:N, N:1, N:N 중 선택
- **연결 종류 선택**: 단순 키값, 데이터 저장, 외부 호출 중 선택
- **엣지 커스터마이징**: 연결 타입별 색상, 스타일, 라벨 설정
### 3. 연결 종류별 세부 설정
#### 단순 키값 연결
- **중계 테이블명**: 자동 생성 또는 사용자 정의
- **연결 규칙**: 중계 테이블 생성 및 관리 규칙
- **참조 무결성**: 외래키 제약조건 설정
#### 데이터 저장
2025-09-05 18:00:18 +09:00
- **컬럼 매핑**: 소스 컬럼과 대상 컬럼 매핑 설정
2025-09-05 10:54:34 +09:00
- **저장 조건**: 데이터 저장 조건 정의
2025-09-05 18:00:18 +09:00
- **데이터 변환**: 컬럼 값 변환 규칙
2025-09-05 10:54:34 +09:00
#### 외부 호출
- **REST API**: API URL, HTTP Method, Headers, Body Template
- **이메일**: SMTP 서버, 발신자, 수신자, 제목/본문 템플릿
- **웹훅**: 웹훅 URL, Payload 형식, Payload 템플릿
- **FTP**: FTP 서버, 업로드 경로, 파일명 템플릿
- **메시지 큐**: 큐 시스템, 큐 이름, 메시지 형식
### 4. React Flow 기반 시각적 관계 관리
2025-09-05 18:00:18 +09:00
- **엣지 렌더링**: React Flow의 커스텀 엣지로 테이블 간 관계를 시각적으로 표현
2025-09-05 10:54:34 +09:00
- **관계 타입별 스타일링**: 연결 종류에 따른 색상, 선 스타일, 라벨 구분
- **인터랙티브 캔버스**: 줌, 팬, 미니맵을 통한 대규모 다이어그램 탐색
- **실시간 시뮬레이션**: 데이터 흐름 애니메이션 및 시뮬레이션
- **관계 검증**: 연결 가능성 및 무결성 검증
- **엣지 편집**: 연결선 클릭으로 관계 설정 수정
### 5. 관계 통계 및 관리
- **연결 통계**: 관계 타입별 연결 수 표시
- **중계 테이블 관리**: 생성된 중계 테이블 목록 및 관리
- **관계 목록**: 생성된 모든 관계 목록 조회
- **관계 삭제**: 불필요한 관계 삭제
## 🗄️ 데이터베이스 설계
2025-09-05 18:00:18 +09:00
### 1. 테이블 관계 테이블
2025-09-05 10:54:34 +09:00
```sql
2025-09-05 18:00:18 +09:00
-- 테이블 간 관계 정의
CREATE TABLE table_relationships (
2025-09-05 10:54:34 +09:00
relationship_id SERIAL PRIMARY KEY,
relationship_name VARCHAR(200) NOT NULL,
2025-09-05 18:00:18 +09:00
from_table_name VARCHAR(100) NOT NULL,
from_column_name VARCHAR(100) NOT NULL,
to_table_name VARCHAR(100) NOT NULL,
to_column_name VARCHAR(100) NOT NULL,
2025-09-05 10:54:34 +09:00
relationship_type VARCHAR(20) NOT NULL, -- 'one-to-one', 'one-to-many', 'many-to-one', 'many-to-many'
connection_type VARCHAR(20) NOT NULL, -- 'simple-key', 'data-save', 'external-call'
company_code VARCHAR(50) NOT NULL,
settings JSONB, -- 연결 종류별 세부 설정
is_active CHAR(1) DEFAULT 'Y',
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
updated_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2025-09-05 18:00:18 +09:00
updated_by VARCHAR(50)
2025-09-05 10:54:34 +09:00
);
-- 회사 코드 인덱스
2025-09-05 18:00:18 +09:00
CREATE INDEX idx_table_relationships_company_code ON table_relationships(company_code);
-- 테이블명 인덱스
CREATE INDEX idx_table_relationships_from_table ON table_relationships(from_table_name);
CREATE INDEX idx_table_relationships_to_table ON table_relationships(to_table_name);
2025-09-05 10:54:34 +09:00
```
### 2. 중계 테이블 관리
```sql
-- 중계 테이블 정의
CREATE TABLE bridge_tables (
bridge_id SERIAL PRIMARY KEY,
bridge_name VARCHAR(200) NOT NULL,
table_name VARCHAR(100) NOT NULL,
relationship_id INTEGER NOT NULL,
company_code VARCHAR(50) NOT NULL,
description TEXT,
is_active CHAR(1) DEFAULT 'Y',
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
-- 외래키 제약조건
CONSTRAINT fk_bridge_tables_relationship
2025-09-05 18:00:18 +09:00
FOREIGN KEY (relationship_id) REFERENCES table_relationships(relationship_id)
2025-09-05 10:54:34 +09:00
);
-- 회사 코드 인덱스
CREATE INDEX idx_bridge_tables_company_code ON bridge_tables(company_code);
```
### 3. 외부 호출 설정
```sql
-- 외부 호출 설정
CREATE TABLE external_call_configs (
config_id SERIAL PRIMARY KEY,
relationship_id INTEGER NOT NULL,
call_type VARCHAR(50) NOT NULL, -- 'rest-api', 'email', 'webhook', 'ftp', 'queue'
parameters JSONB NOT NULL, -- 호출 유형별 파라미터
is_active CHAR(1) DEFAULT 'Y',
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50),
-- 외래키 제약조건
CONSTRAINT fk_external_call_configs_relationship
2025-09-05 18:00:18 +09:00
FOREIGN KEY (relationship_id) REFERENCES table_relationships(relationship_id)
2025-09-05 10:54:34 +09:00
);
```
### 4. 테이블 간 연계 관계
```
2025-09-05 18:00:18 +09:00
table_relationships (테이블 관계)
2025-09-05 10:54:34 +09:00
↓ (1:N)
bridge_tables (중계 테이블)
↓ (1:N)
external_call_configs (외부 호출 설정)
```
## 🎨 프론트엔드 설계
### 1. React Flow 기반 메인 컴포넌트
```typescript
// DataFlowDesigner.tsx
import ReactFlow, {
Node,
Edge,
Controls,
Background,
MiniMap,
useNodesState,
useEdgesState,
addEdge,
Connection,
EdgeChange,
NodeChange,
} from "reactflow";
import "reactflow/dist/style.css";
interface DataFlowDesignerProps {
companyCode: string;
2025-09-05 18:00:18 +09:00
onSave?: (relationships: TableRelationship[]) => void;
2025-09-05 10:54:34 +09:00
}
export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({
companyCode,
onSave,
}) => {
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const [selectedField, setSelectedField] = useState<FieldSelection | null>(
null
);
const [pendingConnection, setPendingConnection] =
useState<PendingConnection | null>(null);
const onConnect = useCallback(
(params: Connection) => {
setEdges((eds) => addEdge(params, eds));
},
[setEdges]
);
return (
<div className="data-flow-designer h-screen">
<div className="flex h-full">
{/* 사이드바 */}
<div className="w-80 bg-gray-50 border-r">
2025-09-05 18:00:18 +09:00
<TableSelector
2025-09-05 10:54:34 +09:00
companyCode={companyCode}
2025-09-05 18:00:18 +09:00
onTableAdd={handleTableAdd}
2025-09-05 10:54:34 +09:00
/>
<ConnectionStatus
2025-09-05 18:00:18 +09:00
selectedColumn={selectedColumn}
2025-09-05 10:54:34 +09:00
onCancel={handleCancelConnection}
/>
<ConnectionStats relationships={relationships} />
</div>
{/* React Flow 캔버스 */}
<div className="flex-1">
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
onNodeClick={handleNodeClick}
onEdgeClick={handleEdgeClick}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
fitView
>
<Controls />
<MiniMap />
<Background variant="dots" gap={12} size={1} />
</ReactFlow>
</div>
</div>
<ConnectionSetupModal
isOpen={!!pendingConnection}
connection={pendingConnection}
onConfirm={handleConfirmConnection}
onCancel={handleCancelConnection}
/>
</div>
);
};
```
2025-09-05 18:00:18 +09:00
### 2. React Flow 테이블 노드 컴포넌트
2025-09-05 10:54:34 +09:00
```typescript
2025-09-05 18:00:18 +09:00
// TableNode.tsx
2025-09-05 10:54:34 +09:00
import { Handle, Position } from "reactflow";
2025-09-05 18:00:18 +09:00
interface TableNodeData {
table: TableDefinition;
onColumnClick: (tableName: string, columnName: string) => void;
2025-09-05 10:54:34 +09:00
}
2025-09-05 18:00:18 +09:00
export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
const { table, onColumnClick } = data;
2025-09-05 10:54:34 +09:00
return (
<div className="bg-white border-2 border-gray-300 rounded-lg shadow-lg min-w-80">
{/* 노드 헤더 */}
<div className="bg-blue-500 text-white p-3 rounded-t-lg">
2025-09-05 18:00:18 +09:00
<div className="font-bold text-sm">{table.tableName}</div>
<div className="text-xs opacity-90">테이블</div>
<div className="text-xs opacity-75">컬럼: {table.columns.length}개</div>
2025-09-05 10:54:34 +09:00
</div>
2025-09-05 18:00:18 +09:00
{/* 컬럼 목록 */}
2025-09-05 10:54:34 +09:00
<div className="p-3">
<div className="text-xs font-semibold text-gray-600 mb-2">
2025-09-05 18:00:18 +09:00
컬럼 목록 ({table.columns.length}개)
2025-09-05 10:54:34 +09:00
</div>
<div className="space-y-1">
2025-09-05 18:00:18 +09:00
{table.columns.map((column) => (
2025-09-05 10:54:34 +09:00
<div
2025-09-05 18:00:18 +09:00
key={column.name}
2025-09-05 10:54:34 +09:00
className="flex items-center justify-between p-2 hover:bg-gray-50 rounded cursor-pointer"
2025-09-05 18:00:18 +09:00
onClick={() => onColumnClick(table.tableName, column.name)}
2025-09-05 10:54:34 +09:00
>
<div className="flex-1">
2025-09-05 18:00:18 +09:00
<div className="text-sm font-medium">{column.name}</div>
<div className="text-xs text-gray-500">
{column.description}
</div>
2025-09-05 10:54:34 +09:00
</div>
<div className="text-xs text-blue-600 font-mono">
2025-09-05 18:00:18 +09:00
{column.type}
2025-09-05 10:54:34 +09:00
</div>
</div>
))}
</div>
</div>
{/* React Flow 핸들 */}
<Handle
type="source"
position={Position.Right}
className="w-3 h-3 bg-blue-500"
/>
<Handle
type="target"
position={Position.Left}
className="w-3 h-3 bg-green-500"
/>
</div>
);
};
// 노드 타입 정의
export const nodeTypes = {
2025-09-05 18:00:18 +09:00
tableNode: TableNode,
2025-09-05 10:54:34 +09:00
};
```
### 3. 연결 설정 모달
```typescript
// ConnectionSetupModal.tsx
interface ConnectionSetupModalProps {
isOpen: boolean;
connection: PendingConnection | null;
onConfirm: (config: ConnectionConfig) => void;
onCancel: () => void;
}
export const ConnectionSetupModal: React.FC<ConnectionSetupModalProps> = ({
isOpen,
connection,
onConfirm,
onCancel,
}) => {
const [connectionType, setConnectionType] =
useState<ConnectionType>("simple-key");
const [relationshipType, setRelationshipType] =
useState<RelationshipType>("one-to-one");
const [settings, setSettings] = useState<ConnectionSettings>({});
return (
<Dialog open={isOpen} onOpenChange={onCancel}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>필드 연결 설정</DialogTitle>
</DialogHeader>
<div className="space-y-6">
{/* 연결 정보 표시 */}
<ConnectionInfo connection={connection} />
{/* 관계 타입 선택 */}
<RelationshipTypeSelector
value={relationshipType}
onChange={setRelationshipType}
/>
{/* 연결 종류 선택 */}
<ConnectionTypeSelector
value={connectionType}
onChange={setConnectionType}
/>
{/* 연결 종류별 세부 설정 */}
<ConnectionSettingsPanel
type={connectionType}
settings={settings}
onChange={setSettings}
/>
</div>
<DialogFooter>
<Button onClick={onCancel}>취소</Button>
<Button
onClick={() =>
onConfirm({ connectionType, relationshipType, settings })
}
>
연결 생성
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
```
### 4. React Flow 엣지 컴포넌트
```typescript
// CustomEdge.tsx
import {
EdgeProps,
getBezierPath,
EdgeLabelRenderer,
BaseEdge,
} from "reactflow";
interface CustomEdgeData {
relationshipType: string;
connectionType: string;
label?: string;
}
export const CustomEdge: React.FC<EdgeProps<CustomEdgeData>> = ({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
data,
markerEnd,
}) => {
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
});
const getEdgeColor = (connectionType: string) => {
switch (connectionType) {
case "simple-key":
return "#3B82F6"; // 파란색
case "data-save":
return "#10B981"; // 초록색
case "external-call":
return "#F59E0B"; // 주황색
default:
return "#6B7280"; // 회색
}
};
const getEdgeStyle = (connectionType: string) => {
switch (connectionType) {
case "simple-key":
return { strokeWidth: 2, strokeDasharray: "5,5" };
case "data-save":
return { strokeWidth: 3 };
case "external-call":
return { strokeWidth: 2, strokeDasharray: "10,5" };
default:
return { strokeWidth: 2 };
}
};
return (
<>
<BaseEdge
id={id}
path={edgePath}
markerEnd={markerEnd}
style={{
stroke: getEdgeColor(data?.connectionType || ""),
...getEdgeStyle(data?.connectionType || ""),
}}
/>
<EdgeLabelRenderer>
<div
style={{
position: "absolute",
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
background: "white",
padding: "4px 8px",
borderRadius: "4px",
fontSize: "12px",
fontWeight: 500,
border: "1px solid #E5E7EB",
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)",
}}
className="nodrag nopan"
>
{data?.label || data?.relationshipType}
</div>
</EdgeLabelRenderer>
</>
);
};
// 엣지 타입 정의
export const edgeTypes = {
customEdge: CustomEdge,
};
```
## 🌐 API 설계
2025-09-05 18:00:18 +09:00
### 1. 테이블 관계 관리 API
2025-09-05 10:54:34 +09:00
```typescript
2025-09-05 18:00:18 +09:00
// 테이블 관계 생성
POST /api/table-relationships
2025-09-05 10:54:34 +09:00
Body: {
relationshipName: string;
2025-09-05 18:00:18 +09:00
fromTableName: string;
fromColumnName: string;
toTableName: string;
toColumnName: string;
2025-09-05 10:54:34 +09:00
relationshipType: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many';
connectionType: 'simple-key' | 'data-save' | 'external-call';
settings: ConnectionSettings;
}
2025-09-05 18:00:18 +09:00
// 테이블 관계 목록 조회 (회사별)
GET /api/table-relationships?companyCode=COMP001
2025-09-05 10:54:34 +09:00
2025-09-05 18:00:18 +09:00
// 테이블 관계 수정
PUT /api/table-relationships/:id
2025-09-05 10:54:34 +09:00
2025-09-05 18:00:18 +09:00
// 테이블 관계 삭제
DELETE /api/table-relationships/:id
2025-09-05 10:54:34 +09:00
// 관계 시뮬레이션
2025-09-05 18:00:18 +09:00
POST /api/table-relationships/:id/simulate
2025-09-05 10:54:34 +09:00
```
### 2. 중계 테이블 관리 API
```typescript
// 중계 테이블 생성
POST /api/bridge-tables
Body: {
bridgeName: string;
tableName: string;
relationshipId: number;
description?: string;
}
// 중계 테이블 목록 조회
GET /api/bridge-tables?companyCode=COMP001
// 중계 테이블 삭제
DELETE /api/bridge-tables/:id
```
### 3. 외부 호출 설정 API
```typescript
// 외부 호출 설정 생성
POST /api/external-call-configs
Body: {
relationshipId: number;
callType: 'rest-api' | 'email' | 'webhook' | 'ftp' | 'queue';
parameters: Record<string, any>;
}
// 외부 호출 설정 조회
GET /api/external-call-configs?relationshipId=123
// 외부 호출 설정 수정
PUT /api/external-call-configs/:id
```
## 🎬 사용 시나리오
### 1. 기본 관계 설정
2025-09-05 18:00:18 +09:00
1. **테이블 추가**: 데이터베이스 테이블 목록에서 관계를 설정할 테이블들을 캔버스에 추가
2. **컬럼 선택**: 첫 번째 테이블의 컬럼을 클릭하여 연결 시작
3. **대상 컬럼 선택**: 두 번째 테이블의 컬럼을 클릭하여 연결 대상 지정
2025-09-05 10:54:34 +09:00
4. **관계 설정**: 관계 타입과 연결 종류를 선택하고 세부 설정 구성
5. **연결 생성**: 설정 완료 후 연결 생성
### 2. 복합 데이터 흐름 설계
2025-09-05 18:00:18 +09:00
1. **다중 테이블 배치**: 관련된 여러 테이블을 캔버스에 배치
2025-09-05 10:54:34 +09:00
2. **다양한 연결 타입**: 단순 키값, 데이터 저장, 외부 호출을 조합
3. **중계 테이블 활용**: N:N 관계에서 중계 테이블 자동 생성
4. **시각적 검증**: 연결선과 색상으로 관계 유형 구분
### 3. 외부 시스템 연동
1. **API 연결**: REST API 호출을 통한 외부 시스템 연동
2. **이메일 알림**: 데이터 변경 시 이메일 자동 전송
3. **웹훅 설정**: 실시간 데이터 동기화
4. **메시지 큐**: 비동기 데이터 처리
## 📅 구현 계획
2025-09-05 11:30:27 +09:00
### Phase 1: React Flow 기본 설정 (1주) ✅ **완료**
- [x] React Flow 라이브러리 설치 및 설정 (@xyflow/react 12.8.4)
- [x] 기본 노드와 엣지 컴포넌트 구현
2025-09-05 18:00:18 +09:00
- [x] 테이블 노드 컴포넌트 구현 (TableNode.tsx)
2025-09-05 11:30:27 +09:00
- [x] 기본 연결선 그리기 (CustomEdge.tsx)
- [x] 메인 데이터 흐름 관리 컴포넌트 구현 (DataFlowDesigner.tsx)
- [x] /admin/dataflow 페이지 생성
- [x] 메뉴 시스템 연동 (SQL 스크립트 제공)
- [x] 샘플 노드 추가/삭제 기능
- [x] 노드 간 드래그앤드롭 연결 기능
- [x] 줌, 팬, 미니맵 등 React Flow 기본 기능
2025-09-05 10:54:34 +09:00
2025-09-05 16:19:31 +09:00
### Phase 2: 관계 설정 기능 (2주) - 🚧 **진행 중 (70% 완료)**
- [x] 연결 설정 모달 UI 구현
- [x] 1:1, 1:N, N:1, N:N 관계 타입 선택 UI
- [x] 단순 키값, 데이터 저장, 외부 호출 연결 종류 UI
2025-09-05 18:00:18 +09:00
- [x] 컬럼-to-컬럼 연결 시스템 (클릭 기반)
- [x] 선택된 컬럼 정보 표시 및 순서 보장
2025-09-05 16:19:31 +09:00
- [ ] 연결 생성 로직 구현 (모달에서 실제 엣지 생성)
- [ ] 생성된 연결의 시각적 표시 (React Flow 엣지)
- [ ] 연결 데이터 백엔드 저장 API 연동
- [ ] 기존 연결 수정/삭제 기능
2025-09-05 10:54:34 +09:00
### Phase 3: 고급 연결 타입 (2-3주)
- [ ] 데이터 저장 연결
- [ ] 외부 호출 연결
- [ ] 중계 테이블 자동 생성
- [ ] 커스텀 엣지 스타일링
### Phase 4: React Flow 고급 기능 (1-2주)
- [ ] 줌, 팬, 미니맵 기능
- [ ] 노드 선택 및 다중 선택
- [ ] 키보드 단축키 지원
- [ ] 레이아웃 자동 정렬
### Phase 5: 시각화 및 관리 (1-2주)
- [ ] 관계 시뮬레이션
- [ ] 연결 통계 및 관리
- [ ] 관계 검증
- [ ] 데이터 흐름 애니메이션
### Phase 6: 고급 기능 (2-3주)
- [ ] N:N 관계 지원
- [ ] 복합 데이터 흐름
- [ ] 외부 시스템 연동
- [ ] 성능 최적화
## 🎯 결론
2025-09-05 18:00:18 +09:00
**테이블 간 데이터 관계 설정 시스템**을 통해 ERP 시스템의 테이블들 간 데이터 관계를 시각적으로 설계하고 관리할 수 있습니다. React Flow 라이브러리를 활용한 직관적인 노드 기반 인터페이스와 회사별 권한 관리, 기존 테이블관리 시스템과의 완벽한 연동을 통해 체계적인 데이터 관계 관리가 가능합니다.
2025-09-05 10:54:34 +09:00
2025-09-05 11:30:27 +09:00
## 📊 구현 현황
### ✅ Phase 1 완료 (2024-12-19)
**구현된 기능:**
- React Flow 12.8.4 기반 시각적 캔버스
2025-09-05 18:00:18 +09:00
- 테이블 노드 컴포넌트 (컬럼 정보, 타입별 색상 구분, 노드 리사이징)
2025-09-05 11:30:27 +09:00
- 커스텀 엣지 컴포넌트 (관계 타입별 스타일링)
- 드래그앤드롭 노드 배치 및 연결
2025-09-05 16:19:31 +09:00
- 줌, 팬, 미니맵 등 고급 시각화 기능 (스크롤 충돌 해결)
2025-09-05 18:00:18 +09:00
- 실제 테이블 데이터 연동 (테이블 관리 API 연결)
- 컬럼-to-컬럼 연결 시스템 (클릭 기반, 2개 테이블 제한)
2025-09-05 16:19:31 +09:00
- 연결 설정 모달 (관계 타입, 연결 종류 선택 UI)
2025-09-05 11:30:27 +09:00
- /admin/dataflow 경로 설정
2025-09-05 16:19:31 +09:00
- 메뉴 시스템 연동 완료
- 사용자 경험 개선 (토스트 알림, 선택 순서 보장)
2025-09-05 11:30:27 +09:00
**구현된 파일:**
2025-09-05 16:19:31 +09:00
- `frontend/components/dataflow/DataFlowDesigner.tsx` - 메인 캔버스 컴포넌트
2025-09-05 18:00:18 +09:00
- `frontend/components/dataflow/TableNode.tsx` - 테이블 노드 컴포넌트 (NodeResizer 포함)
2025-09-05 16:19:31 +09:00
- `frontend/components/dataflow/CustomEdge.tsx` - 커스텀 엣지 컴포넌트
- `frontend/components/dataflow/ConnectionSetupModal.tsx` - 연결 설정 모달
- `frontend/app/(main)/admin/dataflow/page.tsx` - 데이터 흐름 관리 페이지
- `frontend/lib/api/dataflow.ts` - 데이터 흐름 API 클라이언트
- `docs/add_dataflow_menu.sql` - 메뉴 추가 스크립트
**주요 개선사항:**
1. **스크롤 충돌 해결**: 노드 내부 스크롤과 React Flow 줌/팬 기능 분리
2. **노드 리사이징**: NodeResizer를 통한 노드 크기 조정 및 내용 반영
2025-09-05 18:00:18 +09:00
3. **컬럼-to-컬럼 연결**: 드래그앤드롭 대신 클릭 기반 컬럼 선택 방식
4. **2개 테이블 제한**: 최대 2개 테이블에서만 컬럼 선택 가능
5. **선택 순서 보장**: 사이드바와 모달에서 컬럼 선택 순서 정확히 반영
6. **실제 데이터 연동**: 테이블 관리 시스템의 실제 테이블/컬럼 데이터 사용
2025-09-05 16:19:31 +09:00
7. **사용자 경험**: react-hot-toast를 통한 친화적인 알림 시스템
8. **React 안정성**: 렌더링 중 상태 변경 문제 해결
**다음 단계:** Phase 2 - 실제 연결 생성 및 시각적 표시 기능 구현
2025-09-05 11:30:27 +09:00
2025-09-05 10:54:34 +09:00
### 주요 가치
2025-09-05 18:00:18 +09:00
- **React Flow 기반 시각적 설계**: 복잡한 테이블 관계를 직관적인 노드와 엣지로 설계
2025-09-05 10:54:34 +09:00
- **인터랙티브 캔버스**: 줌, 팬, 미니맵 등 고급 시각화 기능 제공
2025-09-05 18:00:18 +09:00
- **회사별 관리**: 각 회사별로 독립적인 테이블 관계 관리
2025-09-05 10:54:34 +09:00
- **다양한 연결 타입**: 업무 요구사항에 맞는 다양한 연결 방식
- **자동화**: 중계 테이블 자동 생성 및 외부 시스템 연동
- **확장성**: 새로운 연결 타입과 관계 유형 쉽게 추가
- **사용자 친화적**: 드래그앤드롭 기반의 직관적인 사용자 인터페이스