Files
vexplor/docs/화면간_데이터_관계_설정_시스템_설계.md
2025-09-05 16:19:31 +09:00

23 KiB

데이터 흐름 관리 시스템 설계

📋 목차

  1. 시스템 개요
  2. 핵심 기능
  3. 데이터베이스 설계
  4. 프론트엔드 설계
  5. API 설계
  6. 사용 시나리오
  7. 구현 계획

🎯 시스템 개요

데이터 흐름 관리 시스템이란?

데이터 흐름 관리 시스템은 회사별로 화면들 간의 데이터 흐름과 관계를 시각적으로 설계하고 관리할 수 있는 시스템입니다. React Flow 라이브러리를 활용하여 직관적인 노드 기반 인터페이스로 1:1, 1:N, N:1, N:N 관계를 지원하며, 다양한 연결 방식과 종류로 복합적인 데이터 흐름을 설계할 수 있습니다.

주요 특징

  • React Flow 기반 인터페이스: 직관적인 노드와 엣지 기반 시각적 설계
  • 회사별 관계 관리: 사용자 회사 코드에 따른 화면 관계 접근 제어
  • 시각적 관계 설계: 드래그앤드롭으로 화면 노드 배치 및 필드 간 연결
  • 다양한 관계 타입: 1:1, 1:N, N:1, N:N 관계 지원
  • 연결 종류별 세부 설정: 단순 키값, 데이터 저장, 외부 호출
  • 실시간 시뮬레이션: 설계한 관계의 데이터 흐름 시뮬레이션
  • 중계 테이블 자동 생성: N:N 관계에서 중계 테이블 자동 생성
  • 인터랙티브 캔버스: 줌, 팬, 미니맵 등 React Flow의 고급 기능 활용

지원하는 관계 타입

  • 1:1 (One to One): 한 화면의 필드와 다른 화면의 필드가 1:1로 연결
  • 1:N (One to Many): 한 화면의 필드가 여러 화면의 필드와 연결
  • N:1 (Many to One): 여러 화면의 필드가 한 화면의 필드와 연결
  • N:N (Many to Many): 여러 화면의 필드가 여러 화면의 필드와 연결

지원하는 연결 종류

  • 단순 키값 연결: 중계 테이블을 통한 참조 관계
  • 데이터 저장: 필드 매핑을 통한 데이터 저장
  • 외부 호출: API, 이메일, 웹훅 등을 통한 외부 시스템 연동

🚀 핵심 기능

1. React Flow 기반 화면 노드 관리

  • 화면 추가: 회사별 화면 목록에서 관계를 설정할 화면들을 React Flow 캔버스에 추가
  • 화면 배치: 드래그앤드롭으로 화면 노드를 원하는 위치에 배치
  • 화면 이동: React Flow의 내장 기능으로 화면 노드 자유롭게 이동
  • 노드 선택: 단일 또는 다중 노드 선택 지원
  • 자동 정렬: React Flow의 레이아웃 알고리즘을 활용한 자동 정렬

2. React Flow 기반 필드 간 연결 설정

  • 필드 선택: 첫 번째 화면의 필드를 클릭하여 연결 시작
  • 대상 필드 선택: 두 번째 화면의 필드를 클릭하여 연결 대상 지정
  • 드래그 연결: React Flow의 핸들(Handle)을 드래그하여 시각적 연결
  • 관계 타입 선택: 1:1, 1:N, N:1, N:N 중 선택
  • 연결 종류 선택: 단순 키값, 데이터 저장, 외부 호출 중 선택
  • 엣지 커스터마이징: 연결 타입별 색상, 스타일, 라벨 설정

3. 연결 종류별 세부 설정

단순 키값 연결

  • 중계 테이블명: 자동 생성 또는 사용자 정의
  • 연결 규칙: 중계 테이블 생성 및 관리 규칙
  • 참조 무결성: 외래키 제약조건 설정

데이터 저장

  • 필드 매핑: 소스 필드와 대상 필드 매핑 설정
  • 저장 조건: 데이터 저장 조건 정의
  • 데이터 변환: 필드 값 변환 규칙

