Skip to main content

화면 구성 — 시각화 (tree/graph)

기본 화면 문법은 화면 구성 (기본), 고급 문법은 화면 구성 (고급)을 참조하세요.

개요

treegraph screenType은 config-driven 시각화 아키텍처를 따릅니다. 캔버스 디자이너에서 설정한 treeConfig 또는 graphConfig가 런타임에서 자동으로 렌더링되며, 코드 수정 없이 다양한 솔루션에 재사용할 수 있습니다.

핵심 설계 원칙:

  • 선언적 구성: JSON config만으로 트리/그래프 화면 생성
  • 동적 컬럼 접근: parentColumn, childColumn 등으로 테이블 컬럼을 동적 참조 (getField 패턴)
  • 솔루션 독립: MES LOT 계보, ERP BOM, EAM 설비 계층 등 동일 엔진으로 처리

데이터 흐름

캔버스 디자이너에서 런타임 렌더링까지의 전체 파이프라인입니다.

┌─────────────────────────┐
│ Canvas Designer │
│ ScreenViewNodePanel │
│ (treeConfig/graphConfig│
│ 설정 UI) │
└──────────┬──────────────┘
│ JSON 저장

┌─────────────────────────┐
│ runtimeStore │
│ (screenType, config │
│ 로드 및 상태 관리) │
└──────────┬──────────────┘
│ props 전달

┌─────────────────────────┐
│ ScreenModal │
│ (screenType 분기) │
│ tree → RuntimeTreeView │
│ graph → RuntimeGraphView│
└──────────┬──────────────┘
│ config 해석

┌─────────────────────────┐
│ 시각화 컴포넌트 │
│ - LotGenealogyTree │
│ - LotTraceGraph │
│ (React Flow 기반 렌더링)│
└─────────────────────────┘
데이터 흐름 요약
  1. 디자이너에서 treeConfig/graphConfig를 JSON으로 저장
  2. runtimeStore가 해당 설정을 로드하여 상태 관리
  3. ScreenModalscreenType에 따라 적절한 뷰 컴포넌트로 분기
  4. 뷰 컴포넌트가 config의 컬럼명을 기반으로 데이터를 동적 조회하여 시각화

treeConfig 상세

트리뷰 화면의 전체 설정 구조입니다.

전체 JSON 예시

{
"refId": "scr_lot_genealogy_tree",
"label": "LOT 계보 트리",
"screenType": "tree",
"menuIcon": "ApartmentOutlined",
"menuOrder": 5,
"boundTableRef": "lot_genealogy",
"parentMenuRef": "menu_mes_production",
"treeConfig": {
"parentColumn": "parent_lot_id",
"childColumn": "child_lot_id",
"labelColumn": "lot_number",
"badgeColumn": "relation_type",
"detailColumns": ["consumed_qty", "produced_qty", "linked_at"],
"direction": "TB",
"maxDepth": 10,
"searchEnabled": true,
"detailPanelEnabled": true
},
"listConfig": {
"columns": [
{ "columnName": "parent_lot_id", "width": 150, "sortable": true },
{ "columnName": "child_lot_id", "width": 150, "sortable": true },
{ "columnName": "relation_type", "width": 100, "filterable": true }
],
"defaultSort": { "columnName": "linked_at", "order": "descend" },
"pageSize": 20
}
}

treeConfig 필드 명세

필드타입필수기본값설명
parentColumnstring필수부모 레코드를 가리키는 FK 컬럼명
childColumnstring필수자식 레코드를 가리키는 FK 컬럼명
labelColumnstring필수트리 노드에 표시할 라벨 컬럼 (마스터 테이블)
badgeColumnstring선택관계유형 뱃지 컬럼 (ENUM 권장)
detailColumnsstring[]선택[]노드 클릭 시 표시할 보조 정보 컬럼들
directionstring선택"TB"트리 방향: TB (상→하), LR (좌→우), BT (하→상)
maxDepthnumber선택10최대 탐색 깊이 (순환 참조 방지)
searchEnabledboolean선택true검색 바 표시 여부
detailPanelEnabledboolean선택true노드 클릭 시 상세 패널 표시 여부

동작 원리

parentColumnchildColumnboundTableRef 테이블의 실제 컬럼명입니다. 런타임에서 getField 패턴으로 동적 컬럼에 접근하여 트리 구조를 구성합니다.

