How to Execute Load Tests Using the k6 Framework

1. 소개

As web applications scale, they must efficiently handle increasing concurrent users and requests. Load testing is crucial in evaluating an application’s performance under varying traffic conditions, identifying potential bottlenecks, and ensuring reliability.

예를 들어, 플래시 세일 중에 사용자가 급증하는 전자상거래 플랫폼이 있습니다. 적절한 로드 테스트 없이 성능 병목 현상이 발생하면 응답 시간이 느려지거나 심지어 다운타임이 발생하여 사용자 경험과 수익에 영향을 미칠 수 있습니다.

k6 프레임워크는 단순성과 정교한 성능 분석을 Bridging하는 강력한 오픈 소스 로드 테스트 도구입니다. JavaScript 스크립팅과 효율적인 실행 기능을 결합하여 개발자가 포괄적인 성능 테스트 시나리오를 만들 수 있도록 설계되었습니다.

이 튜토리얼에서는 k6를 설정하고, 로드 테스트를 수행하고, 성능 메트릭을 분석하며 최적 시스템 성능을 보장하기 위한 모범 사례를 따르는 전체 프로세스를 탐구할 것입니다.

2. K6 설정하기

k6로 로드 테스트를 시작하려면 도구를 설치하고 테스트 스크립트를 설정해야 합니다.

2.1. 설치

k6를 시작하는 것은 간단합니다. 시스템의 패키지 관리자를 사용하여 설치할 수 있습니다.

예를 들어 macOS에서는 다음 명령을 실행할 수 있습니다:

$ brew install k6

설치가 완료되면 버전을 확인하여 제대로 설치되었는지 확인합시다:

$ k6 version

출력은 설치를 확인합니다:

k6 v0.56.0 (go1.23.4, darwin/arm64)

2.2. 테스트 스크립트

k6의 핵심 기능을 보여주는 기본 로드 테스트 스크립트 test.js를 개발해 보겠습니다:

import http from 'k6/http';
import { sleep, check } from 'k6';

// 테스트 구성
export const options = {
  vus: 10, // 동시 가상 사용자 시뮬레이션
  duration: '30s',

  thresholds: {
    http_req_duration: ['p(95)<500'], // 95%의 요청이 500ms 이하로 완료되어야 함
    http_req_failed: ['rate<0.01']    // 요청 실패 비율이 1% 미만
  }
};

// 테스트 시나리오
export default function () {

  // 요청 시뮬레이션
  const response = http.get('https://test-api.k6.io'); 

  // 응답 검증
  check(response, {
    'status is 200': (r) => r.status === 200,
    'response time is acceptable': (r) => r.timings.duration < 500
  });

  // 사용자 활동 시뮬레이션
  sleep(1);
}

이 스크립트는 k6이 10개의 가상 사용자와 30초의 지속 시간을 설정하는 테스트 구성을 정의합니다. 이는 95%의 요청이 500ms 이하로 완료되고, 실패 비율이 1% 미만임을 보장합니다.

이후 스크립트는 GET 요청을 API 엔드포인트로 보내고 응답 상태가 200인지 확인하며 응답 시간이 500ms 이하인지 검증합니다.

또한, 시스템에 지속적이고 현실적인 부하를 유지하기 위해 각 가상 사용자는 요청 간에 1초간 일시 중지합니다.

테스트 스크립트를 실행합시다:

k6 run test.js

실행되면 스크립트는 주요 성능 메트릭을 캡처하고 응답 조건을 검증하며 로드 테스트의 포괄적인 보고서를 제공합니다. 이 보고서에는 응답 시간, 요청 비율 및 잠재적 실패가 포함됩니다.

3. 로드 테스트 실행하기

k6를 성공적으로 설정하고 첫 번째 기본 로드 테스트를 실행함으로써 포괄적인 성능 평가를 위한 기초를 다졌습니다.

초기 구성에 따라 이제 현실적인 애플리케이션 사용을 모방하는보다 정교한 테스트 시나리오를 탐구할 수 있습니다.

3.1. 고급 테스트 시나리오

k6는 options 객체를 통해 테스트 시나리오를 유연하게 구성할 수 있으므로 실제 트래픽 패턴을 쉽게 시뮬레이션할 수 있습니다. 예를 들어, 사용자 행동을 모방하기 위해 증가 및 감소 단계 정의 가능:

