⚡ k6 · 실전 예제

k6 실전 예제 모음

복사해서 바로 실행 가능한 k6 예제 코드입니다. Load·Stress·Spike 시나리오부터 API 인증 흐름, Thresholds, GitHub Actions CI/CD까지 실무에서 바로 쓰는 완성 스크립트를 제공합니다.

✅ 100% 오픈소스 ✅ 즉시 실행 가능 JavaScript/TypeScript Grafana k6 GitHub Actions

0환경 설정

1
k6 설치 (Linux/Mac)brew install k6 또는 sudo apt install k6
2
k6 설치 (Windows)winget install k6 --source winget 또는 공식 MSI 설치 파일 사용
3
버전 확인k6 versionk6 v0.50+ 확인
4
테스트 대상 서버 — 로컬 서버 또는 https://test-api.k6.io 공개 테스트 API 활용 가능

1Load 시나리오 — Ramp-up/Down

실제 트래픽 패턴을 재현하는 stages 기반 Load 테스트입니다. 점진적으로 부하를 높였다가 낮추는 표준 패턴으로, 서버의 임계점과 회복력을 함께 검증합니다.

load_test.js — Ramp-up / Steady / Ramp-down
Loadstages
100 VU까지 점진적으로 올린 뒤 5분 유지, 다시 0으로 내리는 표준 Load 시나리오.
jsimport http from 'k6/http';
import { sleep, check } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 50 },   // Ramp-up: 0 → 50 VU
    { duration: '5m', target: 100 },  // Ramp-up: 50 → 100 VU
    { duration: '5m', target: 100 },  // Steady state: 100 VU 유지
    { duration: '2m', target: 0 },    // Ramp-down: 100 → 0 VU
  ],
};

const BASE_URL = 'https://test-api.k6.io';

export default function () {
  const res = http.get(`${BASE_URL}/public/crocodiles/`);

  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });

  sleep(1);
}
💡
실행: k6 run load_test.js — 터미널에서 실시간 메트릭을 확인할 수 있습니다. Grafana로 시각화하려면 k6 run --out influxdb=http://localhost:8086/k6 load_test.js를 사용하세요.

Stress / Spike 시나리오

stress_spike.js — 한계점 탐색 및 Spike 테스트
StressSpike
서버 한계를 찾는 Stress와 갑작스런 트래픽 급증을 시뮬레이션하는 Spike를 하나의 파일에서 선택 실행.
jsimport http from 'k6/http';
import { sleep, check } from 'k6';

// STRESS: 한계점까지 점진 증가
export const stressOptions = {
  stages: [
    { duration: '2m', target: 100 },
    { duration: '5m', target: 200 },
    { duration: '5m', target: 300 },
    { duration: '2m', target: 0 },
  ],
};

// SPIKE: 갑작스러운 트래픽 급증
export const spikeOptions = {
  stages: [
    { duration: '30s', target: 10 },
    { duration: '10s', target: 500 }, // 순간 급증
    { duration: '1m',  target: 500 },
    { duration: '10s', target: 10 },  // 회복 후 정상
    { duration: '30s', target: 0 },
  ],
};

// 실행 시: K6_SCENARIO=spike k6 run stress_spike.js
const scenario = __ENV.K6_SCENARIO || 'stress';
export const options = scenario === 'spike' ? spikeOptions : stressOptions;

export default function () {
  const res = http.get('https://test-api.k6.io/public/crocodiles/');
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}

2API 인증 흐름 — 로그인 → JWT → API 호출

실제 서비스 대부분은 인증이 필요합니다. 로그인으로 토큰을 발급받아 이후 요청에 Bearer 헤더를 붙이는 실무 패턴입니다.

auth_flow.js — 로그인 → 토큰 발급 → 인증 API 호출
JWT인증 플로우
setup() 함수에서 토큰을 한 번만 발급하고, VU들이 공유해서 사용하는 효율적인 패턴.
jsimport http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 50,
  duration: '3m',
};

const BASE_URL = 'https://test-api.k6.io';

// setup: 부하 시작 전 1회 실행 → 토큰 발급
export function setup() {
  const loginRes = http.post(
    `${BASE_URL}/auth/token/login/`,
    JSON.stringify({ username: 'test_case', password: '1234' }),
    { headers: { 'Content-Type': 'application/json' } }
  );

  check(loginRes, { 'login OK': (r) => r.status === 200 });

  const token = loginRes.json('access');
  return { token };
}

// 메인 VU 함수 — data는 setup()의 반환값
export default function (data) {
  const params = {
    headers: {
      Authorization: `Bearer ${data.token}`,
      'Content-Type': 'application/json',
    },
  };

  // 1. 목록 조회
  const listRes = http.get(`${BASE_URL}/my/crocodiles/`, params);
  check(listRes, {
    'list status 200': (r) => r.status === 200,
    'list has items': (r) => r.json().length > 0,
  });

  sleep(0.5);

  // 2. 새 항목 생성
  const createRes = http.post(
    `${BASE_URL}/my/crocodiles/`,
    JSON.stringify({ name: `croc_${__VU}_${__ITER}`, sex: 'M', date_of_birth: '2020-01-01' }),
    params
  );
  check(createRes, { 'create status 201': (r) => r.status === 201 });

  sleep(1);
}