parentColumn: "parent_lot_id" → record[getField("parent_lot_id")]
childColumn: "child_lot_id" → record[getField("child_lot_id")]
labelColumn: "lot_number" → 마스터 테이블에서 표시용 값 조회
direction 옵션
  • TB (Top → Bottom): 부모가 위, 자식이 아래 — BOM, 조직도에 적합
  • LR (Left → Right): 부모가 좌, 자식이 우 — 프로세스 흐름에 적합
  • BT (Bottom → Top): 자식이 위, 부모가 아래 — 역추적에 적합

graphConfig 상세

네트워크 그래프 화면의 전체 설정 구조입니다.

전체 JSON 예시

{
"refId": "scr_lot_trace_graph",
"label": "LOT 추적 그래프",
"screenType": "graph",
"menuIcon": "DeploymentUnitOutlined",
"menuOrder": 6,
"boundTableRef": "lot_genealogy",
"parentMenuRef": "menu_mes_production",
"graphConfig": {
"sourceColumn": "parent_lot_id",
"targetColumn": "child_lot_id",
"labelColumn": "lot_number",
"edgeLabelColumn": "relation_type",
"edgeWeightColumn": "consumed_qty",
"layout": "elk",
"detailPanelEnabled": true,
"zoomControlEnabled": true,
"minimapEnabled": true
},
"listConfig": {
"columns": [
{ "columnName": "parent_lot_id", "width": 150, "sortable": true },
{ "columnName": "child_lot_id", "width": 150, "sortable": true },
{ "columnName": "relation_type", "width": 100, "filterable": true },
{ "columnName": "consumed_qty", "width": 100 }
],
"defaultSort": { "columnName": "linked_at", "order": "descend" },
"pageSize": 20
}
}

graphConfig 필드 명세

필드타입필수기본값설명
sourceColumnstring필수소스(출발) 노드 FK 컬럼명
targetColumnstring필수타겟(도착) 노드 FK 컬럼명
labelColumnstring필수노드 라벨 컬럼 (마스터 테이블)
edgeLabelColumnstring선택엣지(간선) 라벨 컬럼
edgeWeightColumnstring선택엣지 가중치 컬럼 (선 두께에 반영)
layoutstring선택"elk"레이아웃 엔진
detailPanelEnabledboolean선택true노드 클릭 시 상세 패널 표시 여부
zoomControlEnabledboolean선택true확대/축소 컨트롤 표시 여부
minimapEnabledboolean선택true미니맵 표시 여부

layout 옵션

레이아웃설명적합한 데이터
elk계층형 레이아웃LOT 계보, BOM 구조 등 방향성 있는 데이터 (기본값)
force자유 네트워크거래처 관계, 부서 간 협업 등 비계층 데이터
circular원형 레이아웃순환 프로세스, 주기적 관계 시각화
레이아웃 선택 기준
  • 방향성이 있는 데이터 (부모→자식, 공급→소비): elk 권장
  • 동등한 관계의 네트워크: force 권장
  • 순환/주기 구조: circular 권장

다른 솔루션 적용 가이드

treegraph screenType은 솔루션에 독립적입니다. parentColumn/childColumn만 해당 테이블의 실제 컬럼명으로 변경하면 동일 엔진으로 다양한 시각화를 구현할 수 있습니다.

예시 1: MES LOT 계보 (현재 구현)

생산 LOT 간의 부모-자식 관계를 트리로 시각화합니다.

{
"refId": "scr_lot_genealogy_tree",
"screenType": "tree",
"boundTableRef": "lot_genealogy",
"treeConfig": {
"parentColumn": "parent_lot_id",
"childColumn": "child_lot_id",
"labelColumn": "lot_number",
"direction": "TB",
"maxDepth": 10
}
}

예시 2: ERP BOM 트리

제품의 부품 구성(Bill of Materials)을 트리로 시각화합니다.

{
"refId": "scr_bom_tree",
"screenType": "tree",
"boundTableRef": "bom",
"treeConfig": {
"parentColumn": "parent_item_id",
"childColumn": "child_item_id",
"labelColumn": "item_name",
"badgeColumn": "bom_type",
"direction": "TB",
"maxDepth": 8
}
}

예시 3: EAM 설비 계층

공장 > 라인 > 설비 > 부품의 계층 구조를 시각화합니다.