export const options = {
  stages: [
    { duration: '1m', target: 20 }, // 1분 내에 20명의 사용자 증가
    { duration: '3m', target: 20 }, // 3분 동안 안정적으로 유지
    { duration: '1m', target: 0 },   // 1분 내에 0명의 사용자로 감소
  ],
};

이 설정은 점진적으로 부하를 증가시키고, 특정 기간 동안 안정적으로 유지한 다음, 부드럽게 감소시켜 실제 사용 조건 하에서 애플리케이션 성능을 테스트하는 데 도움이 됩니다.

3.2. 다수의 엔드포인트 테스트

한 스크립트에서 여러 API 경로의 성능을 평가하여 포괄적인 테스트 범위를 보장할 수 있습니다. 예를 들어:

export default function () {

  // 다양한 사용자 상호 작용 시뮬레이션
  const responses = http.batch([
    ['GET', 'https://test-api.k6.io/public/crocodiles/'],
    ['POST', 'https://test-api.k6.io/auth/basic/login/', JSON.stringify({username:'test',password:'1234'})]
  ]);

  // 여러 엔드포인트 응답 검증
  check(responses[0], { 'Crocodiles loaded': (r) => r.status === 200 });
  check(responses[1], { 'Login done': (r) => r.status === 200 });
}

이 스크립트는 GET 요청을 통해 crocodileslogin을 동시에 실행하고, 각 엔드포인트가 성공적인 HTTP 200 상태 코드를 반환하는지 검증함으로써 다중 엔드포인트 로드 테스트를 수행합니다.

3.3. 내장 메트릭

k6는 범위가 다양한 유용한 메트릭을 자동으로 제공합니다. 예를 들면:

  • httpreqduration: DNS 조회, 연결 및 응답 시간을 포함한 총 요청 기간
  • http_reqs: 발생한 HTTP 요청 총 수
  • httpreqfailed: 실패한 요청의 비율
  • vus: 현재 동시 가상 사용자 수
  • iterations: 실행된 스크립트 반복 횟수

이러한 메트릭은 고수준 및 세부적인 통찰력을 제공하여 성능 분석의 기반을 설정합니다.

3.4. 커스텀 메트릭

커스텀 메트릭은 k6의 강력한 기능으로, 애플리케이션 성능의 특정 측면을 모니터링할 수 있습니다. 예를 들어, 커스텀 카운터를 사용하여 실패한 로그인 시도를 추적할 수 있습니다:

import { Counter } from 'k6/metrics';

let loginFailures = new Counter('login_failures');

export default function () {
  let res = http.post('https://test-api.k6.io/auth/basic/login/', { 
    username: 'test',
    password: 'wrong_password'
  });
  if (res.status !== 200) {
    loginFailures.add(1); // 실패한 로그인을 위해 카운터 증가
  }
}

따라서 k6의 커스터마이즈 가능한 시나리오, 다중 엔드포인트 테스트, 상세한 메트릭 추적 기능은 애플리케이션 성능 평가 도구로서 우수합니다.

4. 로드 테스트 결과

로드 테스트 결과를 분석하는 것은 애플리케이션 성능을 이해하고 병목 현상을 식별하며 신뢰성을 보장하는 데 중요합니다.

4.1. 결과 내보내기

k6는 추가 분석을 위해 다양한 형식으로 테스트 결과를 내보낼 수 있습니다. 예를 들어, 출력 결과를 JSON 형식으로 저장할 수 있습니다:

$ k6 run --out json=results.json test.js

이것은 k6 데이터를 Grafana와 같은 시각화 도구와 통합하거나 상세한 테스트 보고서를 공유하는 데 가능하게 합니다.

k6 터미널 출력의 예시는 다음과 같을 수 있습니다:

    execution: local
    script: test.js
    output: json (results.json)
    scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration (incl. graceful stop):
              * default: 10 looping VUs for 30s (gracefulStop: 30s)
    ✓ status is 200
    ✓ response time is acceptable

   ✓ http_req_duration..............: avg=109.59ms min=104.52ms med=108.86ms max=190.22ms p(90)=113.03ms p(95)=114.66ms
   ✓ http_req_failed................: 0.00%   0 out of 270
     vus............................: 10      min=10         max=10
     vus_max........................: 10      min=10         max=10

running (0m30.3s), 00/10 VUs, 270 complete and 0 interrupted iterations
default ✓ [======================================] 10 VUs  30s

