# 메인 대시보드 차트 구성 가이드 > 관리자 시스템 메인화면은 대시보드 차트로 구성한다. > 네이버 클라우드 콘솔의 "서비스 사용 현황" 및 "리소스 모니터링" 화면을 참조한다. ## 메인 대시보드 레이아웃 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ GUARDiA Manager — 통합 운영 대시보드 마지막 갱신: 2분 전 [↺ 새로고침] │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌── 핵심 지표 카드 (4개) ─────────────────────────────────────────────┐ │ │ │ [SR 현황] [인시던트] [서버 가용률] [SLA 달성률] │ │ │ │ 24건 긴급 2건 91.7% 98.7% │ │ │ │ 진행중 8↗ 해결중 3 11/12대 실행 ▲ 0.3% │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌── SR 추이 꺾은선 차트 ─────────┐ ┌── 서버 상태 도넛 차트 ──────────┐ │ │ │ 7일간 SR 생성 vs 완료 │ │ │ │ │ │ │ │ 실행중 10 │ │ │ │ ╭──╮ │ │ ●────────── │ │ │ │ │ ╰──╮ ╭─── │ │ ○ 중지 1 │ │ │ │ │ ╰────╯ │ │ ● 오류 1 │ │ │ │ └────────────────────────── │ │ │ │ │ │ 월 화 수 목 금 토 일 │ │ 12대 서버 │ │ │ └────────────────────────────────┘ └──────────────────────────────┘ │ │ │ │ ┌── 리소스 모니터링 막대 차트 ──────────────────────────────────────────┐ │ │ │ CPU ██████████░░ 62% 메모리 ████████████░ 78% 디스크 ████░ 16% │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌── 최근 배포 이력 타임라인 ────────┐ ┌── AI/LLM 사용 현황 ───────────┐ │ │ │ 5분전 ✅ zioinfo-web v1.2.1 │ │ llama3:8b 응답시간 2.3s │ │ │ │ 1시간 ✅ guardia-itsm v2.0.4 │ │ 요청 124건/오늘 │ │ │ │ 3시간 ❌ zioinfo-web (실패) │ │ [████████░░] 메모리 4.7GB │ │ │ └────────────────────────────────┘ └──────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ``` --- ## 차트 라이브러리 선택: Recharts ```bash npm install recharts ``` **선택 이유:** NCloud 콘솔과 유사한 심플한 차트 스타일, React 친화적, 번들 크기 적당. --- ## 1. SR 추이 꺾은선 차트 (SRTrendChart) ```tsx // components/dashboard/SRTrendChart.tsx import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; interface SRTrendData { date: string; // 'MM/DD' created: number; completed: number; } export function SRTrendChart({ data }: { data: SRTrendData[] }) { return (

SR 생성/완료 추이 (7일)

); } ``` --- ## 2. 서버 상태 도넛 차트 (ServerStatusDonut) ```tsx // components/dashboard/ServerStatusDonut.tsx import { PieChart, Pie, Cell, Tooltip, Legend, ResponsiveContainer } from 'recharts'; const COLORS = { running: '#22c55e', stopped: '#94a3b8', error: '#ef4444', pending: '#f59e0b', }; export function ServerStatusDonut({ servers }: { servers: { status: string }[] }) { const counts = servers.reduce((acc, s) => { acc[s.status] = (acc[s.status] ?? 0) + 1; return acc; }, {} as Record); const data = Object.entries(counts).map(([status, value]) => ({ name: { running: '실행중', stopped: '중지', error: '오류', pending: '진행중' }[status] ?? status, value, status, })); return (

서버 상태 ({servers.length}대)

{data.map((entry) => ( ))} [`${value}대`, name]} />
); } ``` --- ## 3. 리소스 모니터링 바 차트 (ResourceGauge) ```tsx // components/dashboard/ResourceGauge.tsx // NCloud 콘솔의 리소스 게이지 UI 참조 interface GaugeProps { label: string; percent: number; detail?: string; } function Gauge({ label, percent, detail }: GaugeProps) { const color = percent > 90 ? '#ef4444' : percent > 70 ? '#f59e0b' : '#22c55e'; return (
{label} {percent}%
{detail &&
{detail}
}
); } export function ResourceGauge({ resources }: { resources: SystemResources }) { return (

서버 리소스

); } ``` --- ## 4. 배포 이력 타임라인 (DeployTimeline) ```tsx // components/dashboard/DeployTimeline.tsx import { useGuardiaApi } from '../../hooks/useGuardiaApi'; function timeAgo(ts: string) { const diff = Date.now() - new Date(ts).getTime(); if (diff < 60000) return '방금 전'; if (diff < 3600000) return `${Math.floor(diff/60000)}분 전`; return `${Math.floor(diff/3600000)}시간 전`; } export function DeployTimeline() { const { data: logs } = useGuardiaApi('/api/deploy/history'); const parsed = (logs ?? []).slice(-5).reverse().map(line => ({ time: line.match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}/)?.[0] ?? '', ok: line.includes('완료') || line.includes('success'), msg: line.replace(/^\d{4}.*?INFO\s+/, '').trim().slice(0, 60), })); return (

최근 배포 이력

    {parsed.map((item, i) => (
  • {item.ok ? '✅' : '❌'} {item.msg} {item.time}
  • ))} {!parsed.length && (
  • 배포 이력이 없습니다.
  • )}
); } ``` --- ## Dashboard.tsx 전체 조합 ```tsx // pages/Dashboard.tsx import { StatCard } from '../components/common/StatCard'; import { SRTrendChart } from '../components/dashboard/SRTrendChart'; import { ServerStatusDonut } from '../components/dashboard/ServerStatusDonut'; import { ResourceGauge } from '../components/dashboard/ResourceGauge'; import { DeployTimeline } from '../components/dashboard/DeployTimeline'; import { useGuardiaApi } from '../hooks/useGuardiaApi'; import { useManagerApi } from '../hooks/useManagerApi'; export function Dashboard() { const { data: stats } = useGuardiaApi('/api/dashboard'); const { data: resources } = useManagerApi('/api/system/resources'); const { data: servers } = useGuardiaApi('/api/cmdb/servers?limit=100'); return (
{/* 핵심 지표 카드 */}
s.status==='running').length / servers.length)*100).toFixed(1)}%` : '-'} icon="🖥️" color="#f0fdf4" />
{/* 차트 행 1: SR 추이 + 서버 상태 */}
{/* 리소스 게이지 */} {resources && } {/* 차트 행 2: 배포 이력 + LLM */}
{/* LLM 상태 카드 추가 가능 */}
); } ```