{
"refId": "scr_equipment_hierarchy",
"screenType": "tree",
"boundTableRef": "equipment_hierarchy",
"treeConfig": {
"parentColumn": "parent_equipment_id",
"childColumn": "child_equipment_id",
"labelColumn": "equipment_name",
"direction": "TB",
"maxDepth": 6
}
}
적용 패턴 요약

모든 예시에서 공통되는 패턴:

  1. boundTableRef를 관계 테이블로 지정
  2. parentColumn/childColumn에 해당 테이블의 FK 컬럼명 설정
  3. labelColumn에 마스터 테이블의 표시용 컬럼명 설정
  4. directionmaxDepth는 데이터 특성에 맞게 조정

규칙

  1. screenType: "tree" 화면은 반드시 treeConfig를 정의해야 하고, screenType: "graph" 화면은 반드시 graphConfig를 정의해야 합니다.
  2. parentColumn/childColumn (또는 sourceColumn/targetColumn)은 boundTableRef 테이블의 실제 존재하는 컬럼명이어야 합니다.
  3. labelColumn은 마스터 테이블의 표시용 컬럼명입니다. FK를 통해 참조되는 테이블에서 해당 컬럼을 조회합니다.
  4. listConfig를 함께 지정하면 트리/그래프 뷰를 지원하지 않는 환경에서 fallback 리스트 뷰를 제공합니다.
  5. treeConfig 또는 graphConfigundefined이면 lot_genealogy 테이블 기준의 기본값으로 동작합니다.

제한사항 및 향후 계획

현재 제한사항

  • API 엔드포인트 하드코딩: lot_tracking, lot_process_histories, lot_material_links API는 현재 MES 솔루션 전용으로 하드코딩되어 있습니다. 다른 솔루션에서 tree/graph 화면을 사용할 경우 백엔드 API를 별도 구현해야 합니다.
  • 마스터 테이블 해석: labelColumn이 참조하는 마스터 테이블은 현재 lot_genealogy 기반으로 고정되어 있습니다.

향후 계획

Phase내용상태
2masterTableName 등 일반화 — API 엔드포인트 자동 매핑예정
3graphConfig layout 옵션 확장 (dagre, radial)예정
4timeline screenType 추가 — 시간축 기반 시각화예정
Phase 1 한계

현재(Phase 1)에서는 tree/graph config가 설정되어 있어도 백엔드 API가 MES LOT 전용입니다. 다른 솔루션에 적용하려면 해당 솔루션의 데이터 조회 API를 먼저 구현해야 합니다. Phase 2에서 masterTableName 기반 자동 API 매핑이 추가될 예정입니다.


JSONB 필드 시각화

개요

노코드 플랫폼에서 JSONB 타입 컬럼에 저장된 데이터를 자동으로 시각화 렌더링하는 기능입니다. 기존 CRUD 기능(목록 조회, 검색, 필터, 수정, 삭제)은 100% 유지하면서, JSONB 값의 구조를 감지하여 적절한 시각화를 제공합니다.

핵심 원리:

  • 구조 기반 자동 감지: JSONB 값에 root + nodes + edges 구조가 존재하면 그래프로 렌더링
  • CRUD 무영향: 기존 목록/검색/필터/수정/삭제 기능은 변경 없이 그대로 동작
  • 범용 적용: lot_trace_records 뿐만 아니라 어떤 테이블이든 동일 구조의 JSONB 컬럼이 있으면 자동 시각화
tree/graph screenType과의 차이

tree/graph screenType은 관계 테이블 전체를 시각화하는 전용 화면입니다. JSONB 필드 시각화는 일반 CRUD 화면(list, form) 내에서 특정 JSONB 컬럼의 값을 인라인으로 시각화합니다. 두 기능은 상호 보완적으로 사용됩니다.


추적결과 JSON 스키마

JSONB 컬럼에 저장되는 그래프 데이터의 표준 스키마입니다.

interface TraceResultJson {
root: string; // 시작 LOT 번호
direction?: 'forward' | 'backward'; // 추적 방향
nodes: Array<{
lotNumber: string; // LOT 식별번호
level: number; // 트리 깊이 (0=루트)
status: string; // LOT 상태
quantity: number; // 수량
}>;
edges: Array<{
from: string; // 출발 LOT
to: string; // 도착 LOT
relationType: string; // 관계유형
quantity: number; // 이동 수량
}>;
}

스키마 필드 명세