외부 호출

  • REST API: API URL, HTTP Method, Headers, Body Template
  • 이메일: SMTP 서버, 발신자, 수신자, 제목/본문 템플릿
  • 웹훅: 웹훅 URL, Payload 형식, Payload 템플릿
  • FTP: FTP 서버, 업로드 경로, 파일명 템플릿
  • 메시지 큐: 큐 시스템, 큐 이름, 메시지 형식

4. React Flow 기반 시각적 관계 관리

  • 엣지 렌더링: React Flow의 커스텀 엣지로 화면 간 관계를 시각적으로 표현
  • 관계 타입별 스타일링: 연결 종류에 따른 색상, 선 스타일, 라벨 구분
  • 인터랙티브 캔버스: 줌, 팬, 미니맵을 통한 대규모 다이어그램 탐색
  • 실시간 시뮬레이션: 데이터 흐름 애니메이션 및 시뮬레이션
  • 관계 검증: 연결 가능성 및 무결성 검증
  • 엣지 편집: 연결선 클릭으로 관계 설정 수정

5. 관계 통계 및 관리

  • 연결 통계: 관계 타입별 연결 수 표시
  • 중계 테이블 관리: 생성된 중계 테이블 목록 및 관리
  • 관계 목록: 생성된 모든 관계 목록 조회
  • 관계 삭제: 불필요한 관계 삭제

🗄️ 데이터베이스 설계

1. 화면 관계 테이블

-- 화면 간 관계 정의
CREATE TABLE screen_relationships (
  relationship_id SERIAL PRIMARY KEY,
  relationship_name VARCHAR(200) NOT NULL,
  from_screen_id INTEGER NOT NULL,
  from_field_name VARCHAR(100) NOT NULL,
  to_screen_id INTEGER NOT NULL,
  to_field_name VARCHAR(100) NOT NULL,
  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,
  updated_by VARCHAR(50),

  -- 외래키 제약조건
  CONSTRAINT fk_screen_relationships_from_screen
    FOREIGN KEY (from_screen_id) REFERENCES screen_definitions(screen_id),
  CONSTRAINT fk_screen_relationships_to_screen
    FOREIGN KEY (to_screen_id) REFERENCES screen_definitions(screen_id)
);

-- 회사 코드 인덱스
CREATE INDEX idx_screen_relationships_company_code ON screen_relationships(company_code);

2. 중계 테이블 관리

-- 중계 테이블 정의
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
    FOREIGN KEY (relationship_id) REFERENCES screen_relationships(relationship_id)
);

-- 회사 코드 인덱스
CREATE INDEX idx_bridge_tables_company_code ON bridge_tables(company_code);

3. 외부 호출 설정

-- 외부 호출 설정
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
    FOREIGN KEY (relationship_id) REFERENCES screen_relationships(relationship_id)
);

4. 테이블 간 연계 관계

screen_definitions (화면 정의)
    ↓ (1:N)
screen_relationships (화면 관계)
    ↓ (1:N)
bridge_tables (중계 테이블)
    ↓ (1:N)
external_call_configs (외부 호출 설정)

🎨 프론트엔드 설계

1. React Flow 기반 메인 컴포넌트

// 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;
  onSave?: (relationships: ScreenRelationship[]) => void;
}

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">
          <ScreenSelector
            companyCode={companyCode}
            onScreenAdd={handleScreenAdd}
          />
          <ConnectionStatus
            selectedField={selectedField}
            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>
  );
};

2. React Flow 화면 노드 컴포넌트

// ScreenNode.tsx
import { Handle, Position } from "reactflow";

interface ScreenNodeData {
  screen: ScreenDefinition;
  onFieldClick: (screenId: string, fieldName: string) => void;
}

