이건 동료가 저번에 저한테 물어봐서 작성하는 글인데요. Load Average 이게 참 애매하죠. Average 이거 평균 아닙니까. 순간적으로 치고 올라가서 문제가 되더라도, 이전이나 이후가 낮으면 평균적으로 낮게 나오니까요. 그거 때문에 한 번 글 적어봅니다.
숫자에 가려진 시스템의 비명
리눅스 서버를 운영하며 가장 먼저 확인하는 메트릭 중 하나가 바로 uptime이나 top 명령어 상단에 위치한 Load Average입니다. 대개 우리는 이 수치가 CPU 코어 수보다 낮으면 안정적이고, 높으면 과부하라고 판단합니다. 하지만 현장은 그리 단순하지 않습니다.
때로는 CPU 점유율이 10% 미만인데도 Load Average가 50을 넘어가며 시스템이 버벅대기도 하고, 반대로 점유율이 90%에 달하는데도 Load Average는 평온한 수치를 유지하기도 합니다. 이러한 괴리는 Load Average가 단순히 'CPU 사용량'을 의미하는 지표가 아니기 때문에 발생합니다. 오늘은 리눅스 커널의 심장부에서 벌어지는 프로세스 스케줄링과 Load Average 산출 로직을 심도 있게 파헤쳐 보겠습니다.

Load Average의 본질: 실행 대기열과 D 상태의 결합
전통적인 유닉스 시스템(Solaris, BSD 등)에서 Load Average는 단순히 실행 중이거나 실행 대기 중인 프로세스(Run Queue)의 수만을 의미했습니다. 하지만 리눅스는 다릅니다. 리눅스 커널 개발자들은 시스템의 전체적인 '압박'을 더 정확히 표현하기 위해 여기에 'Uninterruptible Sleep(D 상태)' 프로세스들을 추가했습니다.
프로세스 상태의 재해석
리눅스에서 프로세스는 크게 다음과 같은 상태를 오갑니다.
- Running (R): CPU에서 실행 중이거나 실행 가능한 상태로 대기열에 있는 프로세스.
- Interruptible Sleep (S): 특정 이벤트(네트워크 데이터 수신 등)를 기다리며 잠든 상태.
- Uninterruptible Sleep (D): 하드웨어 I/O(디스크 쓰기, NFS 응답 등) 처리를 기다리며 어떤 시그널에도 반응하지 않는 상태.
리눅스의 Load Average는 바로 이 R 상태와 D 상태 프로세스의 합을 시간으로 나눈 수치입니다. 즉, CPU를 쓰기 위해 줄을 서 있는 프로세스뿐만 아니라, 디스크 I/O가 끝나기만을 애타게 기다리며 아무것도 못 하고 멈춰있는 프로세스들도 모두 Load로 간주합니다. 이것이 바로 CPU 점유율은 낮은데 Load만 폭증하는 기이한 현상의 주범입니다.
지수 이동 평균(EWMA)의 수학적 메커니즘
Load Average는 단순한 산술 평균이 아니라 1분, 5분, 15분 단위의 지수 이동 평균(Exponentially Weighted Moving Average)입니다. 커널은 5초마다 현재의 활성 프로세스 수(n)를 확인하고, 이를 기존 평균값과 결합하여 새로운 수치를 산출합니다.
커널의 계산 공식
커널 내부에서는 다음과 같은 논리의 수식을 사용합니다.
- t: 샘플링 간격 (리눅스는 보통 5초)
- C: 시간 상수 (1분용은 60, 5분용은 300 등)
- n: 현재 측정된 활성 프로세스(R+D) 수
이 덕분에 Load Average는 찰나의 스파이크 트래픽에 민감하게 반응하지 않으면서도, 시스템에 가해지는 점진적인 압박의 추세를 엔지니어에게 명확하게 전달합니다. 15분 수치가 서서히 우상향하고 있다면, 이는 인프라 증설이나 로직 최적화가 필요한 임계점에 도달했음을 의미합니다.
CPU Bound vs I/O Bound
Load Average가 높을 때 엔지니어가 가장 먼저 해야 할 일은 이 부하의 정체가 CPU 때문인지, 아니면 I/O 때문인지 구분하는 것입니다.
vmstat를 활용한 정밀 분석

