K6 소개
목차
부하·성능 테스트 도구 K6 소개
1. k6란?
k6는 서버·API·시스템의 부하 테스트, 스트레스 테스트, 성능 검증을 수행하기 위한 오픈소스 도구입니다. 트래픽을 코드 기반으로 시뮬레이션할 수 있어 이해하고 유지하기 쉬운 테스트 환경을 제공합니다.
특징 요약
- JavaScript로 테스트 시나리오 작성
- 테스트를 코드처럼 관리(Git PR 리뷰·버전 관리 가능)
- 요청량, 가중치, 세션 흐름 등 실제 사용 패턴 시뮬레이션 가능
- 운영 환경에서 확인하는 지표(지연 시간, 에러율, 처리량 등)를 테스트 단계에서 확인 가능
2. K6 장점
테스트를 코드로 정의하는 방식이기 때문에 다음과 같은 장점이 있습니다.
| 장점 | 설명 |
|---|---|
| 명확성 | 테스트 의도가 코드에 그대로 표현됨 |
| 재현성 | 같은 코드라면 항상 동일한 테스트 결과 |
| 수정 용이성 | API 스펙 변경 시 코드만 고치면 반영 |
| 기록·이력 | 테스트 변경 이력을 Git으로 추적 가능 |
| 확장성 | 테스트가 많아져도 구조 유지 가능 |
즉, 테스트를 개발 프로세스 안으로 자연스럽게 가져올 수 있는 도구입니다.
3. 핵심 개념
| 용어 | 설명 |
|---|---|
| VU (Virtual User) | 동시에 실행되는 가상 사용자 |
| iteration | VU가 default()를 1회 수행한 횟수 |
| scenario | 부하 패턴 정의 (예: TPS 유지, 단계적 증가 등) |
| threshold | 목표 성능 기준 (예: p95<1500ms, 실패율<1%) |
| tags | 요청 라벨링 (엔드포인트별 통계 분석 목적) |
4. 스크립트 구조 예제
import http from 'k6/http';
import { check, sleep } from 'k6';
/**
* 기본 설정
* - BASE_URL : 요청을 보낼 대상 서버 (환경 변수로 덮어쓰기 가능)
* - RATE : 초당 요청 수(TPS). 미설정 시 100 TPS
* - TEST_DURATION : 테스트 수행 시간. 미설정 시 24h
*/
//const BASE_URL = __ENV.BASE_URL || 'http://10.0.1.8:24002';
const BASE_URL = __ENV.BASE_URL || 'http://127.0.0.1:24002'; // ← 기본값
const RATE = __ENV.RATE ? Number(__ENV.RATE) : 30;
const TEST_DURATION = __ENV.TEST_DURATION || '10m';
//const TEST_DURATION = __ENV.TEST_DURATION || '24h';
// 불규칙 트래픽을 만들기 위한 API 경로와 가중치
// 예: orders 호출이 가장 빈번, shipments는 가장 드묾
const API_WEIGHTS = [
{ path: '/api/spans/orders', weight: 4 },
{ path: '/api/spans/payments', weight: 4 },
{ path: '/api/spans/shipments', weight: 2 },
];
/**
* 가중치 기반 랜덤 API 선택
* - weight 합을 기준으로 0 ~ totalWeight 사이 난수를 뽑아서
* 해당 구간에 걸리는 path를 선택
*/
function pickRandomApi() {
const totalWeight = API_WEIGHTS.reduce((sum, item) => sum + item.weight, 0);
let rand = Math.random() * totalWeight;
for (const item of API_WEIGHTS) {
if (rand < item.weight) {
return item.path;
}
rand -= item.weight;
}
// 방어적 코드: 논리상 이 지점은 오지 않아야 하지만,
// 예외 상황 대비하여 첫 번째 항목을 반환
return API_WEIGHTS[0].path;
}
/**
* VU별로 유지되는 traceId
* - 각 VU마다 별도 값
* - default() 안에서 확률적으로 갱신
*/
let currentTraceId = `${__VU}-${Date.now()}`;
/**
* k6 옵션
* - executor: constant-arrival-rate
* → 시나리오 전체 기준으로 RATE 값만큼 초당 iteration 실행 시도
* - rate : 목표 TPS (초당 요청 수)
* - timeUnit : rate 기준 단위 (1초)
* - duration : 전체 테스트 시간
*
* preAllocatedVUs / maxVUs
* - 응답 시간에 따라 필요한 동시 VU 수가 달라질 수 있으므로
* 여유 있게 설정
*/
export const options = {
scenarios: {
span_scenario: {
executor: 'constant-arrival-rate',
rate: RATE, // 목표 TPS (기본 100)
timeUnit: '1s',
duration: TEST_DURATION, // 기본 24h, 필요 시 환경 변수로 조정
// 초기에 확보할 VU 수
preAllocatedVUs: 50,
// 최대 허용 VU 수 (TPS가 안 나오면 이 값을 더 늘려볼 수 있음)
maxVUs: 200,
},
},
thresholds: {
// 95퍼센타일 응답 시간 1.5초 미만
http_req_duration: ['p(95)<1500'],
// 실패율 1% 미만
http_req_failed: ['rate<0.01'],
},
};
export default function () {
// 30% 확률로 traceId 변경 → 일정 기간 동안 동일 traceId로 묶인 요청 유지
if (Math.random() < 0.3) {
currentTraceId = `${__VU}-${Date.now()}`;
}
const path = pickRandomApi();
const res = http.get(`${BASE_URL}${path}`, {
headers: {
// 백엔드/APM에서 추적용으로 사용할 커스텀 헤더
'x-trace-id': currentTraceId,
},
tags: {
// k6 메트릭(예: http_reqs)에 endpoint 태그가 붙도록 설정
endpoint: path,
},
});
// 엔드포인트별 상태 코드 검증
check(res, {
[`${path} status is 200`]: (r) => r.status === 200,
});
/**
* iteration 사이에 약간의 지터 추가 (0 ~ 300ms)
*
* executor가 constant-arrival-rate 이기 때문에
* 전체 TPS는 rate에 의해 제어되고,
* 이 sleep은 개별 VU들의 타이밍을 살짝 어긋나게 만들어
* 완전히 규칙적인 패턴을 피하는 정도의 역할만 수행한다.
*/
sleep(Math.random() * 0.3);
}5. 실행 방법
기본 실행
k6 run span-load.js결과 예시