export const ScreenNode: React.FC<{ data: ScreenNodeData }> = ({ data }) => {
  const { screen, onFieldClick } = data;

  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">
        <div className="font-bold text-sm">{screen.screenName}</div>
        <div className="text-xs opacity-90">{screen.screenCode}</div>
        <div className="text-xs opacity-75">테이블: {screen.tableName}</div>
      </div>

      {/* 필드 목록 */}
      <div className="p-3">
        <div className="text-xs font-semibold text-gray-600 mb-2">
          필드 목록 ({screen.fields.length})
        </div>
        <div className="space-y-1">
          {screen.fields.map((field) => (
            <div
              key={field.name}
              className="flex items-center justify-between p-2 hover:bg-gray-50 rounded cursor-pointer"
              onClick={() => onFieldClick(screen.screenId, field.name)}
            >
              <div className="flex-1">
                <div className="text-sm font-medium">{field.name}</div>
                <div className="text-xs text-gray-500">{field.description}</div>
              </div>
              <div className="text-xs text-blue-600 font-mono">
                {field.type}
              </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 = {
  screenNode: ScreenNode,
};

3. 연결 설정 모달

// 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 엣지 컴포넌트

// 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 설계

1. 화면 관계 관리 API

// 화면 관계 생성
POST /api/screen-relationships
Body: {
  relationshipName: string;
  fromScreenId: number;
  fromFieldName: string;
  toScreenId: number;
  toFieldName: string;
  relationshipType: 'one-to-one' | 'one-to-many' | 'many-to-one' | 'many-to-many';
  connectionType: 'simple-key' | 'data-save' | 'external-call';
  settings: ConnectionSettings;
}

// 화면 관계 목록 조회 (회사별)
GET /api/screen-relationships?companyCode=COMP001

// 화면 관계 수정
PUT /api/screen-relationships/:id

// 화면 관계 삭제
DELETE /api/screen-relationships/:id

// 관계 시뮬레이션
POST /api/screen-relationships/:id/simulate

2. 중계 테이블 관리 API

// 중계 테이블 생성
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

// 외부 호출 설정 생성
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. 기본 관계 설정

  1. 화면 추가: 회사별 화면 목록에서 관계를 설정할 화면들을 캔버스에 추가
  2. 필드 선택: 첫 번째 화면의 필드를 클릭하여 연결 시작
  3. 대상 필드 선택: 두 번째 화면의 필드를 클릭하여 연결 대상 지정
  4. 관계 설정: 관계 타입과 연결 종류를 선택하고 세부 설정 구성
  5. 연결 생성: 설정 완료 후 연결 생성

2. 복합 데이터 흐름 설계

  1. 다중 화면 배치: 관련된 여러 화면을 캔버스에 배치
  2. 다양한 연결 타입: 단순 키값, 데이터 저장, 외부 호출을 조합
  3. 중계 테이블 활용: N:N 관계에서 중계 테이블 자동 생성
  4. 시각적 검증: 연결선과 색상으로 관계 유형 구분

3. 외부 시스템 연동

  1. API 연결: REST API 호출을 통한 외부 시스템 연동
  2. 이메일 알림: 데이터 변경 시 이메일 자동 전송
  3. 웹훅 설정: 실시간 데이터 동기화
  4. 메시지 큐: 비동기 데이터 처리

📅 구현 계획

Phase 1: React Flow 기본 설정 (1주) 완료

  • React Flow 라이브러리 설치 및 설정 (@xyflow/react 12.8.4)
  • 기본 노드와 엣지 컴포넌트 구현
  • 화면 노드 컴포넌트 구현 (ScreenNode.tsx)
  • 기본 연결선 그리기 (CustomEdge.tsx)
  • 메인 데이터 흐름 관리 컴포넌트 구현 (DataFlowDesigner.tsx)
  • /admin/dataflow 페이지 생성
  • 메뉴 시스템 연동 (SQL 스크립트 제공)
  • 샘플 노드 추가/삭제 기능
  • 노드 간 드래그앤드롭 연결 기능
  • 줌, 팬, 미니맵 등 React Flow 기본 기능

Phase 2: 관계 설정 기능 (2주) - 🚧 진행 중 (70% 완료)

  • 연결 설정 모달 UI 구현
  • 1:1, 1:N, N:1, N:N 관계 타입 선택 UI
  • 단순 키값, 데이터 저장, 외부 호출 연결 종류 UI
  • 필드-to-필드 연결 시스템 (클릭 기반)
  • 선택된 필드 정보 표시 및 순서 보장
  • 연결 생성 로직 구현 (모달에서 실제 엣지 생성)
  • 생성된 연결의 시각적 표시 (React Flow 엣지)
  • 연결 데이터 백엔드 저장 API 연동
  • 기존 연결 수정/삭제 기능

Phase 3: 고급 연결 타입 (2-3주)

  • 데이터 저장 연결
  • 외부 호출 연결
  • 중계 테이블 자동 생성
  • 커스텀 엣지 스타일링

Phase 4: React Flow 고급 기능 (1-2주)

  • 줌, 팬, 미니맵 기능
  • 노드 선택 및 다중 선택
  • 키보드 단축키 지원
  • 레이아웃 자동 정렬

Phase 5: 시각화 및 관리 (1-2주)

  • 관계 시뮬레이션
  • 연결 통계 및 관리
  • 관계 검증
  • 데이터 흐름 애니메이션

Phase 6: 고급 기능 (2-3주)

  • N:N 관계 지원
  • 복합 데이터 흐름
  • 외부 시스템 연동
  • 성능 최적화

🎯 결론

데이터 흐름 관리 시스템을 통해 ERP 시스템의 화면들 간 데이터 흐름을 시각적으로 설계하고 관리할 수 있습니다. React Flow 라이브러리를 활용한 직관적인 노드 기반 인터페이스와 회사별 권한 관리, 기존 화면관리 시스템과의 완벽한 연동을 통해 체계적인 데이터 관계 관리가 가능합니다.

📊 구현 현황

Phase 1 완료 (2024-12-19)

구현된 기능:

  • React Flow 12.8.4 기반 시각적 캔버스
  • 화면 노드 컴포넌트 (필드 정보, 타입별 색상 구분, 노드 리사이징)
  • 커스텀 엣지 컴포넌트 (관계 타입별 스타일링)
  • 드래그앤드롭 노드 배치 및 연결
  • 줌, 팬, 미니맵 등 고급 시각화 기능 (스크롤 충돌 해결)
  • 실제 화면 데이터 연동 (테이블 관리 API 연결)
  • 필드-to-필드 연결 시스템 (클릭 기반, 2개 화면 제한)
  • 연결 설정 모달 (관계 타입, 연결 종류 선택 UI)
  • /admin/dataflow 경로 설정
  • 메뉴 시스템 연동 완료
  • 사용자 경험 개선 (토스트 알림, 선택 순서 보장)

구현된 파일:

  • frontend/components/dataflow/DataFlowDesigner.tsx - 메인 캔버스 컴포넌트
  • frontend/components/dataflow/ScreenNode.tsx - 화면 노드 컴포넌트 (NodeResizer 포함)
  • 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를 통한 노드 크기 조정 및 내용 반영
  3. 필드-to-필드 연결: 드래그앤드롭 대신 클릭 기반 필드 선택 방식
  4. 2개 화면 제한: 최대 2개 화면에서만 필드 선택 가능
  5. 선택 순서 보장: 사이드바와 모달에서 필드 선택 순서 정확히 반영
  6. 실제 데이터 연동: 테이블 관리 시스템의 실제 화면/필드 데이터 사용
  7. 사용자 경험: react-hot-toast를 통한 친화적인 알림 시스템
  8. React 안정성: 렌더링 중 상태 변경 문제 해결

다음 단계: Phase 2 - 실제 연결 생성 및 시각적 표시 기능 구현

주요 가치

  • React Flow 기반 시각적 설계: 복잡한 데이터 관계를 직관적인 노드와 엣지로 설계
  • 인터랙티브 캔버스: 줌, 팬, 미니맵 등 고급 시각화 기능 제공
  • 회사별 관리: 각 회사별로 독립적인 관계 관리
  • 다양한 연결 타입: 업무 요구사항에 맞는 다양한 연결 방식
  • 자동화: 중계 테이블 자동 생성 및 외부 시스템 연동
  • 확장성: 새로운 연결 타입과 관계 유형 쉽게 추가
  • 사용자 친화적: 드래그앤드롭 기반의 직관적인 사용자 인터페이스