You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
본 프로젝트는 Proxmox 가상화 환경에서 운용되는 여러 가상 머신의 시스템 리소스를 실시간으로 수집 및 시각화하고, 임계치 초과 시 경보를 제공하는 웹 기반 모니터링 대시보드 SysPulse를 설계 및 구현하는 것을 목적으로 한다.
React, Node.js, Docker, Prometheus 등 실무에서 널리 사용되는 기술 스택을 직접 설계·구현함으로써 풀스택 웹 애플리케이션 개발 역량과 서버 인프라 운용 능력을 함양하는 것을 목표로 한다.
1.2 포함 내용
Proxmox 기반 Ubuntu VM 3대(모니터링 서버 1대 + 대상 VM 3대) 구성
Node Exporter를 이용한 VM 리소스 메트릭 수집
Prometheus를 이용한 15초 주기 자동 수집 및 PostgreSQL 저장
React 기반 실시간 모니터링 대시보드 구현
PostgreSQL을 이용한 메트릭 이력 저장 및 과거 데이터 조회
시간 범위 필터 기능
메트릭 종류 필터(CPU/메모리/디스크/네트워크) 기능
VM 온/오프라인 상태 실시간 감지
Docker Compose를 이용한 컨테이너 기반 배포
GitHub를 이용한 소스 코드 관리 및 버전 관리
1.3 불포함 내용
HTTPS/SSL 보안 설정
외부 인터넷 접속 환경 (내부 네트워크 전용)
2. 분석
2.1 기능 목록 (유스케이스 다이어그램)
2.2 유스케이스 명세서
VM 목록 조회
항목
내용
이름
VM 목록 조회
액터
사용자
시작조건
등록된 VM이 1개 이상 존재
기본흐름
1. 사용자가 대시보드 접속 → 2. React가 5초마다 /api/vms 호출 → 3. 백엔드가 DB에서 VM 목록 조회 → 4. 각 VM의 온라인 상태를 Prometheus up 메트릭으로 확인 → 5. VM 목록과 상태를 사이드바에 표시
예외흐름
등록된 VM이 없으면 "등록된 VM이 없습니다" 표시
종료조건
사이드바에 VM 목록과 Online/Offline 상태가 표시됨
VM 등록
항목
내용
이름
VM 등록
액터
사용자
시작조건
대상 VM에 Node Exporter가 실행 중
기본흐름
1. POST /api/vms 호출 → 2. 백엔드가 alias, local_ip를 DB의 vm_targets 테이블에 저장 → 3. 이후 VM 목록 조회 시 등록된 VM 포함하여 반환
예외흐름
IP 형식이 잘못된 경우 등록 실패
종료조건
신규 VM이 대시보드 사이드바에 표시됨
실시간 메트릭 조회
항목
내용
이름
실시간 메트릭 조회
액터
사용자
시작조건
VM이 등록되어 있고 Node Exporter가 실행 중
기본흐름
1. 사용자가 VM 목록에서 VM 선택 → 2. React가 5초마다 /api/metrics/current 호출 → 3. 백엔드가 Prometheus에 PromQL 쿼리 → 4. 결과를 가공하여 JSON 응답 → 5. 화면에 현재값 카드 업데이트
예외흐름
VM이 오프라인인 경우 메트릭 값 0으로 표시
종료조건
CPU/메모리/디스크/네트워크 현재값이 화면에 표시됨
차트 시각화
항목
내용
이름
차트 시각화
액터
사용자
시작조건
VM이 선택되어 있고 메트릭 이력 데이터가 존재
기본흐름
1. 사용자가 VM 선택 → 2. React가 DB 이력 데이터 조회 → 3. CPU/메모리는 AreaChart, 디스크는 PieChart, 네트워크는 AreaChart로 렌더링 → 4. 5초마다 자동 갱신
예외흐름
데이터 없으면 빈 차트 표시
종료조건
4종 차트가 화면에 표시되고 5초마다 자동 갱신됨
메트릭 이력 조회
항목
내용
이름
메트릭 이력 조회
액터
사용자
시작조건
metric_history 테이블에 데이터가 존재
기본흐름
1. 사용자가 시간 범위 선택 → 2. React가 /api/metrics/history?vm_id=&range= 호출 → 3. 백엔드가 PostgreSQL에서 해당 범위 데이터 조회 → 4. JSON 응답 → 5. 차트에 이력 데이터 표시
예외흐름
해당 시간대 데이터 없으면 빈 차트 표시
종료조건
선택한 시간 범위의 메트릭 이력이 차트에 표시됨
시간 범위 필터
항목
내용
이름
시간 범위 필터
액터
사용자
시작조건
VM이 선택되어 있음
기본흐름
1. 사용자가 1시간/3시간/6시간/12시간/24시간 버튼 클릭 또는 직접 입력 → 2. 날짜·시간 선택 → 3. "조회" 버튼 클릭 → 4. 해당 범위 데이터 조회 및 차트 갱신
예외흐름
시작 시간이 끝 시간보다 늦으면 경고 알림 표시
종료조건
지정한 시간 범위의 데이터가 차트에 표시됨
메트릭 종류 필터
항목
내용
이름
메트릭 종류 필터
액터
사용자
시작조건
VM이 선택되어 있음
기본흐름
1. 사용자가 헤더의 CPU/메모리/디스크/네트워크 버튼 클릭 → 2. 해당 메트릭 차트 토글(표시/숨김) → 3. 요약 카드도 동일하게 흐림 처리
예외흐름
모든 필터를 끄면 차트 영역이 비어있는 상태로 표시
종료조건
선택한 메트릭 종류의 차트만 화면에 표시됨
VM 상태 감지
항목
내용
이름
VM 상태 감지
액터
사용자
시작조건
VM이 등록되어 있음
기본흐름
1. React가 5초마다 /api/vms 호출 → 2. 백엔드가 Prometheus의 up{instance="IP:9100"} 쿼리 → 3. 값이 1이면 Online(초록), 0이면 Offline(빨강)으로 표시
예외흐름
Prometheus 수집 지연 시 이전 상태 유지
종료조건
사이드바에 VM별 Online/Offline 상태가 실시간 표시됨
증감 표시
항목
내용
이름
증감 표시
액터
사용자
시작조건
실시간 메트릭이 2회 이상 수신됨
기본흐름
1. React가 5초마다 메트릭 수신 → 2. 이전 값과 현재 값 비교 → 3. 증가 시 빨간색 ↑, 감소 시 초록색 ↓ 표시 → 4. 변화 없으면 표시 안 함
예외흐름
첫 번째 수신 시에는 이전 값이 없어 증감 표시 안 함
종료조건
요약 카드에 이전 값 대비 증감 수치가 표시됨
CPU 임계치 표시
항목
내용
이름
CPU 임계치 표시
액터
사용자
시작조건
CPU 차트가 화면에 표시되어 있음
기본흐름
1. CPU 사용률이 80% 이상인 구간 감지 → 2. 해당 구간을 빨간 영역(Area)으로 표시 → 3. 80% 기준선을 빨간 점선(ReferenceLine)으로 표시
예외흐름
CPU가 80% 미만이면 기준선만 표시되고 빨간 영역은 없음
종료조건
CPU 80% 초과 구간이 차트에 빨간 영역으로 시각화됨
메트릭 수집
항목
내용
이름
메트릭 수집
액터
시스템(자동)
시작조건
백엔드 서버가 실행 중이고 VM이 1개 이상 등록되어 있음
기본흐름
1. 백엔드 시작 시 수집 엔진(collector.js) 자동 실행 → 2. 15초마다 DB에서 활성 VM 목록 조회 → 3. 각 VM에 대해 Prometheus PromQL 쿼리(CPU/메모리/디스크/네트워크) → 4. 수집된 값을 metric_history 테이블에 저장
예외흐름
Prometheus 쿼리 실패 시 해당 메트릭 값 0으로 저장
종료조건
15초마다 metric_history 테이블에 새 데이터가 적재됨
DB 저장
항목
내용
이름
DB 저장
액터
시스템(자동)
시작조건
PostgreSQL이 실행 중이고 metric_history 테이블이 존재
기본흐름
1. collector.js가 메트릭 수집 완료 → 2. INSERT INTO metric_history 쿼리 실행 → 3. vm_id, cpu, memory, disk, network, collected_at 저장
예외흐름
DB 연결 실패 시 해당 수집 주기 저장 건너뜀
종료조건
수집된 메트릭이 PostgreSQL에 영구 저장됨
VM 등록
항목
내용
이름
VM 등록
액터
시스템(자동)
시작조건
.env 파일에 VM_B_IP, VM_C_IP, VM_D_IP가 설정되어 있음
기본흐름
1. Docker Compose 실행 시 vm-register 컨테이너 자동 시작 → 2. 백엔드 헬스체크 통과 대기 → 3. .env에서 VM IP 읽기 → 4. 이미 등록된 IP인지 확인 → 5. 미등록 VM만 POST /api/vms 호출하여 등록
예외흐름
이미 등록된 IP는 건너뜀 / IP가 없으면 등록 안 함
종료조건
.env에 설정된 VM이 자동으로 대시보드에 등록됨
3. 설계
3.1 시스템 구조
Proxmox 서버
└── VM-A (모니터링 서버) 192.168.1.101
└── Docker Compose
├── Nginx :80 React 빌드 파일 서빙 + API 리버스 프록시
├── Backend :3000 Express REST API 서버
├── Prometheus :9090 메트릭 수집 (15초 간격)
└── PostgreSQL :5432 메트릭 이력 및 VM 정보 저장
↓ Prometheus Pull (15초)
└── VM-B (테스트 대상 1) 192.168.1.107
└── Node Exporter :9100
└── VM-C (테스트 대상 2) 192.168.1.105
└── Node Exporter :9100
└── VM-D (테스트 대상 3) 192.168.1.106
└── Node Exporter :9100
함수 collectMetrics():
vms = DB에서 활성화된 VM 목록 조회
각 vm에 대해:
instance = vm.local_ip + ":9100"
cpu = Prometheus.query("100 - avg(idle_rate) * 100")
memory = Prometheus.query("(1 - avail/total) * 100")
disk = Prometheus.query("avg(1 - avail/size) * 100")
network = Prometheus.query("sum(rate(recv_bytes[1m]))")
DB.insert(metric_history, vm.id, cpu, memory, disk, network)
끝
// 15초마다 반복 실행
setInterval(collectMetrics, 15000)
3.6 VM 온/오프라인 감지 알고리즘 (슈더 코드)
함수 checkVmStatus(ip):
result = Prometheus.query("up{instance=ip:9100}")
만약 result가 비어있으면:
return false (Offline)
만약 result[0].value == "1"이면:
return true (Online)
그 외:
return false (Offline)
3.7 VM 등록 API 알고리즘 (슈더 코드)
함수 POST /api/vms(요청):
alias = 요청.body.alias
local_ip = 요청.body.local_ip
만약 alias가 비어있거나 local_ip가 비어있으면:
return 오류 응답 (400 Bad Request)
DB.insert(vm_targets, alias, local_ip, enabled=true)
return 성공 응답 ("VM 등록 완료")
3.8 VM 목록 조회 API 알고리즘 (슈더 코드)
함수 GET /api/vms():
vms = DB.query("SELECT * FROM vm_targets WHERE enabled = true")
각 vm에 대해:
status = checkVmStatus(vm.local_ip)
vm.online = status
return vms (온라인 상태 포함)
3.9 실시간 메트릭 조회 API 알고리즘 (슈더 코드)
함수 GET /api/metrics/current(vm_ip):
instance = vm_ip + ":9100"
cpu = Prometheus.query("100 - avg(idle_rate) * 100")
memory = Prometheus.query("(1 - avail / total) * 100")
disk = Prometheus.query("avg(1 - avail / size) * 100")
network = Prometheus.query("sum(rate(recv_bytes[1m]))")
각 값에 대해:
만약 값이 없으면: 0으로 설정
그 외: 소수점 2자리로 반올림
return { cpu, memory, disk, network }
3.10 메트릭 이력 조회 API 알고리즘 (슈더 코드)
함수 GET /api/metrics/history(vm_id, range, start, end):
만약 start와 end가 존재하면:
조건 = "collected_at >= start AND collected_at <= end"
그 외:
interval = range에 따라 변환
"1h" → "1 hour"
"3h" → "3 hours"
"6h" → "6 hours"
"12h" → "12 hours"
"24h" → "24 hours"
조건 = "collected_at > now() - interval"
결과 = DB.query(
"SELECT cpu, memory, disk, network,
to_char(collected_at AT TIME ZONE 'Asia/Seoul', 'HH24:MI:SS') as time
FROM metric_history
WHERE vm_id = vm_id AND 조건
ORDER BY collected_at ASC"
)
return 결과
3.11 증감 표시 알고리즘 (슈더 코드)
함수 계산증감(현재값, 이전값):
만약 이전값이 없으면:
return null (표시 안 함)
차이 = 현재값 - 이전값
만약 |차이| < 0.01이면:
return null (변화 없음)
만약 차이 > 0이면:
return { 방향: "↑", 값: 차이, 색상: 빨강 }
그 외:
return { 방향: "↓", 값: |차이|, 색상: 초록 }
// 5초마다 메트릭 수신 시 호출
useEffect():
만약 현재메트릭이 존재하면:
증감 = 계산증감(현재메트릭, 이전메트릭)
이전메트릭 = 현재메트릭
3.12 CPU 임계치 감지 알고리즘 (슈더 코드)
상수 THRESHOLD = 80
함수 렌더CpuChart(데이터):
각 데이터포인트에 대해:
만약 value >= THRESHOLD이면:
빨간영역에 포함
그 외:
파란영역에 포함
차트에 그리기:
파란 AreaChart (전체 데이터)
빨간 AreaChart (THRESHOLD 초과 데이터만)
빨간 점선 ReferenceLine (y = THRESHOLD)
3.13 VM 자동 등록 알고리즘 (슈더 코드)
함수 register-vms():
.env 파일에서 VM_B_IP, VM_C_IP, VM_D_IP 읽기
백엔드 헬스체크 통과할 때까지 대기:
GET /health 반복 호출 (2초 간격)
각 (alias, ip) 쌍에 대해:
만약 ip가 비어있으면:
건너뜀
기존VM목록 = GET /api/vms
만약 ip가 기존VM목록에 존재하면:
"이미 등록됨" 출력 후 건너뜀
그 외:
POST /api/vms { alias, local_ip: ip }
"등록 완료" 출력
3.14 프론트엔드 컴포넌트 구조
App
└── Dashboard (메인 페이지)
├── VmList (VM 목록 사이드바)
├── MetricFilter (메트릭 종류 필터)
├── TimeRangePicker (시간 범위 선택)
│ └── DateTimePicker (날짜/시간 직접 입력)
├── 요약 카드 (CPU/메모리/디스크/네트워크 현재값)
├── CpuChart (CPU 사용률 Area 차트)
├── MemoryChart (메모리 사용량 Area 차트)
├── DiskChart (디스크 사용량 Pie 차트)
└── NetworkChart (네트워크 트래픽 Area 차트)
3.15 클래스 다이어그램
3.16 순서도
4. 구현
4.1 구현 환경
하드웨어 환경
항목
내용
서버
Proxmox VE 기반 물리 서버
가상화
Proxmox VE
VM-A (모니터링 서버)
vCPU 2코어, RAM 2GB, 디스크 20GB
VM-B/C/D (대상 VM)
vCPU 1코어, RAM 1GB, 디스크 10GB
네트워크
내부 네트워크 (192.168.1.0/24)
소프트웨어 환경
항목
버전
역할
Ubuntu
22.04 LTS
VM 운영체제
Docker
최신
컨테이너 런타임
Docker Compose
v1
멀티 컨테이너 관리
Node.js
20.x
백엔드 런타임
React
18.x
프론트엔드 프레임워크
Vite
8.x
프론트엔드 빌드 도구
4.2 개발 언어 및 프레임워크
프론트엔드
React 18을 이용해 사용자가 보는 대시보드 화면 전체를 개발했다. Recharts 라이브러리를 이용해 CPU, 메모리, 디스크, 네트워크 차트를 구현했고, Tailwind CSS를 이용해 다크 모던 스타일로 UI를 디자인했다. Axios를 이용해 1주차에 개발한 백엔드 REST API와 연결하여 VM 목록 및 메트릭 데이터를 화면에 표시한다.
백엔드
Node.js + Express를 이용해 REST API 서버를 직접 개발했다. React의 요청을 받아 Prometheus에 PromQL 쿼리를 보내고 결과를 가공하여 응답한다. node-postgres(pg)를 이용해 PostgreSQL과 연결했다.
모니터링 수집
Prometheus를 이용해 VM-B, VM-C, VM-D의 메트릭을 15초마다 자동 수집한다. 각 대상 VM에는 Node Exporter를 설치하여 CPU, 메모리, 디스크, 네트워크 데이터를 9100 포트로 노출시켰다.
데이터베이스
PostgreSQL 15를 이용해 VM 목록, 메트릭 이력, 알림 규칙, 알림 이력을 저장한다. 백엔드가 15초마다 Prometheus에서 수집한 데이터를 DB에 저장하여 과거 데이터 조회가 가능하다.
본 프로젝트에서는 Proxmox 가상화 환경에서 운용되는 VM들의 시스템 리소스를 실시간으로 모니터링하는 웹 기반 대시보드 SysPulse를 설계·구현하였다.
React 18 기반의 프론트엔드와 Node.js + Express 기반의 백엔드를 직접 개발하고, Prometheus와 Node Exporter를 활용하여 15초 주기로 메트릭을 자동 수집하는 시스템을 구축하였다. PostgreSQL을 이용해 수집된 메트릭을 영구 저장함으로써 과거 데이터 조회 기능을 구현하였다.
6.2 구현된 주요 기능
VM 3대(VM-B, VM-C, VM-D)의 CPU/메모리/디스크/네트워크 실시간 모니터링