배경
시스템이 느려졌을 때 "어디서부터 봐야 하지?"라는 막막함을 느낀 적이 있습니다. CPU가 문제인지, 메모리가 부족한 건지, 디스크 I/O인지, 아니면 네트워크인지 — 방향 없이 뛰어들면 시간만 소비됩니다.
이 글은 성능 이슈를 분석하는 방법론과 각 자원(CPU, 메모리, 파일시스템/디스크, 네트워크)의 동작 원리와 주요 분석 도구를 정리한 것입니다
1. 성능 이슈 분석 방법론
무작정 도구부터 실행하기 전에 어떤 관점으로 접근할지 방법론을 정해두면 빠트리는 지점 없이 체계적으로 분석할 수 있습니다.
USE 방법론
모든 자원에 대해 사용률(Utilization), 포화도(Saturation), 오류(Errors)를 확인하는 방식입니다. 인프라 레벨의 성능 분석에 적합합니다.
| 지표 | 의미 |
| 사용률 (Utilization) | 자원을 바쁘게 사용한 시간 |
| 포화도 (Saturation) | 처리되지 못한 자원이 있는 수준 |
| 오류 (Errors) | 발생한 오류의 횟수 |
RED 방법론
USE 방법론은 서비스 단위에는 맞지 않습니다. 분산, MSA 환경에서는 서비스 요청 관점의 RED 방법론이 적합합니다.
| 지표 | 의미 |
| Rate | 처리하고 있는 초당 요청의 개수 |
| Errors | 초당 요청이 실패한 개수 |
| Duration | 요청을 처리하는데 걸린 시간 |
| Saturation | 요청을 처리하지 못하고 대기하는 상태 |
과학적 방법론
가설을 수립하고 검증하면서 분석합니다.
질문 → 가설 → 예측 → 테스트 → 분석
예시:
- 질문: DB 쿼리가 느린 원인은?
- 가설: 파일시스템 I/O 성능이 문제일 것이다
- 예측: 쿼리 중 파일시스템 지연시간을 측정해본다
- 테스트: 파일시스템 지연시간을 쿼리 지연시간으로 나눠보니 전체의 5% 미만
- 분석: 파일시스템/디스크는 원인이 아님 → 새로운 가설 수립
2. CPU 성능 분석
동작 원리
CPU는 모든 소프트웨어 실행을 담당합니다. CPU 코어 수보다 프로세스가 많으면 대기열에서 순서를 기다려야 하며, 이 순서를 프로세스 스케줄러가 관리합니다.
| 개념 | 설명 |
| 클럭 속도 | CPU가 명령을 실행하는 속도. 전력 절감을 위해 동적으로 조정 가능 (x86: p-state, ARM: DVFS) |
| 하이퍼스레딩 | 물리 코어 하나에 둘 이상의 스레드 실행. OS는 더 많은 코어로 인식 |
| 사용자 시간 | 사용자 공간 코드를 실행하는 데 소비한 CPU 시간 |
| 커널 시간 | 커널 공간 코드를 실행하는 데 소비한 CPU 시간 |
계산 중심 어플리케이션은 사용자/커널 시간 비율이 99/1에 가깝고, I/O 중심 어플리케이션은 커널 시간 비중이 높습니다.
CPU 사용률 100%가 반드시 문제는 아닙니다. 급격하게 증가하는 패턴이나 특정 인스턴스의 극적인 성능 저하가 동반될 때 조사가 필요합니다.
분석 도구
top — 프로세스/스레드별 CPU 사용 정보를 실시간으로 확인합니다. /proc의 모든 프로세스를 순회하므로 도구 자체의 오버헤드가 있습니다.
us : 사용자 모드에서 실행한 시간
sy : 커널 모드에서 실행한 시간
wa : I/O 완료를 기다리며 아무것도 실행하지 않은 시간
uptime — 시스템 부하 평균을 확인합니다. 1분, 5분, 15분 평균 부하를 보여주므로 추세를 파악하는 데 유용합니다.
vmstat — 가상 메모리 통계와 함께 시스템 전체 CPU 사용률을 표시합니다. 개별 프로세서별로 보려면 mpstat을 사용합니다.
r : 실행/대기 중인 프로세스 개수
b : 인터럽트 불가능 상태의 프로세스 개수
pidstat — 프로세스/스레드별 CPU 사용률을 확인합니다.
| 도구 | 용도 |
| top | 현 시점의 사용량 확인 |
| uptime | 최근 15분간 CPU 사용률 경향 파악 |
| vmstat | 시스템 전체 CPU 사용률 파악 |
| pidstat | 프로세스/스레드별 CPU 사용률 파악 |
3. 메모리 성능 분석
동작 원리
물리 메모리 — 실제로 사용할 수 있는 메모리 공간입니다.
가상 메모리 — 프로세스가 바라보는 물리 메모리를 추상화한 공간입니다. 가상/물리 메모리 공간을 일정한 조각으로 나누어 관리하는 방식을 페이징이라 합니다.
가상 메모리 조각 → 페이지
물리 메모리 조각 → 페이지 프레임
매핑 정보 → 페이지 테이블
요구 페이징 (Demand Paging) — 모든 데이터를 메모리에 올리지 않고 필요할 때만 로드합니다. 프로세스가 존재하지 않는 페이지에 접근하면 페이지 폴트가 발생합니다.
캐시와 버퍼
리눅스는 여유 메모리를 Buffer와 Cache로 사용해 느린 디스크 접근을 최소화합니다.
항목의미
| Buffer | 블록 디바이스 메타데이터를 캐싱한 메모리 |
| Cache | 페이지 캐시 + slab으로 사용 중인 메모리 |
| active | buff+cache 중 최근 사용된 메모리 |
| inactive | buff+cache 중 회수 가능한 메모리 |
Out Of Memory (OOM)
가용 메모리가 소진되면 커널의 OOM Killer가 가장 높은 oom_score를 가진 프로세스를 종료하여 메모리를 확보합니다.
# OOM Killer 커널 메시지 예시
Out of memory: Killed process 1124107 (stress-ng-bighe) total-vm:440728kB, anon-rss:356888kB
score 범위는 0~1000이며, 메모리를 많이 사용할수록 높아집니다. 특정 프로세스를 보호하려면 oom_score_adj를 낮게 설정합니다.
# 특정 프로세스가 OOM Killer에 종료되지 않게 설정
echo -1000 > /proc/448/oom_score_adj
cat /proc/448/oom_score
# 0
분석 도구
vmstat — 가상 메모리 통계를 확인합니다.
free : idle 메모리 양
buff : 버퍼로 사용된 메모리 양
cache : 캐시로 사용된 메모리 양
si : 디스크에서 swap in 된 메모리 양
so : 디스크에서 swap out 된 메모리 양 (메모리 부족 상황 신호)
free — 메모리 사용 현황을 요약합니다.
[total] : 설치된 총 메모리 크기
[used] : total - free - buff/cache
[free] : 실제 사용 가능한 여유 메모리
[available] : 스왑 없이 새 프로세스에 할당 가능한 예상 크기
pmap — 프로세스의 메모리 맵 정보를 표시합니다. 매핑된 메모리 크기, 권한, 실제 사용량을 확인할 수 있습니다.
4. 파일시스템 성능 분석
파일시스템 선택
EXT4와 XFS는 일반적인 워크로드에서 성능 차이가 크지 않습니다. I/O 바운드 워크로드(예: 데이터베이스 서버)에서는 파일시스템 종류와 커널 버전을 함께 확인합니다.
페이지 캐시
디스크 I/O를 최소화하기 위해 디스크 접근이 필요한 데이터를 물리 메모리에 저장합니다. 페이지 캐시 히트 비율이 성능에 크게 영향을 미칩니다.
버퍼 캐시 (쓰기 성능 개선)
- 쓰기 동작은 페이지 캐시에 수행하고, 즉시 디스크에 반영하지 않음
- pdflush 데몬이 주기적으로 더티 페이지를 디스크에 저장
동기적 쓰기
버퍼를 우회하여 바로 디스크에 기록해야 할 때 사용합니다.
fsync(fd) // 지연된 쓰기 버퍼 내용을 동기적으로 디스크에 저장
O_SYNC // write + fsync
O_DIRECT // 버퍼 캐시를 사용하지 않고 직접 디스크에 쓰기
DB가 O_DIRECT를 쓰는 이유는 자체 메모리 관리를 통해 성능과 안정성을 보장하기 위해서입니다.
주요 성능 지표
| 지표 | 설명 |
| 처리량 (Throughput) | 초당 전송되는 데이터 양 (예: AWS gp3 EBS 최대 1,000 MiB/s) |
| IOPS | 초당 I/O 요청 개수 (예: AWS gp3 EBS 최대 16,000) |
| I/O 요청 크기 | 요청 크기가 작을수록 성능 낮음 |
| 읽기/쓰기 비율 | 페이지 캐시 활용 패턴에 영향 |
| 동기적 쓰기 비율 | 지연 쓰기 대비 성능 차이가 큼 |
| 접근 패턴 | HDD는 랜덤/순차 차이가 크고, SSD는 Small Random Write에 약점 |
5. 디스크 성능 분석
디스크 I/O 성능 개선
가장 효과적인 방법은 HDD를 SSD로 교체하는 것입니다. SSD는 랜덤 읽기, 처리량, IOPS 모두 HDD보다 우세합니다. 다만 HDD는 대규모 스트리밍 데이터 저장에서 여전히 비용 효율적입니다.
I/O 스케줄러
블록 I/O 요청을 병합하고 정렬하여 성능을 향상시킵니다.
| 스케줄러 | 특징 |
| deadline / mq-deadline | 각 I/O 요청의 시작 시간을 보장 |
| cfq | 프로세스 간 I/O를 공정하게 할당 |
| noop / none | 요청을 정렬하지 않음, SSD에 적합 |
SSD에서는 탐색 시간이 없으므로 스케줄러 효과가 적습니다. 가상/클라우드 환경에서도 I/O 바운드 앱이 아니라면 스케줄러 변경의 극적인 효과를 기대하기 어렵습니다.
분석 도구
iostat — CPU 통계와 디바이스별 I/O 통계를 표시합니다.
tps : 디바이스에 요청된 데이터 전송 횟수
read/s : 초당 읽기 양
wrtn/s : 초당 쓰기 양
r_await : 읽기 요청의 평균 응답 시간 (큐 대기 포함)
w_await : 쓰기 요청의 평균 응답 시간 (큐 대기 포함)
pidstat -d — 프로세스별 I/O 내용을 표시합니다.
iotop — top과 유사하게 I/O에 대한 상위 프로세스 정보를 출력합니다.
벤치마크 도구: fio
# fio 설치
sudo apt install -y fio
# 연속 쓰기 테스트 (1M 크기, 10개 job)
sudo fio --name=write_test \
--filename=/dev/xvdf --filesize=100G \
--time_based --ramp_time=2s --runtime=1m \
--ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
--bs=1M --iodepth=64 --rw=write --numjobs=10 --offset_increment=10G
# 랜덤 읽기 테스트 (4K 크기)
sudo fio --name=read_test \
--filename=/dev/xvdf --filesize=100G \
--time_based --ramp_time=2s --runtime=1m \
--ioengine=libaio --direct=1 --verify=0 --randrepeat=0 \
--bs=4K --iodepth=256 --rw=randread
I/O 우선순위 조정: ionice
# I/O 스케줄링 클래스 설정
ionice -c 2 -n 0 COMMAND # 높은 우선순위
# 클래스 번호
# 1: realtime (가장 높은 우선순위)
# 2: best-effort
# 3: idle (디스크가 유휴 상태일 때만 I/O)
6. 네트워크 성능 분석
핵심 지표
네트워크 성능은 처리량(Throughput)과 지연시간(Latency)으로 평가합니다.
- Throughput — 특정 시간 동안 발생한 이벤트 (높을수록 좋음)
- Latency — 이벤트가 발생하기까지 걸린 시간 (낮을수록 좋음)
주요 지연 시간 지표입니다.
| 지표 | 설명 |
| 이름 분석 지연시간 | DNS 질의에 걸리는 시간 |
| 연결 지연시간 | TCP 핸드셰이크에 걸리는 시간 |
| TTFB | 연결 후 첫 번째 바이트가 도착하기까지 걸린 시간 |
| RTT | 네트워크 패킷이 두 끝점을 왕복하는 시간 |
| 연결 지속 시간 | 연결이 맺어진 시간부터 닫힐 때까지의 시간 |
클라우드 환경에서 Latency 줄이기
물리적 거리 단축 — 클라이언트 근처의 캐시/엣지 서버를 활용합니다.
인스턴스 크기 변경 — 일반적으로 인스턴스 크기가 증가할수록 네트워크 대역폭도 증가합니다.
점보 프레임 — MTU 크기를 늘려 전송합니다. AWS VPC 간 연결에 활용할 수 있으나, 큰 패킷은 손상되기 쉽고 재전송 시 부담도 커집니다.
TCP 튜닝 파라미터
# 백로그 대기열 크기
sysctl net.core.netdev_max_backlog
# TCP 송신/수신 버퍼 크기
sysctl net.ipv4.tcp_wmem
sysctl net.ipv4.tcp_rmem
# 혼잡 제어 알고리즘 (BBR 적용 예시)
net.ipv4.tcp_congestion_control="bbr"
BBR(Bottleneck Bandwidth and RTT)은 Google이 개발한 혼잡 제어 알고리즘으로, 네트워크 사용량이 중요한 앱에서 성능 개선 효과가 있습니다. 운영 환경 적용 전에 충분한 실험이 필요합니다.
분석 도구
ping — ICMP echo 요청으로 네트워크 연결성과 RTT를 확인합니다. ICMP 패킷은 라우터에서 낮은 우선순위로 처리될 수 있어 실제보다 높은 지연이 나올 수 있습니다.
traceroute — 목적지까지의 경로(홉)를 확인합니다.
sudo traceroute -T -p 443 example.com
mtr — traceroute + ping. 경로를 찾으면서 각 게이트웨이의 응답시간도 측정합니다.
mtr -c 10 8.8.8.8 --report
# Host Loss% Snt Last Avg Best Wrst StDev
항목의미
| 항목 | 의미 |
| Loss | 패킷 손실율 |
| Last | 최근 응답시간 |
| Avg | 평균 응답시간 |
| Best / Wrst | 최소 / 최대 응답시간 |
| StDev | 표준편차 |
ip -s link — 인터페이스별 RX/TX 통계, 오류, 드롭을 확인합니다.
마치며
성능 분석은 "어디를 봐야 할지"를 아는 것에서 시작합니다. USE/RED 방법론으로 방향을 잡고, 자원별로 올바른 도구를 사용해 수치를 읽는 것이 핵심입니다.
한 자원만 보지 말고 항상 시스템 전체 관점에서 병목을 추적하는 것이 중요합니다. CPU 사용률이 낮아도 디스크 I/O 대기가 쌓이고 있을 수 있고, 메모리가 여유로워 보여도 swap out이 발생하고 있을 수 있습니다.
'system' 카테고리의 다른 글
| 도와줘! strace (0) | 2026.06.04 |
|---|---|
| 인프라 모니터링: 무엇을, 왜, 어떻게 볼 것인가 (0) | 2026.06.04 |
| 스토리지 종류와 구성 방식 정리 (0) | 2026.06.04 |
| SELinux, 그런데 Nginx를 곁들인 (0) | 2026.05.19 |
| OpenVPN Access Server로 Split Tunneling 구현하기 (0) | 2026.04.21 |