3 분 소요

서버 성능 문제는 증상이 나타나기 전에 선제적으로 모니터링해야 합니다. Windows Server는 성능 카운터, 이벤트 로그, WMI 등 다양한 모니터링 인터페이스를 제공합니다. 이 글에서는 실무에서 바로 활용 가능한 모니터링 방법을 소개합니다.

서버 코드 이미지

Windows Server 성능 지표를 실시간으로 모니터링하는 화면

성능 카운터 기본 이해

핵심 성능 카운터

카운터 정상 범위 경고 기준
\Processor(_Total)\% Processor Time < 70% > 85% 지속
\Memory\Available MBytes > 전체의 20% < 10%
\PhysicalDisk(_Total)\% Disk Time < 50% > 80%
\Network Interface(*)\Bytes Total/sec < 80% 대역폭 > 90%
\System\Processor Queue Length < CPU 수 × 2 > CPU 수 × 4

PowerShell로 실시간 모니터링

# CPU 사용률 실시간 확인 (5초 간격)
Get-Counter -Counter "\Processor(_Total)\% Processor Time" `
    -SampleInterval 5 -MaxSamples 12 |
    ForEach-Object {
        $cpu = [math]::Round($_.CounterSamples[0].CookedValue, 1)
        Write-Host "$(Get-Date -Format 'HH:mm:ss') CPU: $cpu%"
    }

# 메모리 사용량 확인
$os = Get-WmiObject Win32_OperatingSystem
$totalMB = [math]::Round($os.TotalVisibleMemorySize / 1KB)
$freeMB  = [math]::Round($os.FreePhysicalMemory / 1KB)
$usedMB  = $totalMB - $freeMB
$usedPct = [math]::Round($usedMB / $totalMB * 100, 1)

Write-Host "메모리: ${usedMB}MB 사용 / ${totalMB}MB 전체 ($usedPct%)"

종합 성능 대시보드

function Get-ServerPerformance {
    param([string]$ComputerName = $env:COMPUTERNAME)

    $counters = @(
        "\Processor(_Total)\% Processor Time",
        "\Memory\Available MBytes",
        "\PhysicalDisk(_Total)\Disk Reads/sec",
        "\PhysicalDisk(_Total)\Disk Writes/sec",
        "\Network Interface(*)\Bytes Total/sec",
        "\System\Processor Queue Length"
    )

    $samples = Get-Counter -ComputerName $ComputerName `
        -Counter $counters -SampleInterval 3 -MaxSamples 3

    $avg = $samples.CounterSamples | Group-Object Path |
        ForEach-Object {
            [PSCustomObject]@{
                Counter = $_.Name -replace "^\\\\[^\\]+", ""
                Average = [math]::Round(
                    ($_.Group | Measure-Object CookedValue -Average).Average, 2
                )
            }
        }

    $avg | Format-Table -AutoSize
}

Get-ServerPerformance

성능 데이터 수집기(PerfMon)

# 성능 데이터 수집기 세트 생성 및 시작
$query = New-Object System.Diagnostics.Eventing.Reader.EventLogQuery