top만으로는 부족합니다. vmstat 1 명령어를 통해 실행 대기열(r)과 차단된 프로세스(b)의 수를 관찰해야 합니다.
- r (run queue) 수치가 높을 때: 전형적인 CPU Bound 상황입니다. 연산량이 많은 로직이 실행 중이거나 특정 프로세스가 자원을 독점하고 있습니다. 이때는 nice 값 조정이나 numactl을 통한 코어 고정(Pinning) 최적화가 필요합니다.
- b (blocked) 수치가 높을 때: 전형적인 I/O Bound 상황입니다. STON과 같은 캐시 서버에서 대규모 파일 쓰기가 발생하거나 NFS 응답이 늦어질 때 발생합니다. 이때는 CPU 사양을 올려봐야 효과가 없습니다. 디스크 스케줄러를 deadline이나 noop으로 변경하거나 스토리지를 SSD로 교체하는 아키텍처적 접근이 필요합니다.
컨텍스트 스위칭과 PSI(Pressure Stall Information)
보이지 않는 비용: Context Switching
Load Average에 영향을 주는 또 다른 요인은 컨텍스트 스위칭입니다. 프로세스가 교체될 때마다 CPU 레지스터 값을 저장하고 불러오는 오버헤드가 발생합니다. 특히 비자발적 스위칭(Involuntary Context Switches)이 빈번하다면, 이는 시스템에 너무 많은 프로세스가 경합하고 있다는 경고입니다.
차세대 지표: PSI의 도입
최신 리눅스 커널(4.20+)은 Load Average의 모호함을 해결하기 위해 PSI를 제공합니다. /proc/pressure/cpu, memory, io 파일을 통해 각 자원별로 프로세스가 얼마나 '지체(Stall)' 되었는지를 백분율로 보여줍니다. 이는 Load Average보다 훨씬 명확하게 시스템의 병목 구간을 짚어줍니다.
수치 너머의 맥락을 읽는 엔지니어링
Load Average는 단순히 하나의 숫자가 아니라 시스템 전체의 '혈류 속도'를 나타내는 지표입니다. 단순히 코어 수와 비교하는 단계에서 벗어나, 이 숫자가 $R$ 상태에서 오는지 아니면 $D$ 상태에서 오는지, 그리고 그 추세가 어떤 방향인지를 읽어낼 수 있어야 합니다.
최근 우리가 분석했던 AI 캡처 시스템이나 GSLB 아키텍처에서도 이러한 커널 메트릭의 이해는 필수적입니다. 데이터로 증명하고 아키텍처로 해결하는 과정, 그 시작은 바로 가장 익숙한 지표인 Load Average를 제대로 이해하는 것부터 시작됩니다.
데이터. 이건 참 편하고도 어려운 존재입니다. 보다보면 눈이 아픈경우가 잦아요. 다만, 숫자 뒤에 숨어있는 하이라이트 그걸 찾는게 가장 중요합니다. 그래서 요즘은 손 빠른것보다 구성을 이해하는 사람이 더 좋다고 생각하나봐요.
참조 항목:
- Linux Kernel Documentation: 'The Load Average' - 커널 소스 및 산출 공식.
- Brendan Gregg: 'Linux Performance' - Load Average 해석 방법론.
- Facebook Engineering: 'PSI: Pressure Stall Information' - 차세대 리소스 모니터링 기술.
- 실무 사례: STON 캐시 서버의 디스크 I/O 병목 및 Load 폭증 트러블슈팅 리포트.
'IT > 이론' 카테고리의 다른 글
| 흐름의 미학: 리눅스 네트워크 스택과 소켓 버퍼(Socket Buffer) 튜닝의 모든 것 (0) | 2026.01.29 |
|---|---|
| 신뢰의 기원: Terraform State 관리 전략과 인프라 드리프트(Drift) 대응 실무 (0) | 2026.01.27 |
| 한계를 돌파하는 인프라 설계: 고성능 웹 서비스를 위한 리눅스 커널 파라미터 튜닝 전략 (0) | 2026.01.23 |
| 시스템의 침묵을 막아라: 로드 밸런싱 아키텍처와 장애 전이(Cascading Failure) 방지 전략 (0) | 2026.01.22 |
| 사이드카를 넘어 커널의 심장부로: eBPF가 혁신하는 딥 옵저버빌리티(Deep Observability) (0) | 2026.01.21 |