- Published on
로드/성능 테스트 도구 2026 — k6·Locust·Vegeta·Gatling·Artillery·JMeter 심층 비교 (JMeter 너머의 풍경)
- Authors

- Name
- Youngju Kim
- @fjvbn20031
프롤로그 — "초당 만 건 가능합니다"라는 거짓말
2026년 어느 회사의 출시 전날.
PM: "초당 만 건 가능하죠?" 백엔드: "JMeter로 돌려봤습니다. 통과했어요." SRE: "어떤 시나리오로?" 백엔드: "constant 만 RPS로 5분..." SRE: "production traffic 패턴은요? warm-up이 들어갔어요? p99는?" 백엔드: "..."
이 장면이 2026년에도 흔하다. 도구는 좋아졌는데 측정 문화는 그대로다. "통과했다"라고 말하지만, 무엇이 통과했는지, 어떤 분포에서 통과했는지, production과 얼마나 닮았는지는 답이 없다. 그러는 사이 출시 후 실제 트래픽은 burst로 들어오고, 캐시가 콜드 상태에서 시작하고, p99는 SLO를 깨고, 그 모든 게 "통과한" 테스트와 무관하게 일어난다.
도구 자체는 좋아졌다. 2010년대의 JMeter 중심 세계는 이제 k6(Grafana) 가 사실상 표준이 된 풍경으로 바뀌었고, Locust·Vegeta·Gatling·Artillery·Bombardier 같은 선택지가 각자의 영역에서 자리를 잡았다. 마이크로 벤치마크 영역에는 wrk·wrk2·autocannon이 살아 있고, gRPC·WebSocket 같은 비-HTTP 프로토콜에는 ghz·fortio가 따로 있다.
이 글은 2026년의 로드/성능 테스트 도구 지도를 그린다. 각 도구의 위치, 같은 시나리오를 도구별로 어떻게 짜는지, "좋은 로드 테스트"란 무엇인지, 그리고 우리 팀이 어떻게 고를지까지.
1장 · 로드 테스트의 4가지 목적 — 무엇을 잴 건지부터
도구를 고르기 전에 목적부터 정리한다. 같은 도구가 모든 목적에 맞지 않는다.
- 마이크로 벤치마크 (micro-benchmark) — 단일 엔드포인트의 한계 throughput과 p99 latency를 잰다. "이 핫 패스가 얼마나 빠른가?" 작은 변경의 회귀를 잡는 용도. wrk, autocannon, Bombardier, Vegeta.
- 부하 테스트 (load test) — 예상 트래픽 수준에서 시스템이 SLO 안에서 동작하는가. 보통 일정 RPS를 일정 시간 유지. k6, Locust, Gatling, Artillery, JMeter.
- 스트레스 테스트 (stress test) — 한계를 찾는다. 어느 지점에서 시스템이 무너지는가, 어떻게 무너지는가, 회복 가능한가. 위 도구들 + 시나리오 설계.
- 스파이크/소크 테스트 (spike & soak) — 갑작스러운 트래픽 폭증(스파이크)과 장시간 유지(소크, 메모리 누수·연결 누수 잡기). k6, Locust가 시나리오 표현에 강하다.
추가로 카오스 테스트(장애 주입 + 부하)는 별도의 축이지만, 부하 도구로 트래픽을 흘리며 chaos tool로 장애를 주입하는 조합이 흔하다.
핵심: "성능 테스트"라는 단일 단어가 위의 4가지를 모두 가리킨다. 도구를 고를 때는 "어떤 종류의 테스트를 주로 할 것인가"부터 답해야 한다. 마이크로 벤치마크에 JMeter를 끄집어내는 건 과하고, 복잡한 시나리오에 wrk를 쓰는 건 부족하다.
2장 · 도구 지도 2026 — 한눈에
| 도구 | 언어/스크립트 | 강점 | 약점 | 대표 사용처 |
|---|---|---|---|---|
| k6 | JS (ES2015+), Go 런타임 | 모던 기본값, 풍부한 출력, 클라우드 옵션, gRPC/WS/브라우저 | 분산은 OSS에서 직접 구성 | 2026년의 일반 기본값 |
| Locust | Python | 분산이 쉽다, Python 코드 가능 | 단일 워커 throughput 한계 | Python 팀, 행위 모델 복잡 |
| Vegeta | Go (CLI + 라이브러리) | 한 줄로 실행, 결과 분석 강력 | 시나리오 표현은 단순 | HTTP 마이크로 벤치, 빠른 측정 |
| Gatling | Scala/Java DSL | 시나리오 표현력, 엔터프라이즈 리포팅 | Scala 학습 곡선 | 대규모, JVM 친화 조직 |
| Artillery | Node.js, YAML | 빠른 시작, YAML로 표현 | 고부하에서 단일 노드 한계 | Node 팀, CI 시나리오 |
| wrk / wrk2 | C, Lua 스크립트 | 매우 가볍고 빠른 HTTP 벤치 | HTTP만, 시나리오 단순 | 핫 패스 마이크로 벤치 |
| autocannon | Node.js | npm 설치만으로 즉시 | Node 팀 외에는 동기 약함 | Node API 빠른 벤치 |
| Bombardier | Go | 정말 단순하고 빠른 CLI | 시나리오 거의 없음 | 한 줄 부하 측정 |
| JMeter | Java, GUI/XML | 오래된 자료·플러그인 생태계 | XML 시나리오, 모던 UX 아님 | 엔터프라이즈, 기존 자산 |
| ghz | Go, CLI | gRPC 전용, 단순 | gRPC 외에는 부적합 | gRPC 서비스 벤치 |
| fortio | Go (Istio) | gRPC + HTTP, 분포 분석 | UI 평이 | 서비스 메시 검증 |
한 줄 정리: 2026년의 "처음 잡는 도구"는 대체로 k6다. 팀이 Python 친화적이면 Locust. 한 줄 마이크로 벤치는 Vegeta(또는 wrk). 엔터프라이즈/JVM 친화 조직과 기존 자산은 JMeter/Gatling. Node 친화 팀의 빠른 CI 시나리오는 Artillery. gRPC는 ghz 또는 k6 gRPC 모듈.
3장 · k6 — 2026년의 일반 기본값
현재 상태 (2026년 5월): Grafana Labs 산하. k6 OSS 바이너리는 무료, Grafana Cloud k6에서 분산 실행/대시보드를 유료로 제공. v0.5x 대 안정 릴리스가 꾸준히 나오고 있으며, browser 모듈(Playwright 백엔드)·gRPC·WebSocket·xk6 확장 생태계가 확장 중이다.
왜 기본값이 됐나:
- JS로 시나리오 작성 — 엔지니어 다수가 읽고 짤 수 있다.
- Go 기반 단일 바이너리 — 설치가 쉽다. CPU 효율도 좋다 (Locust보다 단일 워커 throughput이 훨씬 높다).
- 출력이 풍부 — 콘솔에서 p50/p90/p95/p99까지 기본으로 본다. Prometheus·InfluxDB·Datadog로 export 가능.
- scenario·executor 모델 —
constant-vus,ramping-arrival-rate,per-vu-iterations등 표현력이 좋다. - 확장 가능 — xk6로 SQL·Kafka·Redis 모듈을 붙일 수 있다.
기본 스크립트 (4장에서 비교용으로 다시 본다):
// k6 script: login + ramp 50 → 200 RPS for 5min
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
scenarios: {
login_ramp: {
executor: 'ramping-arrival-rate',
startRate: 50,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 500,
stages: [
{ target: 50, duration: '1m' },
{ target: 200, duration: '5m' },
{ target: 200, duration: '2m' },
],
},
},
thresholds: {
http_req_duration: ['p(99)<500'],
http_req_failed: ['rate<0.01'],
},
};
export default function () {
const res = http.post('https://api.example.com/login', JSON.stringify({
user: 'demo',
pass: 'pw'
}), { headers: { 'Content-Type': 'application/json' } });
check(res, { 'status 200': (r) => r.status === 200 });
sleep(1);
}
k6 Cloud(Grafana Cloud k6) 비용 감각 (2026년 기준): 무료 플랜은 월 50 VUh, Pro 플랜은 $299/월 부터 시작하며 VUh와 동시 실행 한도가 늘어난다. 분산 실행/지역 분산이 필요하면 cloud 옵션이 편하고, 대안은 self-host 분산(여러 노드에서 같은 스크립트 실행, 결과 집계).
한계:
- 분산 실행이 OSS에서는 직접 구성해야 한다 — k8s operator(
grafana/k6-operator)가 있지만 운영 부담. - JS 런타임은 V8이 아니라 Goja(Go에서 임베드된 ES5+). 일부 모던 JS feature는 babel transform 필요.
- 데이터 변환 무거운 로직은 시나리오 외부에서 처리하는 게 안전.
4장 · 같은 시나리오, 도구별 비교 — POST /login + ramp 50 → 200 RPS
같은 시나리오를 k6 / Locust / Vegeta로 어떻게 표현하는지 나란히 본다.
k6
위 3장의 스크립트 그대로. 핵심은 ramping-arrival-rate executor와 thresholds로 p99·실패율을 코드로 선언.
Locust (Python)
# locustfile.py
from locust import HttpUser, task, LoadTestShape, constant_throughput
class LoginUser(HttpUser):
wait_time = constant_throughput(1) # 1 req/sec per user
@task
def login(self):
self.client.post(
"/login",
json={"user": "demo", "pass": "pw"},
headers={"Content-Type": "application/json"},
)
class RampShape(LoadTestShape):
stages = [
{"duration": 60, "users": 50, "spawn_rate": 50},
{"duration": 360, "users": 200, "spawn_rate": 5},
{"duration": 480, "users": 200, "spawn_rate": 0},
]
def tick(self):
run_time = self.get_run_time()
for stage in self.stages:
if run_time < stage["duration"]:
return (stage["users"], stage["spawn_rate"])
return None
실행: locust -f locustfile.py --headless -H https://api.example.com. 분산 모드는 master/worker(--master, --worker)로 쉽게 분리되며, k8s helm chart도 잘 알려져 있다.
Vegeta (CLI)
# targets.txt
# POST https://api.example.com/login
# Content-Type: application/json
# @body.json
# step 1: 50 RPS for 1m
echo "POST https://api.example.com/login" | \
vegeta attack -rate=50 -duration=60s -body=body.json \
-header="Content-Type: application/json" \
| vegeta report -type=hist[0,100ms,200ms,500ms,1s]
# step 2: 200 RPS for 5m
echo "POST https://api.example.com/login" | \
vegeta attack -rate=200 -duration=5m -body=body.json \
-header="Content-Type: application/json" \
| tee result.bin \
| vegeta report
vegeta plot result.bin > plot.html
Vegeta는 시나리오 자체가 단순하다 — 일정 rate를 일정 시간 동안 친다. ramp는 보통 단계별 명령을 이어 실행하거나, 셸 스크립트로 외부에서 만든다. 그 단순함이 강점이다 — 한 줄로 측정이 끝나고, vegeta report -type=json이나 vegeta plot으로 분포·시계열을 본다.
비교 관찰:
- 표현력: Locust(가장 자유) ≈ k6 > Vegeta. Vegeta는 일부러 단순하다.
- CPU 효율: k6 > Vegeta > Locust (단일 워커 기준; Locust는 분산으로 보완).
- CI 친화: k6(threshold로 exit code) ≈ Vegeta(report로 grep). Locust도 headless로 CI 가능.
- 결과 시각화: k6(Grafana Cloud k6 또는 직접 Prometheus) > Locust(웹 UI) > Vegeta(plot HTML).
5장 · Locust — Python 팀의 편안한 친구
현재 상태 (2026년): 활발히 유지보수 중. v2.x 안정. Locust는 "코드로 표현 가능한 행위 모델"이 강점이다. 사용자가 무엇을 하는지 클래스/메서드로 표현하고, @task 데코레이터로 가중치를 준다.
언제 적합한가:
- 팀이 Python 친화적이고 데이터/추상화 라이브러리를 그대로 부르고 싶을 때.
- 사용자 행위 모델이 복잡할 때(여러 페이지를 순회, 상태 보유).
- 분산 실행이 필요하지만 별도 SaaS는 쓰기 싫을 때 —
--master/--worker로 매우 단순.
한계:
- 단일 워커의 throughput은 k6보다 낮다. Python의 gevent 기반 동시성은 효율적이지만 Go보다는 무겁다.
- 결과 시각화는 내장 웹 UI가 있지만 k6/Grafana 조합만큼 풍부하지 않다.
팁: Locust의 강점은 분산이 쉽다는 것이다. 100k+ RPS가 필요하면 워커 수십 개를 띄우는 게 자연스럽다. k8s에 helm chart로 띄우고, Prometheus로 메트릭 모으는 패턴이 익숙해지면 운영이 단순해진다.
6장 · Vegeta — 한 줄의 우아함
현재 상태 (2026년): 단일 메인테이너 중심으로 유지보수 중. 안정적이고 단순하다. 신기능은 거의 없지만, 그게 미덕이다.
왜 Vegeta가 살아남았나:
- 한 줄로 측정 —
echo "GET https://..." | vegeta attack -rate=100 -duration=30s | vegeta report. 다른 도구라면 파일 만들고, runner 띄우고, 컨테이너 마운트하는 게 vegeta는 한 줄이다. - 분포 분석이 정확 —
vegeta report출력에 p50/p90/p95/p99/min/mean/max가 한 번에 나온다. histogram 버킷도 CLI로 지정. - 결과 직렬화 —
.bin형식으로 저장 후 나중에 reproc 가능. CI에서 bin을 artifact로 저장하고 나중에 분석.
한계:
- 시나리오 표현이 단순하다 — 일정 rate 또는 step 묶음. 복잡한 사용자 시뮬레이션엔 부적합.
- 분산 모드는 CLI 도구다 보니 직접 구성. 보통 여러 머신에서 같은 명령을 실행하고 bin을 모아 합치는 방식.
대표 사용: 핫 패스 하나의 latency 분포를 정확히 측정하고 싶을 때, CI에서 회귀를 잡는 마이크로 벤치, "지금 서버가 살아 있나" 빠른 체크.
7장 · Gatling — JVM 진영의 강자
현재 상태 (2026년): Gatling 3.x 안정. Gatling Enterprise(유료, 구 FrontLine)와 OSS 둘 다 활발. Scala DSL이 기본이지만 Java/Kotlin DSL도 정식 지원한다.
왜 여전히 쓰이나:
- DSL의 표현력 — 시나리오·체이닝·assertion이 코드처럼 자연스럽다.
- 리포팅 — HTML 리포트가 매우 깔끔하다. enterprise는 분산/팀 협업.
- JVM 친화 조직 — Maven/Gradle 빌드에 자연스럽게 들어간다.
- Scala 학습 비용은 줄었다 — Java DSL이 1급 시민이 됐다.
언제 적합한가:
- JVM 기반 백엔드를 가진 조직, 빌드 시스템에 통합하고 싶을 때.
- 시나리오가 복잡하고 코드 리뷰 가능한 형태로 두고 싶을 때.
- 엔터프라이즈 지원이 필요한 환경.
한계:
- 가벼운 한 줄 측정은 부적합 — JVM 기동·SBT/Maven 비용.
- Scala 진입 장벽은 줄었지만 0은 아니다.
8장 · Artillery — YAML 시나리오의 간편함
현재 상태 (2026년): OSS + Cloud(유료). YAML로 시나리오를 표현하는 게 매력. 최근 v2 부터는 분산 실행(Cloud) 옵션도 강화됐다.
왜 쓰이나:
- YAML 시나리오 — 코드 작성 없이 "URL·페이로드·플로우"를 선언적으로.
- Node.js 기반 — Node 팀에 친숙.
- 빠른 시작 —
npm install -g artillery후 yml 파일 하나면 실행.
한계:
- 단일 노드 throughput은 k6보다 낮다 (Node 이벤트 루프 한계).
- 매우 큰 부하에선 Cloud 또는 다중 인스턴스가 필요.
예시 시나리오 (조금 다른 형태로):
config:
target: 'https://api.example.com'
phases:
- duration: 60
arrivalRate: 50
- duration: 300
arrivalRate: 50
rampTo: 200
- duration: 120
arrivalRate: 200
scenarios:
- flow:
- post:
url: '/login'
json:
user: 'demo'
pass: 'pw'
expect:
- statusCode: 200
9장 · JMeter — 살아 있는 노장
현재 상태 (2026년): Apache JMeter 5.x 유지보수 중. 학습 자료가 가장 많고, 플러그인 생태계가 가장 넓다. GUI 중심이지만 헤드리스 실행도 정식 지원.
왜 여전히 보이나:
- 기존 자산 — 수많은 조직이
.jmx파일을 갖고 있다. 마이그레이션 비용 vs. 유지 비용. - 플러그인 — Prometheus listener, custom protocol, blazemeter 통합 등.
- 금융·통신 등 엔터프라이즈 — 사내 표준이 JMeter인 경우.
- GUI 친화 — 코드를 모르는 QA가 쓰기 좋다 (장단 양면).
왜 새로 시작하는 팀은 거의 안 고르나:
- XML(
.jmx) 시나리오 — git diff 친화적이지 않다. - 모던 UX·CLI 친화가 약하다.
- CI 통합이 가능하지만 k6/Locust에 비해 손이 더 간다.
가이드: 신규 프로젝트에서 JMeter를 새로 선택할 이유는 거의 없다. 다만 기존 자산이 있다면 그것을 폐기하고 마이그레이션하는 비용은 별도 결정. 점진적으로 새 테스트는 k6/Gatling으로 짜고, 기존은 유지하는 패턴이 흔하다.
10장 · 마이크로 벤치마크 — wrk / wrk2 / autocannon / Bombardier
이 4개 도구는 "한 엔드포인트의 한계 throughput과 latency 분포"를 빠르게 잡는 데 특화됐다.
wrk
- C로 작성, 매우 빠르다. Lua 스크립트로 약간의 커스터마이즈.
- HTTP만, keep-alive 친화.
- 단점: rate-limit이 없다 — 한계 throughput을 측정하므로 항상 max 부하.
wrk2
- wrk의 fork. 고정 rate를 지원 — "정확히 1000 RPS를 30초 동안" 같은 측정 가능.
- 마이크로 벤치 + 고정 rate 측정에 이상적.
- coordinated omission 보정에 강점.
autocannon
- Node.js 기반.
npm install -g autocannon후autocannon -c 50 -d 30 https://.... - Node 친화 팀의 빠른 CI 벤치에 적합.
Bombardier
- Go 단일 바이너리. 매우 단순하고 빠르다.
bombardier -c 125 -n 1000000 https://.... - 시나리오 표현 거의 없지만, 그게 핵심.
- 메인테이너 활동은 있지만 신기능보다는 안정 유지 모드.
언제 무엇을:
- 정확한 latency 분포와 고정 rate가 필요 → wrk2.
- 그냥 빠르게 한 번 부하 → wrk 또는 Bombardier.
- Node 팀이고 CI 통합 → autocannon.
- 시나리오가 조금이라도 필요 → 이 4개가 아니라 Vegeta 또는 k6.
11장 · 비-HTTP 프로토콜 — gRPC, WebSocket, 브라우저
2026년의 부하 측정은 HTTP만이 아니다. gRPC·WebSocket·실 브라우저(Headless Chrome) 모두 측정 대상이다.
gRPC
- ghz — gRPC 전용 CLI 도구.
ghz --insecure --proto ./svc.proto --call svc.Hello -c 50 -n 10000 .... 단순하고 정확. - k6 gRPC 모듈 —
import grpc from 'k6/net/grpc'. 시나리오 안에 gRPC 호출을 섞을 수 있다. - fortio — Istio 출신. HTTP + gRPC 둘 다, p50–p999 분포 분석에 강하다.
WebSocket
- k6 WS 모듈 —
import ws from 'k6/ws'. 연결 수·메시지 RPS·세션 길이 시나리오 가능. - Artillery — WS를 기본 지원, YAML로 시나리오.
- Gatling — WS 시나리오 표현력이 좋음.
브라우저 (Real Browser Load)
- k6 browser 모듈 — Playwright 백엔드. 실제 브라우저로 JS 실행·렌더·페이지 상호작용을 측정. 사용 사례: 프런트엔드 회귀, 페이지 로드 SLO.
- 비용 주의: 브라우저 인스턴스는 무거우므로 RPS가 아니라 동시 세션 수로 사고.
12장 · "좋은 로드 테스트"란 무엇인가 — 2026 체크리스트
도구가 좋아도 시나리오가 나쁘면 결과도 나쁘다. 좋은 로드 테스트의 핵심.
1) production-like 데이터
- 사용자 ID, 페이로드 크기, 토큰 분포가 production과 닮아야 한다.
- "한 사용자가 같은 페이지를 1만 번"은 캐시에 다 맞는다 — production은 그렇지 않다.
- production에서 sampling한 페이로드를 anonymize해서 사용하는 패턴.
2) 일정 rate가 아니라 분포
- "constant 1000 RPS"는 measurement용이지 reality와 멀다.
- production은 burst·dip·diurnal 패턴이 있다.
- k6의
ramping-arrival-rate, Locust의LoadTestShape로 시나리오를 모델링.
3) warm-up과 ramp-up
- 캐시·DB connection pool·JIT가 콜드 상태로 시작하는 측정은 항상 비관적이다.
- 처음 1–2분은 warm-up으로 두고 측정 구간에서 제외.
4) p99 (avg 아님)
- "평균 latency"는 SLO의 친구가 아니다. 평균은 long-tail을 숨긴다.
- p95·p99·p999 (특히 p99)가 SLO와 직결된다. 모든 도구의 출력에서 percentile을 확인.
- 측정 도구가 coordinated omission으로 p99를 낮게 보고할 수 있다 — wrk2가 이 문제를 처음 잘 다뤘다.
5) error rate 분리
- 성공 응답만으로 latency를 잡으면 죽은 요청을 못 본다.
- 4xx·5xx·timeout·connection refused를 따로 카운트하고, 임계치를 설정.
6) 다중 측정점
- 부하 도구의 클라이언트 측 latency뿐 아니라 서버 측 RED(Rate·Error·Duration) 메트릭, downstream 의존성도 함께 본다.
- 부하 도구가 "느림"을 보고하는데 서버 메트릭은 빠르다 → 네트워크/측정 문제. 그 반대도 있다.
7) 한 번 말고 정기적
- 출시 전 한 번이 아니라, 주간·월간 회귀 테스트로 둔다.
- 코드 변경이 latency 분포에 미친 영향을 시계열로.
13장 · self-host 대 cloud — 비용과 운영
분산 실행이 필요해지면 두 갈래다.
Self-host 분산
- k6 OSS + grafana/k6-operator (k8s) — pod로 실행, 결과를 Prometheus/InfluxDB로.
- Locust master/worker — 가장 단순. helm chart로 워커 N개 띄움.
- 여러 노드에서 같은 명령 + 결과 머지 — vegeta·wrk·Bombardier 식 접근.
장점: 비용 통제, 데이터가 인하우스. 단점: 운영 부담, 지역 분산 어려움.
Cloud
- Grafana Cloud k6 — 분산 실행, 지역, 대시보드. 월 $299 부터.
- BlazeMeter — JMeter/Gatling/k6 호환, 엔터프라이즈 SaaS.
- Artillery Cloud — Artillery 기반 SaaS.
- Loader.io, k6 Cloud — 작은 부하 측정용 무료 티어부터.
장점: 지역 분산·즉시 실행·대시보드 즉시. 단점: 비용(주 1회 큰 테스트면 빠르게 $수백~수천/월).
경험칙: 단발성 대형 측정(출시 전)은 cloud가 싸고 빠르다. 정기 회귀 테스트는 self-host가 장기적으로 싸다. 둘을 섞는 조직이 많다 — 일상 CI는 self-host, 분기별 대규모는 cloud.
14장 · 도구를 고르는 결정 프레임 — 정직한 가이드
| 상황 | 추천 |
|---|---|
| 처음 시작, 일반 백엔드 | k6 |
| Python 팀, 행위 모델 복잡 | Locust |
| 한 줄 마이크로 벤치 | Vegeta 또는 wrk2 |
| Node 팀, CI 빠르게 | Artillery 또는 autocannon |
| 엔터프라이즈 JVM 조직 | Gatling |
| 기존 자산이 JMeter | JMeter 유지 + k6 신규 병행 |
| gRPC 측정 | ghz 또는 k6 gRPC |
| 브라우저 부하 | k6 browser |
| 단순 throughput 한계 측정 | wrk 또는 Bombardier |
| 카오스 테스트 + 부하 | k6/Locust + Toxiproxy/Litmus |
섞기는 흔하다. 한 조직 안에서 마이크로 벤치는 Vegeta, 일반 부하는 k6, 기존 큰 시나리오는 JMeter — 이런 조합이 현실의 모습. 도구를 통일하려고 무리하지 말고, 영역별로 적합한 도구를 인정하는 게 운영을 단순하게 한다.
15장 · 안티패턴과 함정
- production에서 직접 부하 테스트 — staging 또는 격리된 production-like 환경에서 한다. production canary는 별개 기법.
- DNS·CDN을 통과하지 않고 origin에 직접 — 측정은 통과하지만 SLO는 CDN 포함이다. 측정 경로가 user path와 같아야 한다.
- localhost에서 측정 후 결론 — 네트워크 latency가 0이라 RPS만 보면 거짓 안전감.
- constant rate 한 번으로 통과 선언 — production은 분포다.
- 평균 latency만 본다 — p99를 봐야 한다.
- 부하 도구만 본다 — 서버 메트릭과 함께 본다.
- 출시 전 한 번 — 회귀 테스트로 둬야 한다.
- wrk로 시나리오 측정 — 시나리오는 wrk의 일이 아니다.
- 분산 안 짜고 단일 노드로 100k RPS 시도 — 도구의 한계를 시스템 한계로 오인.
에필로그 — 측정은 결정의 도구다
도구는 풍부하다. JMeter가 표준이던 시절은 갔고, k6가 사실상 기본값이 됐다. Locust는 Python 친화 조직의 좋은 친구, Vegeta는 한 줄 측정의 우아함, Gatling은 JVM 진영의 강자, Artillery는 빠른 시작, wrk/wrk2/autocannon/Bombardier는 마이크로 벤치의 단순함.
그러나 도구가 결과를 만들지는 않는다. 시나리오가 production을 닮았는가, percentile을 보았는가, warm-up을 두었는가, 회귀로 두었는가가 결과를 만든다. 도구를 고른 후의 일이 더 길고 중요하다.
이 글의 한 문장 요약: "잘 돌아요"는 측정이 아니다. p99·분포·시나리오로 답해야 측정이다. 도구는 그 답을 가능하게 하는 수단일 뿐, 답 자체는 우리가 정의해야 한다.
12개 항목 체크리스트
- 목적이 명확한가 (마이크로/부하/스트레스/스파이크 중)?
- production-like 데이터를 쓰는가?
- constant rate 말고 분포·ramp를 모델링했는가?
- warm-up 구간을 측정에서 제외했는가?
- p99(또는 p999)를 SLO에 연결했는가?
- error rate를 latency와 분리해서 보았는가?
- 클라이언트 측 + 서버 측 메트릭을 같이 보았는가?
- CI에 회귀로 들어가 있는가?
- 분산이 필요할 때 self-host/cloud 결정을 내렸는가?
- 비-HTTP 프로토콜이 있다면 그 도구를 함께 쓰는가 (gRPC/WS/브라우저)?
- 측정 경로가 user path와 일치하는가 (DNS·CDN 포함)?
- coordinated omission 보정을 이해하고 있는가?
안티패턴 10가지
- 평균 latency만 본다 — p99를 보라.
- constant rate 한 번으로 통과 선언 — 분포를 모델링.
- localhost에서 측정 후 결론 — 네트워크가 없다.
- production에서 직접 부하 — staging에서.
- 부하 도구만 본다 — 서버 메트릭과 함께.
- 출시 전 한 번 — 정기 회귀로.
- JMeter로 모든 걸 한다 — 영역별로 도구를.
- 분산 안 짜고 단일 노드로 무리 — 도구 한계 ≠ 시스템 한계.
- warm-up 무시 — 초반 데이터가 결론을 왜곡.
- error rate 누락 — 죽은 요청을 못 본다.
다음 글 예고
다음 글 후보: production에서 신호와 노이즈 — RED·USE·SLO 대시보드 설계, chaos engineering 2026 — Litmus·Chaos Mesh·Gremlin·AWS FIS 비교, performance regression CI — 한 줄에서 분포까지.
"측정 가능한 것이 개선 가능한 것이다. 그리고 분포를 보지 않으면 측정이 아니다."
— 로드/성능 테스트 도구 2026, 끝.
참고 / References
- k6 — Grafana Labs
- k6 GitHub — grafana/k6
- k6 Documentation
- k6 Cloud Pricing — Grafana Cloud k6
- k6 Operator — grafana/k6-operator
- k6 browser module
- Locust — Python load testing
- Locust GitHub — locustio/locust
- Locust Documentation
- Vegeta GitHub — tsenart/vegeta
- Gatling — Open source load testing
- Gatling GitHub — gatling/gatling
- Artillery — Cloud-scale load testing
- Artillery GitHub — artilleryio/artillery
- Apache JMeter
- wrk GitHub — wg/wrk
- wrk2 GitHub — giltene/wrk2
- autocannon — Node.js HTTP benchmark
- Bombardier — Go HTTP benchmark
- ghz — gRPC benchmarking
- fortio — load testing library and tool
- BlazeMeter — Performance testing platform
- Coordinated Omission — Gil Tene
- Google SRE Book — Monitoring distributed systems
- Brendan Gregg — USE Method