프롤로그 — "초당 만 건 가능합니다"라는 거짓말
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가지 목적 — 무엇을 잴 건지부터
도구를 고르기 전에 **목적**부터 정리한다. 같은 도구가 모든 목적에 맞지 않는다.
1. **마이크로 벤치마크 (micro-benchmark)** — 단일 엔드포인트의 한계 throughput과 p99 latency를 잰다. "이 핫 패스가 얼마나 빠른가?" 작은 변경의 회귀를 잡는 용도. wrk, autocannon, Bombardier, Vegeta.
2. **부하 테스트 (load test)** — 예상 트래픽 수준에서 시스템이 SLO 안에서 동작하는가. 보통 일정 RPS를 일정 시간 유지. k6, Locust, Gatling, Artillery, JMeter.
3. **스트레스 테스트 (stress test)** — 한계를 찾는다. 어느 지점에서 시스템이 무너지는가, 어떻게 무너지는가, 회복 가능한가. 위 도구들 + 시나리오 설계.
4. **스파이크/소크 테스트 (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
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개 항목 체크리스트
1. 목적이 명확한가 (마이크로/부하/스트레스/스파이크 중)?
2. production-like 데이터를 쓰는가?
3. constant rate 말고 분포·ramp를 모델링했는가?
4. warm-up 구간을 측정에서 제외했는가?
5. p99(또는 p999)를 SLO에 연결했는가?
6. error rate를 latency와 분리해서 보았는가?
7. 클라이언트 측 + 서버 측 메트릭을 같이 보았는가?
8. CI에 회귀로 들어가 있는가?
9. 분산이 필요할 때 self-host/cloud 결정을 내렸는가?
10. 비-HTTP 프로토콜이 있다면 그 도구를 함께 쓰는가 (gRPC/WS/브라우저)?
11. 측정 경로가 user path와 일치하는가 (DNS·CDN 포함)?
12. coordinated omission 보정을 이해하고 있는가?
안티패턴 10가지
1. 평균 latency만 본다 — p99를 보라.
2. constant rate 한 번으로 통과 선언 — 분포를 모델링.
3. localhost에서 측정 후 결론 — 네트워크가 없다.
4. production에서 직접 부하 — staging에서.
5. 부하 도구만 본다 — 서버 메트릭과 함께.
6. 출시 전 한 번 — 정기 회귀로.
7. JMeter로 모든 걸 한다 — 영역별로 도구를.
8. 분산 안 짜고 단일 노드로 무리 — 도구 한계 ≠ 시스템 한계.
9. warm-up 무시 — 초반 데이터가 결론을 왜곡.
10. error rate 누락 — 죽은 요청을 못 본다.
다음 글 예고
다음 글 후보: **production에서 신호와 노이즈 — RED·USE·SLO 대시보드 설계**, **chaos engineering 2026 — Litmus·Chaos Mesh·Gremlin·AWS FIS 비교**, **performance regression CI — 한 줄에서 분포까지**.
> "측정 가능한 것이 개선 가능한 것이다. 그리고 분포를 보지 않으면 측정이 아니다."
— 로드/성능 테스트 도구 2026, 끝.
참고 / References
- [k6 — Grafana Labs](https://k6.io/)
- [k6 GitHub — grafana/k6](https://github.com/grafana/k6)
- [k6 Documentation](https://grafana.com/docs/k6/latest/)
- [k6 Cloud Pricing — Grafana Cloud k6](https://grafana.com/products/cloud/k6/)
- [k6 Operator — grafana/k6-operator](https://github.com/grafana/k6-operator)
- [k6 browser module](https://grafana.com/docs/k6/latest/using-k6-browser/)
- [Locust — Python load testing](https://locust.io/)
- [Locust GitHub — locustio/locust](https://github.com/locustio/locust)
- [Locust Documentation](https://docs.locust.io/)
- [Vegeta GitHub — tsenart/vegeta](https://github.com/tsenart/vegeta)
- [Gatling — Open source load testing](https://gatling.io/)
- [Gatling GitHub — gatling/gatling](https://github.com/gatling/gatling)
- [Artillery — Cloud-scale load testing](https://www.artillery.io/)
- [Artillery GitHub — artilleryio/artillery](https://github.com/artilleryio/artillery)
- [Apache JMeter](https://jmeter.apache.org/)
- [wrk GitHub — wg/wrk](https://github.com/wg/wrk)
- [wrk2 GitHub — giltene/wrk2](https://github.com/giltene/wrk2)
- [autocannon — Node.js HTTP benchmark](https://github.com/mcollina/autocannon)
- [Bombardier — Go HTTP benchmark](https://github.com/codesenberg/bombardier)
- [ghz — gRPC benchmarking](https://ghz.sh/)
- [fortio — load testing library and tool](https://fortio.org/)
- [BlazeMeter — Performance testing platform](https://www.blazemeter.com/)
- [Coordinated Omission — Gil Tene](https://highscalability.com/your-load-generator-is-probably-lying-to-you-take-the-red-pi/)
- [Google SRE Book — Monitoring distributed systems](https://sre.google/sre-book/monitoring-distributed-systems/)
- [Brendan Gregg — USE Method](https://www.brendangregg.com/usemethod.html)
현재 단락 (1/313)
2026년 어느 회사의 출시 전날.