Skip to content

필사 모드: 로드/성능 테스트 도구 2026 — k6·Locust·Vegeta·Gatling·Artillery·JMeter 심층 비교 (JMeter 너머의 풍경)

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — "초당 만 건 가능합니다"라는 거짓말

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년 어느 회사의 출시 전날.

작성 글자: 0원문 글자: 14,194작성 단락: 0/313