Grafana k6는 JavaScript로 작성하는 현대적인 오픈소스 부하 테스트 도구입니다. 개발자 친화적인 CLI, 강력한 메트릭, 손쉬운 CI/CD 통합으로 빠르게 성능 테스트를 구축할 수 있습니다.
Grafana k6는 개발자가 JavaScript로 부하 테스트 스크립트를 작성하는 오픈소스 성능 테스트 도구입니다. Go 언어로 구현되어 단일 머신에서도 수만 명의 가상 사용자(VU)를 시뮬레이션할 수 있습니다.
| 특징 | 설명 |
|---|---|
| JavaScript 스크립트 | 익숙한 JS로 테스트 시나리오 작성 |
| 고성능 | Go 기반 엔진, 낮은 리소스 사용 |
| CLI 중심 | CI/CD 파이프라인에 자연스럽게 통합 |
| 풍부한 메트릭 | 응답 시간, 에러율, 처리량 등 자동 수집 |
brew install k6sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6docker pull grafana/k6
docker run --rm -i grafana/k6 run - < script.jschoco install k6import http from 'k6/http';
import { sleep, check } from 'k6';
export const options = {
vus: 10, // 가상 사용자 수
duration: '30s', // 테스트 시간
};
export default function () {
const res = http.get('https://httpbin.test.k6.io/');
check(res, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}k6 run script.jshttpbin.test.k6.io는 k6 공식 테스트 서버입니다. 자신의 서버 주소로 변경하세요.
VU(Virtual User)는 실제 사용자를 모방하는 가상의 스레드입니다. 각 VU는 독립적으로 스크립트를 실행하며 쿠키와 세션을 유지합니다.
각 VU가 export default function()을 실행하는 횟수입니다. duration이 지나거나 iterations에 도달하면 테스트가 종료됩니다.
| 메트릭 | 설명 |
|---|---|
http_req_duration | 요청 전체 응답 시간 |
http_req_failed | 실패율 (4xx, 5xx) |
vus | 현재 활성 VU 수 |
iterations | 완료된 반복 횟수 |
정상 또는 예상 최대 부하에서 시스템 성능을 확인합니다.
export const options = {
stages: [
{ duration: '2m', target: 100 }, // 100 VU까지 증가
{ duration: '5m', target: 100 }, // 100 VU 유지
{ duration: '2m', target: 0 }, // 0으로 감소
],
};시스템 한계점을 찾기 위해 점진적으로 부하를 증가시킵니다.
export const options = {
stages: [
{ duration: '2m', target: 100 },
{ duration: '5m', target: 100 },
{ duration: '2m', target: 200 },
{ duration: '5m', target: 200 },
{ duration: '2m', target: 300 },
{ duration: '5m', target: 300 },
{ duration: '10m', target: 0 },
],
};갑작스러운 트래픽 폭증 상황을 시뮬레이션합니다.
export const options = {
stages: [
{ duration: '10s', target: 100 },
{ duration: '1m', target: 100 },
{ duration: '10s', target: 1400 }, // 스파이크!
{ duration: '3m', target: 1400 },
{ duration: '10s', target: 100 },
{ duration: '3m', target: 100 },
{ duration: '10s', target: 0 },
],
};import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
thresholds: {
'http_req_duration': ['p(95)<500'], // 95%ile < 500ms
'http_req_failed': ['rate<0.01'], // 에러율 1% 미만
'checks': ['rate>0.99'], // check 성공률 99% 이상
},
};
export default function () {
const res = http.get('https://your-api.com/health');
check(res, {
'status 200': (r) => r.status === 200,
'body not empty': (r) => r.body.length > 0,
'fast response': (r) => r.timings.duration < 200,
});
sleep(1);
}Threshold 기준을 만족하지 못하면 k6가 exit code 99로 종료됩니다. CI/CD에서 이를 실패로 처리할 수 있습니다.
import http from 'k6/http';
export default function () {
// GET
http.get('https://api.example.com/users');
// POST (JSON)
const payload = JSON.stringify({ username: 'user1', password: 'secret' });
const params = { headers: { 'Content-Type': 'application/json' } };
const loginRes = http.post('https://api.example.com/login', payload, params);
// Authorization header
const token = loginRes.json('token');
http.get('https://api.example.com/profile', {
headers: { Authorization: `Bearer ${token}` },
});
}# JSON 출력
k6 run --out json=result.json script.js
# CSV 출력
k6 run --out csv=result.csv script.js
# Grafana Cloud로 스트리밍
k6 run --out cloud script.jsname: Load Test
on: [push]
jobs:
k6-load-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: grafana/setup-k6-action@v1
- run: k6 run scripts/load-test.js
env:
K6_CLOUD_TOKEN: ${{ secrets.K6_CLOUD_TOKEN }}