서버 운영자나 개발자라면 한 번쯤 경험해 보셨을 법한 당황스러운 상황이 있습니다. 바로 ‘CPU 사용률은 낮은데 서버의 Load Average(부하 평균)는 비정상적으로 높은’ 경우입니다. 많은 분들이 CPU 사용률이 높아야 서버가 바쁘다고 생각하시지만, 실제로는 그렇지 않은 경우가 많습니다. 이 글에서는 이러한 현상이 발생하는 근본적인 이유를 파헤치고, 문제 진단부터 해결까지 실용적인 가이드를 제공해 드리겠습니다.
CPU 사용률과 Load Average의 차이점 이해하기
이 현상을 이해하기 위해서는 먼저 CPU 사용률과 Load Average가 무엇을 의미하는지 정확히 알아야 합니다.
CPU 사용률 CPU Usage 이란
CPU 사용률은 특정 시간 동안 CPU가 작업을 처리하는 데 얼마나 바빴는지를 백분율로 나타낸 지표입니다. 예를 들어, CPU 사용률이 10%라면, CPU는 10%의 시간 동안 활발하게 명령어를 처리하고 있었고, 나머지 90%의 시간은 대기 상태였거나 다른 작업을 준비하고 있었다는 의미입니다. 이는 CPU 자체의 ‘활동량’을 직접적으로 보여줍니다.
Load Average 부하 평균 이란
Load Average는 특정 시점(보통 1분, 5분, 15분 평균)에 시스템에서 실행 중이거나 실행을 기다리는 프로세스의 평균 개수를 나타냅니다. 여기서 중요한 점은 ‘실행을 기다리는’ 프로세스에 단순히 CPU를 기다리는 프로세스뿐만 아니라, 디스크 I/O (입출력)나 네트워크 I/O와 같은 다른 시스템 자원을 기다리는 프로세스까지 모두 포함된다는 것입니다. 즉, Load Average는 CPU뿐만 아니라 디스크, 메모리, 네트워크 등 시스템 전반의 부하를 종합적으로 나타내는 지표라고 할 수 있습니다.
쉽게 비유하자면, CPU 사용률은 계산대에서 실제로 계산 중인 직원의 바쁜 정도를 나타내고, Load Average는 계산대에서 계산을 기다리는 사람, 카트를 찾거나 물건을 고르고 있는 사람, 심지어 화장실에 갔다가 다시 계산대로 돌아올 사람 등 상점 안에 있는 모든 손님의 수를 합한 것과 비슷합니다. 계산대 직원이 한가해도 상점 안에 손님이 바글바글하다면, 전체 상점은 매우 바쁜 상태일 것입니다.
CPU는 한가한데 서버 부하가 높은 이유 주요 원인 분석
이제 왜 CPU는 한가한데 Load Average는 높은지, 그 주요 원인들을 자세히 살펴보겠습니다. 대부분의 경우, CPU 외의 다른 자원 병목 현상 때문입니다.
디스크 I/O 병목 현상 Disk I/O Bottleneck
이것이 Load Average는 높고 CPU 사용률은 낮은 현상의 가장 흔한 원인입니다. 프로세스가 디스크에서 데이터를 읽거나 디스크에 데이터를 쓰는 작업을 수행할 때, 디스크의 처리 속도가 느리거나 디스크에 과도한 요청이 몰리면 해당 프로세스는 디스크 작업이 완료될 때까지 ‘대기’ 상태에 놓이게 됩니다. 이 대기 상태의 프로세스는 CPU를 사용하지 않지만, Load Average에는 포함되어 부하를 높입니다.
- 예시 대규모 데이터베이스 서버가 복잡한 쿼리를 처리하거나, 파일 서버가 수많은 파일을 동시에 읽고 쓸 때, 또는 로그 파일이 빠르게 쌓이는 시스템에서 디스크의 성능이 따라가지 못하면 이러한 현상이 발생합니다.
- 진단 팁
top명령어를 실행했을 때wa(iowait) 값이 높게 나타나거나,iostat명령어로 디스크의%util(활용률)이 100%에 가깝고avgqu-sz(평균 큐 길이)가 높게 나타난다면 디스크 I/O 병목을 의심할 수 있습니다.
메모리 부족 및 스와핑 발생 Insufficient Memory and Swapping
서버의 물리적 메모리(RAM)가 부족해지면 운영체제는 디스크의 스왑 공간(가상 메모리)을 사용하기 시작합니다. 메모리에 있어야 할 데이터가 디스크로 옮겨지고(swap out), 다시 필요할 때 디스크에서 메모리로 읽어와야(swap in) 합니다. 이 과정은 매우 느린 디스크 I/O 작업을 유발하여, 메모리 집약적인 작업이 디스크 I/O 집약적인 작업으로 변모하게 만듭니다.
- 예시 많은 양의 데이터를 캐싱해야 하는 웹 서버나, 대용량 데이터를 처리하는 분석 애플리케이션에서 메모리가 부족할 때 발생합니다.
- 진단 팁
vmstat명령어를 실행했을 때si(swap in) 또는so(swap out) 값이 지속적으로 높게 나타나면 스와핑이 활발하게 일어나고 있다는 증거입니다. 또한,free -h명령어로 사용 가능한 메모리가 거의 없는지 확인합니다.
네트워크 I/O 병목 현상 Network I/O Bottleneck
디스크 I/O만큼 흔하지는 않지만, 네트워크 트래픽이 과도하게 많거나 네트워크 인터페이스 카드의 성능이 충분하지 않을 때, 또는 네트워크 연결 자체가 불안정할 때 프로세스가 네트워크 응답을 기다리느라 대기 상태에 빠질 수 있습니다. 이 경우에도 CPU는 한가하지만 Load Average는 높아질 수 있습니다.
- 예시 대용량 파일 전송 서버, 스트리밍 서버, 또는 외부 API 호출이 빈번한 시스템에서 네트워크 대역폭이나 지연 문제가 발생할 때 나타날 수 있습니다.
- 진단 팁
sar -n DEV 1또는nload,iftop같은 도구를 사용하여 네트워크 트래픽 사용량과 오류율을 확인합니다.
락 경합 Lock Contention
여러 프로세스나 스레드가 동시에 공유 자원(예: 데이터베이스 테이블, 파일, 메모리 영역)에 접근하려고 할 때, 데이터의 일관성을 유지하기 위해 락(Lock)을 사용합니다. 만약 특정 자원에 대한 락이 너무 오랫동안 유지되거나, 많은 프로세스가 동일한 락을 얻기 위해 경쟁하면, 락을 기다리는 프로세스들은 CPU를 사용하지 않고 대기 상태에 빠지게 됩니다.
- 예시 데이터베이스에서 특정 레코드에 대한 업데이트가 빈번하게 발생하거나, 애플리케이션 코드 내에서 동기화 메커니즘이 비효율적으로 구현되었을 때 발생합니다.
- 진단 팁 데이터베이스의 경우, 슬로우 쿼리 로그나 락 관련 모니터링 도구를 확인합니다. 애플리케이션 레벨에서는 프로파일링 도구를 사용하여 병목 지점을 찾습니다.
과도한 커널 스레드 또는 좀비 프로세스 Excessive Kernel Threads or Zombie Processes
운영체제의 커널 스레드는 백그라운드에서 다양한 시스템 작업을 수행합니다. 때로는 이러한 커널 스레드가 비정상적으로 많아지거나 특정 작업에서 지연될 경우 Load Average를 높일 수 있습니다. 또한, 부모 프로세스가 자식 프로세스의 종료 상태를 수집하지 않아 발생하는 ‘좀비 프로세스’도 드물게 Load Average에 기여할 수 있습니다. 좀비 프로세스는 CPU를 사용하지 않지만, 프로세스 테이블에 남아 있어 시스템 자원을 소모합니다. (다만, 좀비 프로세스만으로 높은 Load Average를 유발하는 경우는 드뭅니다.)
- 진단 팁
ps aux명령어로 프로세스 목록을 확인하고Z상태의 좀비 프로세스나 비정상적으로 많은 커널 스레드([kworker/...]등)를 확인합니다.
문제 진단 및 해결 방법 실용적인 팁
Load Average는 높고 CPU는 한가한 문제를 해결하기 위한 구체적인 진단 및 해결 방법을 알려드립니다.
1. 모니터링 도구 활용하기
서버 상태를 정확하게 파악하는 것이 문제 해결의 첫걸음입니다.
top또는htopwa(iowait) 값 확인: CPU가 I/O 작업을 기다리느라 낭비된 시간의 비율입니다. 이 값이 높으면 디스크 I/O 병목을 강력히 의심해야 합니다.- 프로세스 상태 확인:
D(Uninterruptible sleep) 상태의 프로세스가 많은지 확인합니다. 이 상태는 주로 디스크 I/O를 기다리는 프로세스에서 나타납니다. - Load Average 확인: 1분, 5분, 15분 평균을 지속적으로 모니터링합니다.
vmstatr(runnable) 대기열: 실행 가능하거나 실행 중인 프로세스 수입니다. 이 값이 높으면 CPU 또는 I/O 병목이 있음을 시사합니다.b(blocked) 대기열: I/O를 기다리는 프로세스 수입니다. 이 값이 높으면 디스크 I/O 병목이 확실합니다.si,so(swap in/out): 스와핑이 활발한지 보여줍니다. 이 값이 높으면 메모리 부족을 의심합니다.wa(iowait):top과 동일하게 I/O 대기 시간을 나타냅니다.
iostat%util: 디스크 활용률입니다. 100%에 가깝다면 디스크가 최대치로 작동하고 있다는 의미입니다.avgqu-sz: 디스크 I/O 큐의 평균 길이입니다. 이 값이 높으면 I/O 요청이 디스크에서 처리되기를 기다리는 중임을 나타냅니다.r/s,w/s: 초당 읽기/쓰기 요청 수입니다.rkB/s,wkB/s: 초당 읽기/쓰기 데이터 양입니다.
sar- 시스템 활동 전반을 시간대별로 기록하고 분석할 수 있는 강력한 도구입니다. CPU, 메모리, 디스크, 네트워크 등 다양한 지표를 확인할 수 있습니다.
2. I/O 병목 현상 해결 방안
- 하드웨어 업그레이드
- 느린 HDD 대신 SSD 또는 NVMe 스토리지를 사용합니다.
- RAID 구성을 최적화하여 디스크 성능을 향상시킵니다 (예: RAID 10).
- I/O 분산
- 데이터베이스 파일, 로그 파일 등을 물리적으로 다른 디스크에 분리하여 I/O 부하를 분산합니다.
- 애플리케이션 최적화
- 불필요한 디스크 I/O를 줄입니다 (예: 캐싱 활용, 배치 처리, 비동기 I/O).
- 데이터베이스 인덱스를 최적화하고 쿼리를 튜닝하여 디스크 읽기 횟수를 줄입니다.
3. 메모리 부족 및 스와핑 해결 방안
- RAM 증설
- 가장 직접적이고 효과적인 방법입니다. 서버에 물리적 RAM을 추가합니다.
- 애플리케이션 메모리 최적화
- 애플리케이션의 메모리 사용량을 분석하고, 메모리 누수(memory leak)가 있는지 확인하여 수정합니다.
- 캐시 크기를 적절히 조절하여 메모리 사용량을 최적화합니다.
- 스와프 공간 관리
- 스와프를 완전히 없애는 것은 권장되지 않지만, 스와프 사용량을 줄이거나 스와프 디스크의 성능을 향상시키는 것을 고려할 수 있습니다.
4. 락 경합 해결 방안
- 데이터베이스 튜닝
- 트랜잭션 격리 수준을 조정하거나, 락이 걸리는 범위를 최소화합니다.
- 쿼리 최적화를 통해 락이 걸리는 시간을 줄입니다.
- 애플리케이션 설계 변경
- 공유 자원에 대한 동시 접근을 줄이도록 애플리케이션 로직을 변경합니다.
- 락 없는(lock-free) 자료구조나 비관적/낙관적 락 전략을 고려합니다.
5. 네트워크 병목 현상 해결 방안
- 네트워크 대역폭 증설
- 네트워크 인터페이스 카드(NIC)를 업그레이드하거나, 서버에 할당된 네트워크 대역폭을 늘립니다.
- 네트워크 설정 최적화
- 네트워크 드라이버 업데이트, TCP/IP 파라미터 튜닝 등을 고려합니다.
흔한 오해와 사실 관계
Load Average와 CPU 사용률에 대해 많은 분들이 잘못 알고 있는 몇 가지 오해가 있습니다.
오해 1 Load Average는 CPU 사용률과 직접적으로 비례한다
사실 Load Average는 CPU 대기열뿐만 아니라 디스크 I/O, 네트워크 I/O 등 다른 자원을 기다리는 프로세스까지 모두 포함합니다. 따라서 CPU 사용률이 낮아도 Load Average는 높을 수 있으며, 이는 CPU가 아닌 다른 자원의 병목 현상을 의미할 가능성이 큽니다.
오해 2 Load Average가 높으면 무조건 서버에 문제가 있다
사실 Load Average가 높다고 해서 무조건 문제가 있는 것은 아닙니다. 서버의 CPU 코어 수와 작업의 특성을 고려해야 합니다. 예를 들어, 8코어 서버에서 Load Average가 4라면, 이는 각 코어에 평균 0.5개의 작업이 할당되어 사실상 여유로운 상태입니다. 하지만 1코어 서버에서 Load Average가 4라면, 이는 3개의 작업이 대기 중이라는 의미이므로 심각한 문제가 있을 수 있습니다. 중요한 것은 Load Average가 CPU 코어 수보다 지속적으로 높을 때, 그리고 평소보다 비정상적으로 높을 때 문제를 의심해야 한다는 것입니다.
오해 3 낮은 CPU 사용률은 항상 좋은 것이다
사실 CPU 사용률이 낮다는 것은 CPU가 바쁘지 않다는 뜻이지만, 이것이 항상 시스템이 효율적으로 작동한다는 의미는 아닙니다. 만약 CPU 사용률은 낮은데 Load Average가 높다면, CPU는 한가하지만 다른 중요한 자원이 병목 현상을 겪고 있어 시스템 전체의 성능이 저하되고 있다는 신호입니다.
자주 묻는 질문과 답변
Q Load Average가 몇부터 높다고 볼 수 있나요
A 일반적으로 Load Average는 CPU 코어 수와 비교하여 판단합니다. 1코어 시스템에서는 Load Average가 1.0을 넘으면 과부하 상태라고 볼 수 있습니다. N코어 시스템에서는 Load Average가 N을 넘으면 평균적으로 각 코어에 1개 이상의 프로세스가 할당되어 대기열이 발생하고 있다는 의미이므로, N을 기준으로 판단하는 것이 좋습니다. 하지만 이는 일반적인 기준이며, 서버의 역할과 중요도에 따라 허용 가능한 Load Average는 달라질 수 있습니다.
Q top 명령어에서 iowait 값이 높은데 CPU 사용률은 낮아요 어떻게 해야 하나요
A 이 경우 디스크 I/O 병목 현상이 매우 유력합니다. iostat 명령어를 사용하여 어떤 디스크에서 병목이 발생하는지 확인하고, 해당 디스크의 성능을 개선하거나 (SSD/NVMe로 교체), 애플리케이션의 디스크 I/O 패턴을 최적화하는 방안을 고려해야 합니다. 데이터베이스 서버라면 쿼리 튜닝이나 인덱스 최적화가 필요할 수 있습니다.
Q vmstat에서 si so 값이 계속 올라가는데 Load Average도 높아요
A 이는 메모리 부족으로 인해 스와핑이 활발하게 일어나고 있다는 명확한 신호입니다. 스와핑은 디스크 I/O를 유발하므로 Load Average를 높이는 주범이 됩니다. 서버의 RAM을 증설하거나, 애플리케이션의 메모리 사용량을 줄이는 최적화 작업을 수행해야 합니다. 메모리 누수가 있는지 확인하는 것도 중요합니다.
전문가의 조언 및 추가 팁
서버의 역할 이해하기
모든 서버에 동일한 Load Average 기준을 적용할 수는 없습니다. 데이터베이스 서버는 디스크 I/O가 많으므로 웹 서버보다 iowait가 높거나 Load Average가 다소 높을 수 있습니다. 파일 서버 역시 디스크 I/O가 많습니다. 서버의 주된 역할과 워크로드를 이해하고, 이에 맞는 정상 범위를 파악하는 것이 중요합니다.
사전 예방 및 주기적인 모니터링
문제가 발생한 후에 해결하는 것보다, 문제가 발생하기 전에 징후를 파악하고 예방하는 것이 훨씬 중요합니다. Load Average, CPU 사용률, 메모리 사용량, 디스크 I/O, 네트워크 트래픽 등 핵심 지표들을 지속적으로 모니터링하고, 임계치를 설정하여 알림을 받는 시스템을 구축하는 것이 좋습니다. Grafana, Prometheus, Zabbix 등 다양한 모니터링 솔루션을 활용할 수 있습니다.
단계별 문제 해결 접근
서버 문제를 해결할 때는 한 번에 여러 가지 변경을 시도하기보다는, 가장 가능성이 높은 원인부터 하나씩 진단하고 변경 사항을 적용한 후 그 효과를 확인하는 ‘단계별 접근’이 중요합니다. 이렇게 해야 어떤 변경이 문제 해결에 기여했는지 명확히 파악할 수 있습니다.
애플리케이션 레벨 최적화
하드웨어 업그레이드나 OS 레벨 튜닝도 중요하지만, 근본적인 해결책은 애플리케이션의 비효율적인 로직을 개선하는 데 있을 때가 많습니다. 불필요한 I/O, 비효율적인 쿼리, 과도한 락 사용, 메모리 누수 등 애플리케이션 코드 레벨의 최적화를 병행해야 합니다.
CPU 사용률은 낮은데 Load Average가 높은 현상은 서버가 ‘열심히 일하는 척’ 하는 것이 아니라, 실제로는 특정 자원에서 병목 현상을 겪고 있어 전체적인 시스템 성능이 저하되고 있다는 중요한 신호입니다. 이 가이드를 통해 여러분의 서버 문제를 성공적으로 진단하고 해결하는 데 도움이 되기를 바랍니다.