📗 스터디#Web#Testing

k6로 API 성능 테스트하기

2024-12-03 | 🕒 읽는 데 0분 예상
작성자
u
카테고리
📗 스터디
작성일
태그
Web
Testing
설명
상태
배포됨
최하위 정렬
최하위 정렬
forest_분류
forest_날짜

k6란?

k6는 Grafana Labs에서 개발한 오픈 소스 부하 테스트 도구이다. K6는 API 엔드포인트에 대한 성능 테스트를 쉽게 수행할 수 있게 해준다.
 
k6의 특징과 장점은 다음과 같다.
  1. JavaScript 기반: k6는 JavaScript를 사용하여 테스트 스크립트를 작성할 수 있게 해준다. 이는 많은 개발자들에게 친숙한 언어로, 학습 곡선을 낮추고 생산성을 높인다.
  1. 높은 성능: Go 언어로 작성되어 있어, 적은 리소스로도 높은 성능을 발휘한다. 이는 대규모 부하 테스트를 수행할 때 특히 유용하다.
  1. 확장성: 다양한 플러그인과 확장 기능을 지원하여 테스트 시나리오를 더욱 풍부하게 만들 수 있다.
  1. 통합 용이성: CI/CD 파이프라인과 쉽게 통합될 수 있어, 자동화된 성능 테스트 환경을 구축하기 용이하다.
  1. 다양한 프로토콜 지원: HTTP/HTTPS, WebSocket, gRPC 등 다양한 프로토콜을 지원한다.
  1. 결과 시각화: 테스트 결과를 다양한 형태로 시각화할 수 있어, 성능 분석이 용이하다.
 

설치

필자는 Windows 환경을 사용중이므로 이를 기준으로 설명하겠다. Windows에서 k6를 사용하기 위해서는 Chocolatey 패키지 매니저를 사용하는 것이 권장된다.
Chocolatey를 설치하기 위해서는 PowerShell을 관리자 권한으로 실행해 아래 커맨드를 입력하면 된다.
> Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
설치가 완료되면 choco 명령어를 입력해 설치 여부를 확인해보자. 설치가 정상적으로 완료됐다면, 이제 아래 커맨드를 입력해 k6를 설치할 수 있다.
$ choco install k6
 

테스트 실행

k6의 기본 테스트 스크립트 구조는 다음과 같다.
import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { vus: 10, duration: '30s', }; export default function () { const res = http.get('https://test.k6.io'); check(res, { 'status was 200': (r) => r.status == 200 }); sleep(1); }
이 코드는 10명의 가상 사용자(VU)가 30초 동안 https://test.k6.io에 GET 요청을 보내는 간단한 테스트를 수행한다.
가상 사용자(VU)란 실제 사용자의 행동을 시뮬레이션하는 가상의 동시 접속자를 말한다. 각 VU는 정의된 시나리오에 따라 독립적으로 작업을 수행하게 된다. 여기서 주의할 것은 VU가 요청의 수를 의미하는 것이 아니라는 것이다. 위 예시처럼 VU가 10이고, duration이 30초라면, 30초 동안 10명의 사용자가 지속적으로 요청을 보내는 것을 가정하는 테스트이다.
테스트를 시작하려면 터미널에 다음과 같이 명령어를 입력하면 된다.
$ k6 run 테스트코드파일.js
테스트가 종료되면 다음과 같이 결과가 출력된다.
notion image
표시된 결과에서 각 항목에 대한 설명은 다음과 같다.
항목
설명
Type
vus
현재 활성화된 가상 사용자
Guage
vus_max
가능한 최대 가상 사용자 수(리소스 미리 할당)
Guage
iterations
테스트에서 VU가 스크립트를 실행한 총 횟수
Counter
iteration_duration
main function의 전체 반복을 완료하는 데 소요된 시간
Trend
data_received
데이터를 전달받은 양
Counter
data_sent
데이터를 전송한 양
Counter
checks
성공적으로 체크된 비율
Rate
http_reqs
생성한 총 HTTP 요청 횟수
Counter
http_req_blocked
요청을 시작하기 전 차단된(TCP connection slot 대기) 시간
Trend
http_req_connecting
원격 호스트에 대한 TCP 연결을 설정하는 데 소요된 시간
Trend
http_tls_handshaking
원격 호스트와의 hand shaking 세션에 소요된 시간
Trend
http_req_sending
원격 호스트에 데이터를 전송하는 데 소요된 시간
Trend
http_req_waiting
원격 호스트로부터 응답을 대기하는 데 소요된 시간
Trend
http_req_receiving
원격 호스트로부터 응답을 수신하는 데 소요된 시간
Trend
http_req_duration
요청의 총 시간 (http_req_sending + http_req_waiting + http_req_receiving)
Trend
http_req_failed
요청이 실패한 비율
Rate
k6는 다양한 고급 기능을 제공하여 복잡한 성능 테스트 시나리오를 구현할 수 있게 해준다. 주요 고급 기능들을 소개하고, 각 기능별로 예시 코드를 통해 살펴보도록 하겠다.