필드타입필수설명
rootstring필수추적 시작점 LOT 번호
directionstring선택추적 방향: "forward" (정추적) 또는 "backward" (역추적)
nodesarray필수그래프 노드(LOT) 배열
nodes[].lotNumberstring필수LOT 식별번호 (노드 라벨)
nodes[].levelnumber필수트리 깊이 (루트=0, 하위로 갈수록 증가)
nodes[].statusstring필수LOT 상태 (색상 매핑에 사용)
nodes[].quantitynumber필수수량
edgesarray필수그래프 엣지(연결선) 배열
edges[].fromstring필수출발 LOT 번호
edges[].tostring필수도착 LOT 번호
edges[].relationTypestring필수관계유형 (색상 매핑에 사용)
edges[].quantitynumber필수이동 수량

자동 감지 조건

시스템은 JSONB 값을 파싱하여 다음 조건을 모두 만족하면 그래프 시각화를 활성화합니다.

function isGraphJson(value: unknown): boolean {
return (
typeof value === 'object' &&
value !== null &&
'root' in value &&
'nodes' in value &&
'edges' in value &&
Array.isArray(value.nodes) &&
Array.isArray(value.edges)
);
}

렌더링 동작

JSONB 필드의 시각화는 기존 CRUD 화면 내에서 3가지 뷰에서 각각 다르게 동작합니다.

기존 (일반 JSON)변경 후 (그래프 JSON)
목록 셀잘린 텍스트 + 툴팁정추적 · 3개 LOT 배지 태그
상세 모달<pre> raw JSON3탭: 그래프 / 트리 / JSON
폼 편집TextAreaTextArea (변경 없음)

목록 셀 배지 태그

그래프 구조가 감지된 JSONB 셀은 요약 배지로 표시됩니다.

┌─────────────────────────────────────────┐
│ LOT번호 │ 품목 │ 추적결과 │
├─────────────────────────────────────────┤
│ LOT-001 │ 볼트 │ [정추적 · 3개 LOT] │
│ LOT-002 │ 너트 │ [역추적 · 5개 LOT] │
│ LOT-003 │ 와셔 │ {"key": "일반JSON"} │ ← 그래프 구조 아님, 기존 렌더링
└─────────────────────────────────────────┘

배지 표시 규칙:

  • 방향 표시: direction"forward"이면 정추적, "backward"이면 역추적, 없으면 추적
  • 노드 수 표시: nodes 배열의 길이를 N개 LOT로 표시
  • 색상: Ant Design Tag 컴포넌트의 blue 프리셋 사용

상세 모달 3탭 구성

상세 보기에서 그래프 JSON이 감지되면 3개 탭으로 렌더링됩니다.

┌─────────────────────────────────────┐
│ [그래프] [트리] [JSON] │
├─────────────────────────────────────┤
│ │
│ 그래프 탭: │
│ React Flow 기반 네트워크 그래프 │
│ 노드 = LOT, 엣지 = 관계 │
│ 상태별 색상, 관계유형별 엣지 색상 │
│ │
│ 트리 탭: │
│ Ant Design Tree 기반 계층 트리 │
│ 레벨별 들여쓰기, 상태 뱃지 표시 │
│ │
│ JSON 탭: │
│ <pre> raw JSON (기존 동작 유지) │
│ │
└─────────────────────────────────────┘
동적 임포트

그래프 및 트리 컴포넌트는 React.lazy로 동적 임포트됩니다. 그래프 JSON이 없는 일반 CRUD 화면에서는 해당 번들이 로드되지 않으므로 성능에 영향을 주지 않습니다.


지원 상태값 및 색상

노드(LOT)의 status 필드값에 따라 자동으로 색상이 매핑됩니다.

상태색상Hex용도
생산 / 생산중blue#1677ff생산 진행 중인 LOT
검사중orange#fa8c16품질 검사 대기/진행
합격green#52c41a품질 검사 통과
불합격red#ff4d4f품질 불량 대상
회수pink#eb2f96회수 대상
출하 / 출하완료cyan#13c2c2출하 완료된 LOT

색상 매핑 로직:

function getStatusColor(status: string): string {
const colorMap: Record<string, string> = {
'생산': '#1677ff',
'생산중': '#1677ff',
'검사중': '#fa8c16',
'합격': '#52c41a',
'불합격': '#ff4d4f',
'회수': '#eb2f96',
'출하': '#13c2c2',
'출하완료': '#13c2c2',
};
return colorMap[status] ?? '#d9d9d9'; // 미매핑 상태는 회색
}
커스텀 상태