# logman으로 성능 로그 생성
logman create counter "ServerMonitor" `
    --v `
    -c "\Processor(_Total)\% Processor Time" `
       "\Memory\Available MBytes" `
       "\PhysicalDisk(_Total)\% Disk Time" `
    -si 30 `
    -f csv `
    -o "C:\PerfLogs\ServerMonitor"

# 수집 시작/중지
logman start ServerMonitor
logman stop ServerMonitor

# 현재 수집기 목록
logman query

프로세스별 리소스 사용량

# CPU 사용률 상위 프로세스
Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 |
    Format-Table Name, ID,
    @{N='CPU(s)'; E={[math]::Round($_.CPU, 1)}},
    @{N='MemMB'; E={[math]::Round($_.WorkingSet/1MB, 1)}},
    Handles -AutoSize

# 메모리 사용 상위 프로세스
Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 10 |
    Format-Table Name, ID,
    @{N='MemMB'; E={[math]::Round($_.WorkingSet/1MB, 1)}},
    @{N='VirtualMB'; E={[math]::Round($_.VirtualMemorySize64/1MB, 1)}} -AutoSize

# 특정 프로세스 상세 모니터링
while ($true) {
    $proc = Get-Process -Name "w3wp" -ErrorAction SilentlyContinue
    if ($proc) {
        $proc | Format-Table Name, ID,
            @{N='CPU'; E={[math]::Round($_.CPU, 1)}},
            @{N='MemMB'; E={[math]::Round($_.WorkingSet/1MB, 1)}}
    }
    Start-Sleep -Seconds 5
}

데이터센터 이미지

대시보드에서 Windows Server 성능을 시각화하는 모습

디스크 I/O 분석

# 디스크 사용량 확인
Get-PSDrive -PSProvider FileSystem |
    Select-Object Name,
    @{N='UsedGB'; E={[math]::Round($_.Used/1GB, 1)}},
    @{N='FreeGB'; E={[math]::Round($_.Free/1GB, 1)}},
    @{N='TotalGB'; E={[math]::Round(($_.Used+$_.Free)/1GB, 1)}},
    @{N='UsedPct'; E={[math]::Round($_.Used/($_.Used+$_.Free)*100, 1)}} |
    Format-Table -AutoSize

# 디스크 I/O 성능
Get-Counter -Counter @(
    "\PhysicalDisk(_Total)\Disk Reads/sec",
    "\PhysicalDisk(_Total)\Disk Writes/sec",
    "\PhysicalDisk(_Total)\Avg. Disk Queue Length"
) -SampleInterval 5 -MaxSamples 6 |
    ForEach-Object {
        $_.CounterSamples | Format-Table Path,
        @{N='Value'; E={[math]::Round($_.CookedValue, 2)}} -AutoSize
    }

네트워크 성능 모니터링

# 네트워크 어댑터 현재 상태
Get-NetAdapterStatistics |
    Select-Object Name,
    @{N='ReceivedMB'; E={[math]::Round($_.ReceivedBytes/1MB, 2)}},
    @{N='SentMB'; E={[math]::Round($_.SentBytes/1MB, 2)}},
    ReceivedUnicastPackets, SentUnicastPackets |
    Format-Table -AutoSize

# 네트워크 연결 상태
Get-NetTCPConnection |
    Group-Object State |
    Sort-Object Count -Descending |
    Format-Table Name, Count -AutoSize

# 대역폭 사용률 실시간 (10초 평균)
$adapter = "Ethernet"
Get-Counter "\Network Interface($adapter)\Bytes Total/sec" `
    -SampleInterval 1 -MaxSamples 10 |
    ForEach-Object {
        $mbps = [math]::Round($_.CounterSamples[0].CookedValue * 8 / 1MB, 2)
        Write-Host "$(Get-Date -Format 'HH:mm:ss') $adapter: $mbps Mbps"
    }

성능 알림 스크립트

# 임계값 초과 시 이메일 알림
function Monitor-ServerResources {
    param(
        [int]$CpuThreshold = 85,
        [int]$MemThresholdMB = 1024,
        [int]$DiskThreshold = 90
    )

    # CPU 확인
    $cpu = (Get-Counter "\Processor(_Total)\% Processor Time").CounterSamples[0].CookedValue
    if ($cpu -gt $CpuThreshold) {
        Write-Warning "CPU 경고: $([math]::Round($cpu, 1))% (임계값: $CpuThreshold%)"
    }

    # 메모리 확인
    $freeMem = (Get-WmiObject Win32_OperatingSystem).FreePhysicalMemory / 1KB
    if ($freeMem -lt $MemThresholdMB) {
        Write-Warning "메모리 경고: 여유 $([math]::Round($freeMem, 0))MB (임계값: $MemThresholdMB MB)"
    }

    # 디스크 확인
    Get-PSDrive -PSProvider FileSystem | ForEach-Object {
        $used = $_.Used / ($_.Used + $_.Free) * 100
        if ($used -gt $DiskThreshold) {
            Write-Warning "디스크 경고: $($_.Name): 드라이브 사용률 $([math]::Round($used,1))%"
        }
    }
}

# 5분마다 모니터링
while ($true) {
    Monitor-ServerResources
    Start-Sleep -Seconds 300
}

성능 모니터링의 핵심은 정상 기준선(Baseline)을 파악하는 것입니다. 서버를 처음 구성할 때부터 성능 데이터를 수집하여 정상 패턴을 파악해두면, 이후 문제 발생 시 빠르게 이상 징후를 발견할 수 있습니다. 수집된 데이터는 Grafana, Azure Monitor 같은 도구로 시각화하면 더욱 효과적입니다.

댓글남기기