AquaView의 시각적 표현은 SVG 직접 조작, Recharts 쳄트, CSS 변수 기반 다크 테마 3가지 기술로 구성됩니다.

1. SVG 공정도 (ProcessFlowDiagram)

React에서 SVG를 JSX로 직접 작성하면 JavaScript로 연동된 동적 벡터 그래픽을 만들 수 있습니다.

레이아웃 수식

5개 공정 박스를 SVG 너비를 동등분해 배치합니다:

const svgWidth = 700;
const slotW = svgWidth / STAGES.length;  // 공정 1개당 너비 = 140px

// i번째 공정의 중심
const centerX = slotW * i + slotW / 2;
const boxW = slotW * 0.7;   // 공정 박스 너비

흐름 애니메이션 (linearGradient + animateTransform)

<defs>
  <linearGradient id="flowGrad" x1="0" x2="1" y1="0" y2="0">
    <stop offset="0%"   stopColor="#3b82f6" stopOpacity="0" />
    <stop offset="50%"  stopColor="#3b82f6" stopOpacity="0.8" />
    <stop offset="100%" stopColor="#3b82f6" stopOpacity="0" />
    <animateTransform
      attributeName="gradientTransform"
      type="translate"
      from="-1 0" to="1 0"
      dur="2s" repeatCount="indefinite"
    />
  </linearGradient>
</defs>

animateTransform으로 그라디언트를 좌우로 이동시켜 정수가 흑러가는 듯한 시각 효과를 연출합니다.

화살표 마커

<defs>
  <marker id="arrowhead" markerWidth="8" markerHeight="8"
          refX="6" refY="4" orient="auto">
    <polygon points="0 0, 8 4, 0 8" fill="#475569" />
  </marker>
</defs>

{/* 연결선에 화살표 적용 */}
<line
  x1={prevCenterX + boxW / 2}
  x2={centerX - boxW / 2}
  y1={centerY} y2={centerY}
  stroke="#334155"
  markerEnd="url(#arrowhead)"
/>

동적 색상과 선택 상태

const isSelected = stage.key === selectedStage;
const statusColor = getStatusColor(stageStatus);  // normal/warning/danger → 색상

<g onClick={() => onSelectStage(stage.key)} style={{ cursor: "pointer" }}>
  <rect
    fill={`${stage.color}22`}   // 헥사 컬러 16진수 투명도 (22 = 13%)
    stroke={isSelected ? stage.color : "transparent"}
    strokeWidth={isSelected ? 2 : 0}
  />
  {/* 위험/경고 아이콘 */}
  {stageStatus !== "normal" && (
    <text fill={statusColor} fontSize="14">⚠</text>
  )}
</g>

2. Recharts 코차트 (HistoryChart)

// HistoryChart.jsx
import {
  LineChart, Line, XAxis, YAxis,
  CartesianGrid, Tooltip, ReferenceLine, ResponsiveContainer
} from "recharts";

return (
  <ResponsiveContainer width="100%" height={220}>
    <LineChart data={history?.data ?? []}>
      <CartesianGrid strokeDasharray="3 3" stroke="#334155" />
      <XAxis
        dataKey="timestamp"
        tickFormatter={(v) => new Date(v).toLocaleTimeString("ko", { hour: "2-digit", minute: "2-digit" })}
      />
      <YAxis domain={["auto", "auto"]} />

      {/* 다크 테마 Tooltip */}
      <Tooltip
        contentStyle={{
          background: "#1e293b",
          border: "1px solid #334155",
          color: "#e2e8f0",
        }}
      />

      {/* 정상 범위 기준선 */}
      <ReferenceLine y={config.normal[0]} stroke="#22c55e" strokeDasharray="4 4"
        label={{ value: "정상 하한", fill: "#22c55e", fontSize: 10 }} />
      <ReferenceLine y={config.normal[1]} stroke="#22c55e" strokeDasharray="4 4"
        label={{ value: "정상 상한", fill: "#22c55e", fontSize: 10 }} />

      <Line
        dataKey="value"
        stroke="#38bdf8"
        dot={false}           // 각 포인트 컴 제거 (시각 포켬, 성능 향상)
        activeDot={{ r: 4 }}  // 호버 시만 컴 표시
        strokeWidth={2}
        isAnimationActive={false}  // 폴링 업데이트 시 쳨리면성 낭매는 현상 방지
      />
    </LineChart>
  </ResponsiveContainer>
);

isAnimationActive={false}: 3초마다 데이터가 갱신되면 차트가 매번 애니메이션을 재시작하는 현상을 방지합니다.


3. CSS 변수 기반 다크 테마

Design Token