3Thresholds & Checks — 성능 기준 설정

Thresholds는 테스트의 합격/불합격 기준입니다. CI/CD에서 기준 미달 시 자동으로 빌드를 실패시킬 수 있습니다.

thresholds.js — SLA 기반 성능 기준 정의
ThresholdsCI/CD
p95 응답시간 500ms 이하, 에러율 1% 미만, Check 통과율 99% 이상을 기준으로 설정.
jsimport http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 30,
  duration: '5m',
  thresholds: {
    // HTTP 응답 시간 기준
    http_req_duration: [
      'p(95)<500',  // 95%ile이 500ms 미만
      'p(99)<1000', // 99%ile이 1000ms 미만
    ],
    // HTTP 에러율
    http_req_failed: ['rate<0.01'], // 에러율 1% 미만

    // Check 성공률 (커스텀 기준 이름)
    'checks{type:api}': ['rate>0.99'],

    // 특정 엔드포인트만 별도 기준
    'http_req_duration{endpoint:list}': ['p(95)<300'],
  },
};

export default function () {
  // 태그로 엔드포인트 구분
  const listRes = http.get('https://test-api.k6.io/public/crocodiles/', {
    tags: { endpoint: 'list' },
  });

  check(listRes, {
    'status 200': (r) => r.status === 200,
    'body not empty': (r) => r.body.length > 0,
  }, { type: 'api' });

  sleep(1);
}
⚠️
Threshold 실패 시 k6는 exit code 99를 반환합니다. GitHub Actions에서 if: failure()로 실패 알림을 설정하거나, Slack 알림을 연동할 수 있습니다.

4커스텀 메트릭 — 비즈니스 지표 수집

k6 내장 메트릭 외에도 비즈니스에 의미 있는 지표(결제 성공률, 장바구니 응답시간 등)를 직접 정의해서 수집할 수 있습니다.

custom_metrics.js — Trend·Counter·Rate·Gauge 예제
MetricsGrafana
4가지 메트릭 타입을 모두 활용한 예제. InfluxDB + Grafana로 시각화 가능.
jsimport http from 'k6/http';
import { check, sleep } from 'k6';
import { Trend, Counter, Rate, Gauge } from 'k6/metrics';

// 커스텀 메트릭 정의
const checkoutDuration = new Trend('checkout_duration_ms');  // 시간 분포
const errorCount       = new Counter('error_count');         // 누적 카운트
const checkoutSuccess  = new Rate('checkout_success_rate');  // 성공률
const activeUsers      = new Gauge('active_user_count');     // 현재값

export const options = {
  vus: 20,
  duration: '3m',
  thresholds: {
    checkout_duration_ms: ['p(95)<800'],
    checkout_success_rate: ['rate>0.95'],
  },
};

export default function () {
  activeUsers.add(__VU); // 현재 VU 수 기록

  const start = Date.now();

  const res = http.post(
    'https://test-api.k6.io/my/crocodiles/',
    JSON.stringify({ name: 'checkout_test', sex: 'M', date_of_birth: '2020-01-01' }),
    { headers: { 'Content-Type': 'application/json' } }
  );

  const duration = Date.now() - start;
  checkoutDuration.add(duration); // ms 기록

  const ok = check(res, { 'checkout ok': (r) => r.status === 201 });
  checkoutSuccess.add(ok);
  if (!ok) errorCount.add(1);

  sleep(1);
}

5GitHub Actions CI/CD 자동화

PR 머지 또는 배포 이후 자동으로 성능 테스트를 실행하고, Threshold 실패 시 워크플로우를 중단시키는 실무 패턴입니다.

.github/workflows/k6-perf.yml — 성능 테스트 자동화
GitHub ActionsCI/CD
PR이 main에 머지될 때마다 k6 성능 테스트를 실행하고 결과를 PR 코멘트로 남기는 워크플로우.
yamlname: k6 Performance Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  k6-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install k6
        run: |
          curl https://github.com/grafana/k6/releases/download/v0.50.0/k6-v0.50.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1

      - name: Run Load Test
        env:
          BASE_URL: ${{ secrets.STAGING_URL }}
        run: |
          ./k6 run \
            --out json=results.json \
            --env BASE_URL=$BASE_URL \
            tests/load_test.js

      - name: Upload Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: k6-results
          path: results.json

      - name: Comment PR with Results
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const results = JSON.parse(fs.readFileSync('results.json', 'utf8'));
            // 마지막 summary 찾기
            const summary = results.filter(r => r.type === 'Point' && r.metric === 'http_req_duration');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `### k6 성능 테스트 결과\n${JSON.stringify(summary.slice(-5), null, 2)}`
            });
ℹ️
k6 Cloud 연동: k6 cloud run load_test.js로 분산 부하를 클라우드에서 실행할 수 있습니다. 무료 플랜으로 월 50회 테스트 실행이 가능합니다. k6 완전 가이드에서 Cloud 설정 방법을 확인하세요.