Files
ExperionCrawler/.rooBackup/2026-05-02_0530/futurePlan/End-to-End P&ID Graph Pipeline/Graph_Pipeline_Phase4.md

6.5 KiB

🎨 Graph Pipeline Phase 4: 활용 및 시각화 (Application & Visualization)

이 문서는 P&ID Graph Pipeline의 최종 단계인 활용 및 시각화의 상세 구현 계획을 다룹니다. 앞선 단계에서 구축한 [기하학적 데이터 \rightarrow 위상 그래프 \rightarrow 시스템 태그 매핑] 결과물을 결합하여, 운영자가 도면 상에서 실시간 공정 상태를 파악하고 장애 영향도를 분석할 수 있는 인터페이스를 구현하는 것이 목표입니다.


📦 1. 필수 패키지 및 기술 스택

1.1 프론트엔드 (Visualization)

기술/라이브러리 용도 비고
SVG / Canvas API P&ID 도면 렌더링 및 데이터 오버레이 벡터 기반 정밀 렌더링
Cytoscape.js / D3.js 위상 그래프 시각화 및 인터랙티브 탐색 그래프 분석 뷰어
Vue.js / React 전체 UI 프레임워크 및 상태 관리 src/Web 구조와 통합
Axios / WebSocket 실시간 OPC UA 데이터 수신 및 API 통신 실시간 업데이트

1.2 백엔드 (API & Analysis)

기술/라이브러리 용도 비고
ASP.NET Core Graph API 및 분석 엔드포인트 제공 ExperionCrawler 메인 서버
NetworkX (Python) 영향도 분석 및 경로 추적 알고리즘 실행 분석 엔진 (Phase 2 활용)
FastAPI / Flask Python 분석 엔진과 C# 서버 간의 브릿지 분석 마이크로서비스

📐 2. 상세 설계 구조

2.1 실시간 데이터 오버레이 (Real-time Overlay)

도면의 좌표 정보와 매핑된 시스템 태그를 연결하여 실시간 값을 표시합니다.

  1. 매핑 데이터 로드: (도면노드ID, 시스템태그, 좌표) 리스트를 프론트엔드로 전달.
  2. 실시간 스트리밍: OPC UA \rightarrow C# Server \rightarrow WebSocket \rightarrow Frontend.
  3. 동적 렌더링: 태그 값이 변경되면 해당 좌표의 SVG 요소 색상을 변경하거나 툴팁에 현재 값을 표시.

2.2 영향도 분석 엔진 (Impact Analysis Engine)

특정 설비의 이상 발생 시 하류(Downstream) 영향을 계산합니다.

  1. 분석 요청: 사용자가 도면에서 특정 노드(예: 펌프 P-101)를 클릭.
  2. 그래프 탐색: Python 분석 엔진에서 nx.descendants(G, 'P-101') 실행.
  3. 결과 반환: 영향받는 모든 노드 ID 리스트와 경로(Path)를 반환.
  4. 시각적 강조: 도면 상에서 영향 경로를 하이라이트(예: 빨간색 선) 처리.

💻 3. 실제 구현 코딩 가이드 (Example)

3.1 [Backend] 영향도 분석 API (C# \rightarrow Python Bridge)

// src/Web/Controllers/PidGraphController.cs

// 1. 분석 상태 추적을 위한 DTO
public record AnalysisStatus(string taskId, double progress, string status, string message);

// 2. 실시간 진행 상태 조회 API (Phase 5 병렬 처리 반영)
[HttpGet("status/{taskId}")]
public async Task<IActionResult> GetAnalysisStatus(string taskId)
{
    // Orchestrator가 관리하는 작업 상태 저장소(Redis/MemoryCache)에서 조회
    var status = await _statusService.GetStatusAsync(taskId);
    if (status == null) return NotFound();
    
    return Ok(new {
        taskId = status.TaskId,
        progress = status.Progress, // 0.0 ~ 1.0
        status = status.Status,     // "Processing", "Completed", "Failed"
        message = status.Message
    });
}

[HttpGet("impact/{nodeId}")]
public async Task<IActionResult> GetImpactAnalysis(string nodeId)
{
    // Python 분석 마이크로서비스에 요청
    var response = await _httpClient.GetAsync($"http://python-analysis-api/impact/{nodeId}");
    var result = await response.Content.ReadFromJsonAsync<ImpactResult>();
    
    return Ok(result);
}

3.2 [Frontend] SVG 데이터 오버레이 및 진행률 표시 (JavaScript)

// src/Web/wwwroot/js/pid-viewer.js

// 1. 실시간 값 업데이트
async function updateRealtimeValues(tagData) {
    for (const [tag, value] of Object.entries(tagData)) {
        const element = document.getElementById(`tag-node-${tag}`);
        if (element) {
            element.style.fill = value > threshold ? 'red' : 'green';
            element.setAttribute('data-value', value);
            const tooltip = document.getElementById('pid-tooltip');
            tooltip.innerText = `${tag}: ${value}`;
        }
    }
}

// 2. 분석 진행 상태 표시 (Phase 5 병렬 처리 반영)
async function trackAnalysisProgress(taskId) {
    const progressBar = document.getElementById('analysis-progress-bar');
    const statusText = document.getElementById('analysis-status-text');

    const pollStatus = async () => {
        const response = await fetch(`/api/pid/status/${taskId}`);
        const data = await response.json();

        // 프로그레스 바 업데이트 (예: 20% -> 40% -> 100%)
        progressBar.style.width = `${data.progress * 100}%`;
        statusText.innerText = `분석 중... ${Math.round(data.progress * 100)}% (${data.message})`;

        if (data.status !== 'Completed' && data.status !== 'Failed') {
            setTimeout(pollStatus, 1000); // 1초 간격 폴링
        } else {
            statusText.innerText = data.status === 'Completed' ? '분석 완료!' : '분석 실패';
        }
    };

    pollStatus();
}

3.3 [Analysis] 경로 추적 유틸리티 (Python)

import networkx as nx

def get_propagation_path(graph, start_node, end_node):
    """장애 전파 경로를 최단 경로 기반으로 추출"""
    try:
        path = nx.shortest_path(graph, source=start_node, target=end_node)
        return path
    except nx.NetworkXNoPath:
        return None

# 예: P-101에서 V-105까지의 영향 경로 추출
path = get_propagation_path(topology_graph, "P-101", "V-105")

🚀 4. Phase 4 완료 기준 (Definition of Done)

  • P&ID 도면(SVG/Canvas) 위에 실시간 OPC UA 값이 정확한 좌표에 표시되는가?
  • 병렬 처리 중인 분석 작업의 **진행 상태(Progress Bar)**가 UI에 실시간으로 반영되는가? (Phase 5 반영)
  • 특정 노드 클릭 시 하류 영향도 분석(Impact Analysis) 결과가 시각적으로 하이라이트 되는가?
  • C# 메인 서버와 Python 분석 엔진 간의 API 통신이 지연 없이 이루어지는가?
  • 운영자가 도면을 통해 이상 징후의 전파 경로를 직관적으로 파악할 수 있는가?
  • 전체 파이프라인(추출 $\rightarrow$ 모델링 $\rightarrow$ 매핑 $\rightarrow$ 시각화)이 통합되어 동작하는가?