이러한 메트릭은 시스템 성능의 명확한 개요를 제공하며 최적화가 필요한 영역을 강조합니다. 기본 메트릭, 상세 분석 및 내보낸 보고서를 결합하여 애플리케이션이 부하 하에서의 행동을 철저하게 평가할 수 있습니다.

4.2. 결과 분석

로드 테스트 결과를 분석할 때 응답 시간 분석에 초점을 맞추는 것으로 시작합시다. 여기에는 다음이 포함됩니다:

  • 시스템이 95% 및 99% 요청에 대해 어떻게 수행되는지 측정하기 위한 p95 및 p99 백분위수 모니터링
  • 잠재적 이상 징후를 식별하기 위한 최대 응답 시간 추적
  • 지속적인 부하 하에서의 응답 시간 증가와 같은 악화 패턴 찾기

그런 다음 오류율 분석을 고려할 것입니다. 여기에서는:

  • 전체 신뢰성을 평가하기 위해 실패한 요청 비율에 주의
  • 타임아웃, 4xx 또는 5xx 응답과 같은 오류의 유형 및 패턴 분석
  • 시스템이 성능 한계에 접근할 때 어떻게 동작하는지 관찰

마지막으로 리소스 활용을 조사합니다. 여기에는:

  • 과도한 활용 또는 병목 현상을 감지하기 위한 CPU 사용 패턴 모니터링
  • 높은 부하 시 메모리 소비 모니터링
  • 대역폭 또는 API 용량의 제약 식별을 위한 네트워크 처리량 추적

5. 모범 사례 및 일반적인 실수

결과가 손에 들어오면 의미 있는 신뢰할 수 있는 결과를 얻기 위해 모범 사례를 따르고 일반적인 실수를 피하는 것이 중요합니다.

5.1. 모범 사례

효과적인 로드 테스트를 보장하기 위해 다음 사항을 기억해야 합니다:

  • 시작은 작게 – 부하를 점진적으로 증가시켜 시스템을 압도하지 말고 애플리케이션의 다양한 요구 사항에 따라 플로우를 유지하도록 하십시오.
  • 현실적인 시나리오 테스트 – 사용자의 행동을 반영하는 시험 결과를 보장하기 위해 실제 트래픽을 시뮬레이션하십시오.
  • 테스트 자동화 – CI/CD 파이프라인에 k6 테스트를 통합하여 지속적인 성능 모니터링 및 초기 문제 탐지 및 기회를 제공합니다.
  • 카테고리화를 위한 태그 사용 – HTTP 요청에 태그를 추가하여 결과를 보다 효과적으로 확인하고 분석할 수 있습니다.

5.2. 일반적인 실수

정확한 테스트 결과를 보장하기 위해 다음의 흔한 실수를 피해야 합니다:

  • 테스트 시스템 과부하 – k6를 실행하는 머신에 적절한 리소스를 확보하고 시스템의 리소스를 과도하게 사용하지 않도록 하십시오.
  • 비현실적인 구성 – 실제 사용을 반영하는 구성 요구 사항을 설정하며, 비현실적인 사용자의 수로 가득 차지 않도록 주의하십시오.
  • 테스트 후 분석 소홀: 결과 분석을 소홀히 하면 성능의 문제를 감지하지 못하게 되며, 최적화의 여지를 간과할 수 있습니다.

6. 결론

이 기사에서는 k6 설정, 현실적인 테스트 시나리오 생성, 결과 분석 및 신뢰할 수 있는 로드 테스트 결과를 얻기 위한 모범 사례를 논의했습니다.

로드 테스트는 단순히 애플리케이션의 스트레스를 테스트하는 것이 아니라, 그行为를 이해하고 실제 트래픽을 처리할 수 있도록 하는 것입니다.

k6의 직관적인 스크립팅, 내장된 메트릭 및 유연한 구성으로 현실적인 트래픽 패턴을 시뮬레이션하고 성능을 정확히 평가하며 시스템이 효과적으로 확장될 수 있도록 준비할 수 있습니다. 우리는 작게 시작하고 고급 시나리오를 실험하며, 진화하는 트래픽 요구에 맞게 테스트를 조정해야 합니다.

이 기사의 전체 코드는 GitHub에서 확인할 수 있습니다.

원본 출처

You may also like...

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다