k6가 진짜 빠른가?
아키텍처와 실행 방식의 효율성
k6가 다른 부하 테스트 도구보다 빠르다?
k6가 다른 부하 테스트 도구보다 빠르다고 평가받는 주요 이유는 아키텍처와 실행 방식의 효율성에 있습니다. 어떨때 빠른지 학습해보며 실제 POC까지 진행해보겠습니다.
Go 언어 기반의 고성능 런타임
- k6는 Go 언어로 작성되어 있으며, 이는 C 수준의 성능과 경량성을 갖춘 언어입니다.
- Go는 가벼운 고루틴(goroutine)을 통해 수천 개의 동시 작업을 효율적으로 처리할 수 있습니다.
- 결과적으로, 적은 리소스로 더 많은 가상 사용자를 실행할 수 있어 고성능 테스트가 가능합니다.
JMeter는 Java 기반으로 무겁고, 쓰레드 기반의 가상 사용자 모델이 메모리와 CPU 자원을 많이 사용합니다.
싱글 바이너리 구조
- k6는 하나의 독립 실행형 바이너리로 구성되어 있어 설치와 실행이 매우 가볍습니다.
- 외부 의존성이 없으며, 불필요한 JVM 초기화 등도 없습니다.
가상 사용자(VU) 모델의 효율성
- k6는 VU를 고루틴 기반으로 처리하여 스레드 오버헤드 없이 수천~수만 명의 동시 사용자를 시뮬레이션할 수 있습니다.
- 자바 기반 도구는 스레드 기반이기 때문에 메모리 한계에 빠르게 도달하는 경향이 있습니다.
JavaScript 기반 스크립트로 유연성 제공
- k6는 VU 스크립트를 JavaScript(ES6 기반)로 작성합니다.
- 러닝커브가 낮고, 테스트 흐름을 직관적으로 구성할 수 있습니다.
- 성능도 높은 수준에서 유지됩니다. (Go 기반으로 실행되므로 JS 인터프리터가 무겁지 않음)
CLI 중심, Headless 실행 최적화
- GUI 없이 CLI에서 빠르게 실행되도록 설계되어, 서버 환경에서의 자동화 및 CI/CD 통합에 최적화되어 있습니다.
- 테스트 결과를 JSON, InfluxDB, Grafana 등 다양한 포맷으로 실시간 전송할 수 있어 실시간 모니터링 성능도 우수합니다.
멀티코어 활용 최적화
- Go 언어의 특징으로, k6는 시스템의 멀티코어를 잘 활용하여 성능 병목 없이 고부하 테스트를 실행할 수 있습니다.
실험
- 목적: 동일 머신, 동일 대상 서버에 대해 VU 1명으로 초당 요청 수(RPS)를 얼마나 낼 수 있는지 측정
- 대상: 가능한 한 응답이 빠른 테스트 서버를 사용해야 성능 측정에 부하가 적습니다. 예: http://localhost:8080/ping 또는 nginx 등 경량 웹서버
테스트 환경 구성
- 동일 머신에서 k6와 Locust를 각각 실행
- 타겟 서버는 로컬에 두거나, 동일 조건의 네트워크 환경에서 유지
- 머신 사양: m4 mac
- GET http://localhost:8080/
- 1분동안 vu1일 때, rps 지표 확인
- 1분동안 vu100일 때, rps 지표 확인
nginx 세팅
1
2
docker run --name nginx-test -d -p 8080:80 nginx
curl localhost:8080
k6 스크립트 세팅 및 실행
1
2
3
4
5
6
7
8
9
10
11
12
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
vus: 1,
duration: '1m',
};
export default function () {
http.get('http://localhost:8080');
// sleep(0); // 최대한 많은 요청을 보내기 위해 sleep 없음
}
1
k6 run script.js
locust 스크립트 세팅 및 실행
1
2
3
4
5
6
from locust import HttpUser, task
class QuickTestUser(HttpUser):
@task
def ping(self):
self.client.get("/", name="test")
1
2
3
# 환경에 맞게 둘중에 선택해서 실행
locust -f locustfile.py --headless -u 1 -r 1 -t 1m --host=http://localhost:8080
python3 -m locust -f locustfile.py --headless -u 1 -r 1 -t 1m --host=http://localhost:8080
결과 해석 (1 VU, 1분 테스트 기준)
vu1로 설정했을 경우에는 locust가 더 많은 rps를 보낸것을 확인할 수 있었습니다.
k6
locust
결과 해석 (100 VU, 1분 테스트 기준)
vu100으로 설정했을 경우에는 locust가 더 많은 rps를 보낸것을 확인할 수 있었습니다.
k6
locust
왜 단일 사용자 RPS에서 Locust가 더 높게 나올 수 있는가?
단순한 실험이지만 단일 VU 환경에서는 k6가 항상 더 빠르다고 볼 수는 없습니다. 실제 실험 결과와 서칭해본결과의 아키텍처 특성을 종합하면 다음과 같은 성향이 있습니다.
단일 사용자 환경
- Locust가 더 높은 RPS를 기록할 수 있음
- 이유:
gevent
기반 비동기 루프가 매우 빠름- Python 스크립트의 루프가 단순하고 오버헤드가 낮음
- tight loop (sleep 없음)에서 Locust는 CPU를 거의 독점함
- k6는 Go의 스케줄러, GC 간섭으로 미세한 딜레이 발생 가능
다수 사용자 및 대규모 부하 환경
- k6가 훨씬 유리함
- 이유:
- Go 고루틴 기반으로 수만 VU도 경량하게 처리 가능
- 멀티코어 활용이 최적화되어 고성능 서버에 적합
- 단일 바이너리 구조로 컨테이너 배포 및 CI/CD 통합 용이
- 다양한 출력 포맷(JSON, InfluxDB 등) 및 Grafana 연동 지원
- 복잡한 시나리오를 JavaScript로 유연하게 작성 가능
결론
단일 사용자 RPS는 Locust가 더 높을 수 있습니다. 그러나 실제 부하 테스트 목적(고부하, 병렬성, 자동화, 관측성)에선 k6가 더 확장성 있고 안정적인 선택지입니다.
[출처]
- https://k6.io/
- https://locust.io/
This post is licensed under CC BY 4.0 by the author.