위 목록에 없는 상태값은 기본 회색(#d9d9d9)으로 렌더링됩니다. 향후 캔버스 디자이너에서 상태-색상 매핑을 사용자 정의할 수 있도록 확장할 예정입니다.


지원 관계유형 및 색상

엣지(연결선)의 relationType 필드값에 따라 색상이 매핑됩니다.

관계유형색상Hex용도
자재투입파랑#1677ff원자재가 생산 LOT에 소비되는 관계
공정연계초록#52c41a공정 간 LOT 이동 관계
분할주황#fa8c16하나의 LOT가 여러 LOT로 분할
합병보라#722ed1여러 LOT가 하나로 합병

색상 매핑 로직:

function getRelationColor(relationType: string): string {
const colorMap: Record<string, string> = {
'자재투입': '#1677ff',
'공정연계': '#52c41a',
'분할': '#fa8c16',
'합병': '#722ed1',
};
return colorMap[relationType] ?? '#8c8c8c'; // 미매핑 관계유형은 회색
}

확장성

JSONB 필드 시각화는 테이블 및 솔루션에 독립적으로 동작합니다. root + nodes + edges 구조만 충족하면 어떤 JSONB 컬럼에서든 자동으로 시각화됩니다.

적용 가능한 시나리오

솔루션테이블JSONB 컬럼시각화 내용
MESlot_trace_recordstrace_resultLOT 추적 그래프
SCMsupply_chain_analysisnetwork_data공급망 네트워크
QMSinspection_resultsdefect_tree불량 원인 트리
EAMfailure_analysiscause_graph고장 원인 분석 그래프

커스텀 그래프 데이터 예시

사용자가 직접 JSONB 컬럼에 그래프 데이터를 입력하면 자동으로 시각화됩니다.

{
"root": "PROC-001",
"direction": "forward",
"nodes": [
{ "lotNumber": "PROC-001", "level": 0, "status": "완료", "quantity": 1 },
{ "lotNumber": "PROC-002", "level": 1, "status": "진행중", "quantity": 1 },
{ "lotNumber": "PROC-003", "level": 1, "status": "대기", "quantity": 1 }
],
"edges": [
{ "from": "PROC-001", "to": "PROC-002", "relationType": "공정연계", "quantity": 1 },
{ "from": "PROC-001", "to": "PROC-003", "relationType": "분할", "quantity": 1 }
]
}

위 데이터가 어떤 테이블의 JSONB 컬럼에 저장되어 있든, 시스템은 자동으로 그래프 구조를 감지하고 시각화합니다.

스키마 준수

자동 시각화가 동작하려면 root, nodes, edges 필드가 모두 존재해야 합니다. 하나라도 누락되면 기존 JSON 렌더링(raw text)으로 fallback됩니다.


검증 체크리스트

JSONB 필드 시각화 구현 시 확인해야 할 항목입니다.

  • JsonGraphMini 컴포넌트 생성 완료 — runtime/JsonGraphMini.tsx (ReactFlow + ELK, 읽기전용)
  • JsonTreeMini 컴포넌트 생성 완료 — runtime/JsonTreeMini.tsx (Ant Design Tree, 순환방지)
  • renderDetailValue() 그래프 감지 로직 추가 — isTraceResultJson() 타입가드 + Tabs 렌더링
  • renderCellValue() 배지 태그 렌더링 추가 — 정추적 · 3개 LOT 형태 Tag
  • React.lazy 동적 임포트 적용 — 모듈 스코프 호이스팅 완료 (불필요 리마운트 방지)
  • 기존 JSON/JSONB 렌더링 유지 확인 — 비그래프 JSON은 기존 <pre> / 툴팁 유지
  • TypeScript 빌드 검증 (tsc --noEmit) — 2026-03-11 통과
  • 상세 모달 3탭 (그래프/트리/JSON) 동작 — DB 시드 + 런타임 서버 필요
  • 목록 셀 배지 태그 표시 — DB 시드 + 런타임 서버 필요
  • 문서 업데이트 완료 — 색상 Ant Design v5 일치 검증 완료

이전: 화면 구성 (고급) | 다음: 워크플로우와 대시보드