API가 "N개의 스레드가 가능한 한 빠르게 요청을 퍼붓는 것"이 아니라, 정확히 초당 500개의 요청에서 어떻게 동작하는지 알고 싶을 것입니다. 대부분의 부하 테스트 도구는 동시성을 고정하고 요청률을 자유롭게 합니다. Vegeta는 그 반대입니다. 요청률을 설정하면 서버 응답 방식에 관계없이 초당 해당 수의 요청을 보냅니다. 이 차이는 답안지가 사용하는 숫자, 즉 목표 부하에서의 처리량, 그리고 SLO에서 실제로 약속할 수 있는 지연 시간에 관심이 있을 때 중요합니다.
Vegeta란 무엇인가
Vegeta는 Go로 작성된 명령줄 HTTP 부하 테스트 도구입니다. Go 라이브러리로도 사용할 수 있지만, 이 튜토리얼에서는 CLI에 집중합니다. 핵심 아이디어는 일정한 요청률입니다. Vegeta에게 "30초 동안 초당 100개의 요청을 보내라"고 지시하면, 필요에 따라 워커를 추가하여 이 속도를 유지합니다. 서버가 느려지더라도 Vegeta는 이전 요청이 완료될 때까지 기다리지 않고 정해진 일정에 따라 새 요청을 계속 발행합니다.
이러한 설계는 개방형 부하 테스트 모델을 제공합니다. 실제 트래픽은 고유한 시간대에 도착합니다. 사용자는 다음 사용자가 나타나기 전에 느린 엔드포인트를 기다리지 않습니다. 속도 기반 도구는 이러한 동작과 일치합니다.
속도 기반 vs 동시성 기반 부하
다음은 사람들이 혼란스러워하는 부분입니다.
동시성 기반 도구(고정된 스레드 또는 가상 사용자 풀, 각각 요청-응답을 반복)는 폐쇄형 모델을 사용합니다. 서버가 느려지면 루프가 멈추므로 실제 요청률이 떨어집니다. 부하를 요청했지만 도구가 조용히 후퇴한 것입니다. 이는 프로덕션에서 발생할 수 있는 병목 현상을 숨깁니다.
Vegeta와 같은 속도 기반 도구는 개방형 모델을 사용합니다. 도착률을 고정합니다. 서버가 따라잡지 못하면 요청이 대기열에 쌓이고, 지연 시간이 증가하며, 보고서에 표시됩니다. 수요가 용량을 초과할 때 발생하는 상황에 대한 솔직한 그림을 얻을 수 있습니다.
두 모델 모두 틀린 것은 아닙니다. "동시에 몇 명의 사용자를 수용할 수 있는가"를 알고 싶을 때는 동시성을 사용하십시오. "초당 2,000개의 요청에서 무슨 일이 발생하는가"를 알고 싶을 때는 속도 모델을 사용하십시오. Vegeta는 두 번째 종류입니다. 도구 공간에 대한 더 넓은 지도는 주요 API 부하 테스트 도구를 참조하십시오.
Vegeta 설치
설치 환경에 맞는 것을 선택하십시오.
macOS의 Homebrew:
brew update && brew install vegeta
다른 패키지 관리자:
# MacPorts
port install vegeta
# Arch Linux
pacman -S vegeta
# FreeBSD
pkg install vegeta
Go가 설치된 상태에서 소스에서 빌드:
git clone https://github.com/tsenart/vegeta
cd vegeta
make vegeta
GitHub 릴리스 페이지에서 미리 빌드된 바이너리를 다운로드할 수도 있습니다. 설치 확인:
vegeta --help
핵심 파이프라인
Vegeta는 Unix 파이프를 중심으로 구축되었습니다. 타겟이 입력되고, 공격이 실행되며, 보고서가 출력됩니다. 가장 작은 유용한 실행은 한 줄입니다:
echo "GET http://localhost:8080/" | vegeta attack -duration=5s -rate=100 | vegeta report
왼쪽에서 오른쪽으로 읽어보면:
echo는 하나의 타겟(메서드와 URL)을 표준 출력으로 씁니다.vegeta attack은 표준 입력에서 해당 타겟을 읽어 5초 동안 초당 100개의 요청을 발사합니다. 총 500개의 요청입니다.vegeta report는 이진 결과 스트림을 읽고 요약을 출력합니다.
-rate 플래그는 시간 단위당 요청 수를 받습니다. -rate=100과 -rate=100/1s는 같은 의미입니다. -rate=50/500ms는 500밀리초마다 50개의 요청을 의미합니다. -rate=0으로 설정하면 제한이 제거되고 가능한 한 빨리 전송되며, 이는 완전히 다른 테스트입니다.
텍스트 보고서는 다음과 같습니다:
Requests [total, rate, throughput] 500, 100.20, 100.18
Duration [total, attack, wait] 4.991s, 4.990s, 1.2ms
Latencies [min, mean, 50, 90, 95, 99, max] 412us, 1.3ms, 1.1ms, 1.9ms, 2.4ms, 5.1ms, 12ms
Bytes In [total, mean] 128500, 257.00
Bytes Out [total, mean] 0, 0.00
Success [ratio] 100.00%
Status Codes [code:count] 200:500
Error Set:
먼저 지연 시간 줄을 읽으십시오. 50열은 중간값(median)입니다. 99열은 꼬리 부분(tail)입니다: 요청의 1%가 이보다 느렸습니다. 꼬리 부분은 사용자가 고통을 느끼는 부분이며, 따라서 평균은 양호해도 99번째 백분위수가 좋지 않다면 여전히 문제입니다. 다음으로 Success [ratio]와 Status Codes를 확인하십시오. 100% 성공률과 모든 200 응답은 서버가 부하를 견뎠음을 의미합니다. 5xx 코드나 비어있지 않은 Error Set은 서버가 오류를 일으키기 시작했음을 의미합니다.
결과를 저장하고 다양한 방식으로 보고
빠른 확인을 위해 report로 직접 파이프하는 것은 좋습니다. 다시 검토할 모든 것들을 위해, 먼저 원본 결과를 파일에 저장한 다음, 해당 파일에서 원하는 모든 보고서를 생성하십시오.
echo "GET http://localhost:8080/" | \
vegeta attack -duration=10s -rate=200 -output=results.bin
이제 실행 결과가 results.bin에 캡처되었습니다. 텍스트 보고서를 생성합니다:
vegeta report results.bin
대시보드 또는 실행 간의 차이 비교를 위한 구조화된 JSON을 생성합니다:
vegeta report -type=json results.bin > metrics.json
선택한 버킷으로 지연 시간 히스토그램을 생성합니다:
vegeta report -type='hist[0,2ms,5ms,10ms,25ms,100ms]' results.bin
히스토그램은 각 지연 시간 구간에 몇 개의 요청이 속하는지 계산합니다. 지연 시간이 밀집되어 있는지 또는 넓은 범위에 걸쳐 퍼져 있는지 빠르게 확인할 수 있는 방법입니다.
타겟 파일 형식
실제 API는 하나 이상의 GET 요청이 필요합니다. 타겟을 파일로 옮기고 -targets로 전달하십시오. 기본 HTTP 형식은 줄 기반이며 읽기 쉽습니다.
targets.txt 생성:
GET http://localhost:8080/api/users
POST http://localhost:8080/api/users
Content-Type: application/json
@./payload.json
GET http://localhost:8080/api/users/42
몇 가지 규칙이 작동하게 합니다:
- 각 타겟의 첫 번째 줄은
METHOD URL입니다. - 헤더 줄은 메서드 줄 바로 아래에 오며, 한 줄에 하나씩
Key: Value형식입니다. @으로 시작하는 줄은 해당 파일의 내용이 요청 본문이 됨을 나타냅니다.- 빈 줄은 하나의 타겟을 다음 타겟과 구분합니다.
#으로 시작하는 줄은 주석입니다.
JSON 본문을 payload.json에 넣으십시오:
{ "name": "Ada", "role": "engineer" }
파일을 대상으로 공격 실행:
vegeta attack -targets=targets.txt -rate=50 -duration=30s | vegeta report
Vegeta는 타겟을 순서대로 순환하며, 기간이 끝날 때까지 계속 반복합니다. -header를 사용하여 명령줄에서 전역 헤더를 추가할 수도 있습니다. 이는 인증에 유용합니다:
vegeta attack -targets=targets.txt -rate=50 -duration=30s \
-header="Authorization: Bearer $TOKEN" | vegeta report
프로그래밍 방식 또는 대량 실행의 경우, Vegeta는 JSON 타겟 형식도 읽습니다. 각 줄은 하나의 JSON 객체이며, -format=json으로 선택합니다:
{"method": "GET", "url": "http://localhost:8080/api/users"}
{"method": "POST", "url": "http://localhost:8080/api/users", "header": {"Content-Type": ["application/json"]}, "body": "eyJuYW1lIjoiQWRhIn0="}
body 필드는 base64로 인코딩됩니다. 이 형식은 스트리밍에 적합하므로, -lazy를 사용하여 메모리 효율성을 위해 실시간으로 타겟을 생성하고 직접 파이프할 수 있습니다.
플롯 및 히스토그램
단일 숫자는 추세를 숨깁니다. 실행 중간에 지연 시간이 저하되면 곡선을 보고 싶을 것입니다. Vegeta의 plot 명령은 결과 스트림을 대화형 HTML 페이지로 변환합니다:
vegeta attack -targets=targets.txt -rate=100 -duration=60s | \
vegeta plot > plot.html
브라우저에서 plot.html을 엽니다. 실행 전반에 걸친 지연 시간의 시계열 차트가 표시되므로 느린 상승 또는 중간 테스트 스파이크가 명확하게 드러납니다. 여러 실행을 함께 플로팅하여 부하 수준을 비교할 수 있습니다:
vegeta attack -rate=50 -duration=30s -targets=targets.txt -output=50qps.bin
vegeta attack -rate=100 -duration=30s -targets=targets.txt -output=100qps.bin
vegeta plot 50qps.bin 100qps.bin > compare.html
헤드리스 환경의 경우, 플롯을 건너뛰고 encode를 사용하여 히스토그램 또는 원본 CSV를 내보낼 수 있습니다:
vegeta encode -to=csv results.bin > results.csv
Vegeta를 사용할 때
속도와 용량에 대한 질문이 있을 때 Vegeta를 사용하십시오:
- 특정 초당 요청 목표에서 처리량과 지연 시간이 필요할 때.
- 지연 시간 또는 오류율이 증가하기 시작하는 속도를 찾고 싶을 때.
- 동일하고 반복 가능한 부하에서 두 빌드 또는 두 인프라 구성을 비교할 때.
- GUI 없이 쉘 파이프라인 및 CI 작업에 통합될 수 있는 스크립트 가능한 도구를 원할 때.
이는 집중된 도구입니다. HTTP 요청을 특정 속도로 보내고 서버가 어떻게 응답하는지 측정합니다. 분기 로직을 사용하여 다단계 사용자 여정을 스크립트하지 않으며, 상태 코드 외에 응답 본문을 검증하지도 않습니다. 이러한 집중은 기능입니다. 도구를 작게 유지하고 결과를 깔끔하게 만듭니다.
다른 도구와 비교할 때, k6 부하 테스트 및 JMeter 부하 테스트의 비교는 동시성 모델 대안을 다룹니다. 기본 개념 및 메트릭에 대해서는 API 성능 테스트 튜토리얼이 좋은 입문서입니다.
기능 테스트가 적합한 경우
부하 테스트는 "충분히 빠른가"에 답합니다. "올바른가"에는 답하지 않습니다. Vegeta 실행은 100% 200 응답을 보고할 수 있지만, 엔드포인트가 잘못된 사용자, 오래된 가격 또는 잘못된 형식의 JSON 필드를 반환할 수도 있습니다. 부하 도구의 관점에서 이러한 응답은 모두 빠르고 성공적인 200 응답입니다.
정확성에는 다른 검사가 필요합니다: 응답 본문, 스키마 및 비즈니스 규칙에 대한 어설션. 이것이 기능 테스트이며, 부하 실행 전후와 함께 수행되어야 합니다. 건전한 패턴은 API가 올바른지 검증한 다음, 특정 속도에서 어떻게 수행되는지 측정하는 것입니다.
이것이 Apidog가 Vegeta와 경쟁하기보다는 보완하는 부분입니다. Apidog에서는 상태, 헤더 및 JSON 필드에 대한 시각적 어설션으로 테스트 시나리오를 구축하고, 요청을 연결하고, 데이터 파일에서 구동합니다. API가 올바른 데이터를 반환하는지 확인합니다. 그런 다음 Vegeta는 올바른 경로가 초당 수백 번 호출될 때도 빠르게 유지되는지 확인합니다. 두 가지 도구, 두 가지 질문입니다.
Apidog는 또한 헤드리스 CLI를 제공하므로 이러한 기능 시나리오가 부하 단계와 동일한 CI 파이프라인에서 실행됩니다. Node로 설치합니다:
npm install -g apidog-cli
그런 다음 파이프라인을 위한 리포터와 함께 ID로 저장된 시나리오 또는 스위트를 실행합니다:
apidog run --access-token "$APIDOG_ACCESS_TOKEN" \
-t <scenarioOrSuiteId> \
-e <environmentId> \
-r cli,html,junit
-t 플래그는 시나리오, 폴더 또는 스위트 ID를, -e는 환경 ID를, -r은 하나 이상의 리포터(cli, html, json, junit)를 선택합니다. junit 출력은 대부분의 CI 대시보드에 적합합니다. 단계별 실행에 대해서는 Apidog CLI 명령줄 튜토리얼을, 복사-붙여넣기 워크플로에 대해서는 CI/CD 파이프라인 가이드를 참조하십시오. 기능 게이트를 먼저 실행한 다음, 통과한 엔드포인트의 성능을 Vegeta로 측정하십시오.
FAQ
Vegeta는 본문이 있는 POST 요청을 지원하나요?
네. HTTP 타겟 파일에서 첫 줄에 메서드와 URL을 넣고, Content-Type 헤더를 추가한 다음, @./payload.json으로 본문 파일을 참조하십시오. JSON 형식에서는 method, url, base64로 인코딩된 body 필드를 설정하십시오.
-rate=0은 무엇을 하나요?
속도 제한을 제거하고 워커와 연결이 허용하는 한 빠르게 요청을 보냅니다. 이는 최대 처리량 테스트이며, 제어된 일정 속도 테스트와는 다릅니다. 반복 가능한 용량 측정을 위해서는 명시적인 속도를 설정하십시오.
지연 시간 백분위수는 어떻게 읽어야 하나요?
보고서의 지연 시간 줄은 최소값, 평균, 50번째, 90번째, 95번째, 99번째 및 최대 백분위수를 보여줍니다. 95번째와 99번째에 집중하십시오. 이는 실제 사용자가 겪는 느린 꼬리 부분을 설명하며, 평균만으로는 숨겨질 수 있습니다.
Vegeta가 내 API가 올바른 데이터를 반환하는지 확인할 수 있나요?
아니요. 처리량, 지연 시간 및 상태 코드를 측정합니다. 응답 본문이나 스키마에 대한 어설션은 하지 않습니다. 정확성을 위해서는 기능 테스트 도구와 함께 사용하고, 속도와 지연 시간 측정에는 Vegeta를 사용하십시오.
CI에서 Vegeta를 어떻게 실행하나요?
표준 입력을 읽고 결과를 쓰는 단일 바이너리이므로 모든 쉘 단계에 쉽게 통합됩니다. -output으로 결과를 저장한 다음, 빌드 아티팩트로 텍스트 또는 JSON 보고서를 생성하십시오. 부하 단계 이전에 Apidog CLI와 같은 기능 게이트를 추가하여 어설션을 이미 통과한 엔드포인트만 측정하도록 하십시오.