단계별 부하 증가 (Stages)

Stages 기능을 사용하면 시간에 따라 가상 사용자(VU) 수를 동적으로 조절할 수 있다. 이는 점진적인 부하 증가나 스파이크 테스트 등을 수행할 때 유용하다.
import http from 'k6/http'; export const options = { stages: [ { duration: '30s', target: 20 }, // 30초 동안 20명까지 증가 { duration: '1m30s', target: 10 }, // 1분 30초 동안 10명으로 감소 { duration: '20s', target: 0 }, // 20초 동안 0명으로 감소 ], }; export default function () { http.get('https://test.k6.io'); }
이 테스트에서는 처음 30초 동안 VU를 20명까지 증가시키고, 그 다음 1분 30초 동안 10명으로 줄인 후, 마지막 20초 동안 0명으로 감소시킨다.

임계값 (Thresholds)

임계값을 설정하여 테스트의 성공/실패 기준을 정의할 수 있다.
import http from 'k6/http'; export const options = { thresholds: { http_req_duration: ['p(95)<500'], // 95%의 요청이 500ms 이내에 완료되어야 함 http_req_failed: ['rate<0.1'], // 요청 실패율이 10% 미만이어야 함 }, }; export default function () { http.get('https://test.k6.io'); }
이 스크립트는 95%의 요청이 500ms 이내에 완료되어야 하며, 요청 실패율이 10% 미만이어야 한다는 조건을 설정한다. 아래 사진과 같이 만약 설정한 조건을 만족하지 못한 항목에는 X 가 표시되며, 만족한 항목에는 체크가 표시된다.
notion image

체크 (Checks)

체크를 사용하여 응답의 유효성을 검증할 수 있다.
import http from 'k6/http'; import { check } from 'k6'; export default function () { let res = http.get('https://test.k6.io'); check(res, { '상태 200': (r) => r.status === 200, '본문에 "Welcome" 포함': (r) => r.body.includes('Welcome'), }); }
이 스크립트는 응답의 상태 코드가 200인지, 그리고 응답 본문에 "Welcome"이라는 텍스트가 포함되어 있는지 확인한다. 위 예제에 대한 결과는 아니지만, 필자가 진행 중인 프로젝트에 사용한 테스트 결과 화면은 아래와 같다. 각 스텝에 대한 테스트가 완료되면 체크 표시를 통해 응답이 정상적으로 반환되었음을 확인할 수 있다.
notion image

그룹화 (Grouping)

그룹화를 사용하면 관련된 요청들을 논리적 단위로 묶을 수 있다. 이는 결과 분석 시 유용하다.
import http from 'k6/http'; import { group, check } from 'k6'; export default function () { group('접속 테스트', function () { let res = http.get('https://test.k6.io'); check(res, { '상태 200': (r) => r.status === 200 }); }); group('로그인 테스트', function () { let res = http.post('https://test.k6.io/login', { username: 'testuser', password: 'testpass' }); check(res, { '로그인 성공': (r) => r.status === 200 }); }); }
이처럼 페이지 접속, 로그인과 같이 각 작업들을 그룹으로 묶어 테스트할 수 있다.
 

사용자 정의 메트릭

k6에서는 사용자 정의 메트릭을 생성하여 특정 이벤트나 조건을 추적할 수 있다. 매트릭 선언 시에 적절한 타입의 객체를 선언해주어야 하는데, 총 4가지로 구분된다.
  • Counters - 값을 누적하여 계산
  • Gauges - 최소, 최대, 마지막 값을 산출
  • Rates - 0(False)이 아닌 값이 얼마나 자주 반환되는 지 체크(백분율)
  • Trends - 평균, 백분위 수, 최빈값 등 다양한 통계 계산
import http from 'k6/http'; import { Counter, Rate } from 'k6/metrics'; const successfulLogins = new Counter('successful_logins'); const failedLogins = new Rate('failed_logins'); export default function () { let res = http.post('https://test.k6.io/login', { username: 'testuser', password: 'testpass' }); if (res.status === 200) { successfulLogins.add(1); } else { failedLogins.add(1); } }
이 스크립트는 성공한 로그인 수와 실패한 로그인 비율을 추적한다.
 
이외에도 k6는 다양한 옵션과 기능들을 제공하고 있으며, Grafana와 같은 시각화 도구를 이용해 결과를 분석해볼 수도 있다. 공식 문서가 상당히 잘 작성되어 있으니 참고하면 좋을 것 같다.
 
 

댓글 0