서버 주소 / TPS / 테스트 시간 조정
k6 run span-load.js \
-e BASE_URL=http://10.0.1.8:24002 \
-e RATE=50 \
-e TEST_DURATION=30m실행 결과로 확인 가능한 항목
- p95 / p99 지연 시간
- 성공/실패 요청 수
- 초당 처리량(TPS)
- 응답 시간 분포
- VU 사용량 변화
6. 테스트 결과 활용
테스트 결과는 다음과 같이 활용할 수 있습니다.
- 지연이 발생하는 API/엔드포인트 확인
- TPS 증가 시 어느 시점에서 응답이 느려지는지 확인
- 에러가 많이 발생하는 상황 파악
- 병목 구간 추적(백엔드/DB/외부 연동 등)
- 배포 후 성능 비교
7. 운영 환경에서의 활용 시나리오
| 상황 | 사용 예 |
|---|---|
| 신규 기능 출시 전 | API 처리 시간/에러율 점검 |
| 성능 최적화 이후 | 개선 전후 응답 시간 비교 |
| 장애 재현 | 대량 트래픽 유입 조건에서 오류 발생 패턴 확인 |
| 확장성 검증 | TPS 상승 시 서비스가 견딜 수 있는 선 파악 |
| 스케일링 테스트 | 부하 증가 시 인프라 반응 확인 |
8. JMeter vs k6 비교
우리 회사에서는 기존에 Apache JMeter를 사용하고 있습니다. k6는 JMeter를 대체한다기보다, 개발자가 테스트를 유지하고 협업하기 좋은 방식을 추가할 수 있습니다.
| 항목 | JMeter | k6 |
|---|---|---|
| 테스트 작성 | GUI 기반 설정 | JavaScript 기반 코드 |
| 협업 | 파일 공유 중심 | 코드 리뷰·PR 가능 |
| 재현성 | 설정 누락/버전 차이 발생 가능 | 코드 그대로 실행되면 동일 결과 |
| 유지 보수 | 테스트 많아지면 복잡해짐 | 코드 구조로 관리 |
| 트래픽 재현 | 반복 호출 중심 | 실제 사용 패턴 반영 용이 |
| 고부하 테스트 | 자원 사용량 많음 | 경량 실행 |
우리 회사 입장에서의 장점
- 개발자가 테스트를 직접 버전 관리
- 테스트 변경 이력이 명확
- API 변경 시 코드만 수정하면 반영
- 실제 서비스 흐름 기반 트래픽 시뮬레이션 가능