부하 테스트 가이드

k6 완전 가이드

👥 방문자 수

Grafana k6는 JavaScript로 작성하는 현대적인 오픈소스 부하 테스트 도구입니다. 개발자 친화적인 CLI, 강력한 메트릭, 손쉬운 CI/CD 통합으로 빠르게 성능 테스트를 구축할 수 있습니다.

오픈소스 JavaScript/TypeScript CLI 기반 CI/CD 통합 클라우드 확장
🧪 실전 예제 보기 → ← TestForge 홈으로

k6란?

k6는 Grafana Labs가 개발한 오픈소스 부하 테스트 프레임워크입니다. JavaScript(ES6+)로 테스트 스크립트를 작성하며, Go로 구현된 런타임 덕분에 높은 성능과 낮은 리소스 사용량을 제공합니다.

주요 특징

설치

macOS (Homebrew)

brew install k6bash

Linux (Debian/Ubuntu)

sudo gpg -k
sudo gpg --no-default-keyring \
  --keyring /usr/share/keyrings/k6-archive-keyring.gpg \
  --keyserver hkp://keyserver.ubuntu.com:80 \
  --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69

echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] \
  https://dl.k6.io/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/k6.list

sudo apt-get update
sudo apt-get install k6bash

Windows (winget)

winget install k6 --source wingetpowershell

Docker

docker pull grafana/k6
docker run --rm -i grafana/k6 run - <script.jsbash
설치 확인: k6 version을 실행해 버전이 출력되면 설치 완료입니다.

첫 번째 테스트

가장 간단한 k6 스크립트입니다. script.js로 저장하세요.

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

export const options = {
  vus: 10,          // 동시 가상 사용자 수
  duration: '30s',  // 테스트 지속 시간
};

export default function () {
  http.get('https://test.k6.io');
  sleep(1);
}javascript

실행:

k6 run script.jsbash

출력 예시:

          /\      |‾‾| /‾‾/   /‾‾/
     /\  /  \     |  |/  /   /  /
    /  \/    \    |     (   /   ‾‾\
   /          \   |  |\  \ |  (‾)  |
  / __________ \  |__| \__\ \_____/ .io

  execution: local
     script: script.js
     output: -

  scenarios: (100.00%) 1 scenario, 10 max VUs, 1m0s max duration

  ✓ http_req_duration............: avg=210ms min=180ms med=205ms max=380ms
  ✓ http_req_failed..............: 0.00%
    iterations...................: 300 / 300
    vus..........................: 10text

핵심 개념

개념설명예시
VU (Virtual User)동시 실행되는 가상 사용자 수vus: 100
Duration테스트 총 지속 시간duration: '5m'
Iterationdefault 함수 1회 실행VU × Duration / sleep
StageVU 수를 단계적으로 변화Ramp-up/Ramp-down
Threshold테스트 합격/실패 기준p(95) < 500
Check응답 검증 (어서션)status === 200

테스트 시나리오

1. 부하 테스트 (Load Test)

정상 및 피크 트래픽 조건에서 시스템 성능을 검증합니다.

export const options = {
  stages: [
    { duration: '5m',  target: 100 },  // Ramp-up: 0 → 100 VU
    { duration: '10m', target: 100 },  // 부하 유지
    { duration: '5m',  target: 0   },  // Ramp-down: 100 → 0
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],  // 95퍼센타일 < 500ms
    http_req_failed:   ['rate<0.01'],  // 에러율 < 1%
  },
};javascript

2. 스트레스 테스트 (Stress Test)

시스템 한계점(breaking point)을 찾기 위해 부하를 점진적으로 증가시킵니다.

export const options = {
  stages: [
    { duration: '2m', target: 100  },
    { duration: '5m', target: 100  },
    { duration: '2m', target: 200  },
    { duration: '5m', target: 200  },
    { duration: '2m', target: 300  },
    { duration: '5m', target: 300  },
    { duration: '2m', target: 0    },  // 복구 확인
  ],
};javascript

3. 스파이크 테스트 (Spike Test)

갑작스러운 트래픽 급증(예: 이벤트, 프로모션)에 시스템이 어떻게 반응하는지 검증합니다.

export const options = {
  stages: [
    { duration: '10s', target: 100  },  // 일반 트래픽
    { duration: '1m',  target: 100  },
    { duration: '10s', target: 1400 },  // 급격한 스파이크
    { duration: '3m',  target: 1400 },
    { duration: '10s', target: 100  },  // 복구
    { duration: '3m',  target: 100  },
    { duration: '10s', target: 0    },
  ],
};javascript

4. 소크 테스트 (Soak Test)

장시간 운영 시 메모리 누수, 커넥션 풀 고갈 등을 탐지합니다. 보통 수 시간 ~ 수일 실행합니다.

export const options = {
  stages: [
    { duration: '5m',  target: 100 },   // Ramp-up
    { duration: '8h',  target: 100 },   // 장시간 유지
    { duration: '5m',  target: 0   },   // Ramp-down
  ],
};javascript

Checks & Thresholds

Checks — 응답 검증

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

export default function () {
  const res = http.get('https://api.example.com/users');

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

Thresholds — 합격 기준

export const options = {
  thresholds: {
    // 95퍼센타일 응답시간 500ms 미만
    http_req_duration: ['p(95)<500', 'p(99)<1000'],

    // 에러율 1% 미만
    http_req_failed: ['rate<0.01'],

    // 특정 check 통과율 99% 이상
    'checks{check:status is 200}': ['rate>0.99'],

    // 커스텀 메트릭
    'my_custom_metric': ['avg<200'],
  },
};javascript
⚠️
Threshold 실패 시: k6는 종료 코드 99를 반환합니다. CI/CD 파이프라인에서 이를 활용해 배포를 차단할 수 있습니다.

HTTP 요청 작성

GET / POST / PUT / DELETE

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

const BASE_URL = 'https://api.example.com';

export default function () {
  // GET
  const listRes = http.get(`${BASE_URL}/users`);

  // POST (JSON body)
  const payload = JSON.stringify({ name: 'TestUser', email: 'test@example.com' });
  const headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer TOKEN' };
  const createRes = http.post(`${BASE_URL}/users`, payload, { headers });

  check(createRes, { 'created': (r) => r.status === 201 });

  // PUT
  const userId = JSON.parse(createRes.body).id;
  http.put(`${BASE_URL}/users/${userId}`, JSON.stringify({ name: 'Updated' }), { headers });

  // DELETE
  http.del(`${BASE_URL}/users/${userId}`, null, { headers });
}javascript

세션 유지 (쿠키 / 로그인)

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

export default function () {
  // 로그인 → 세션 쿠키 자동 유지
  const loginRes = http.post('https://api.example.com/login', {
    username: 'user@example.com',
    password: 'password123',
  });

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

  // 이후 요청에 쿠키 자동 첨부
  http.get('https://api.example.com/profile');
}javascript

결과 출력 & 리포트

내장 요약 리포트

k6는 실행 후 자동으로 통계 요약을 출력합니다. 파일로 저장:

k6 run --out json=results.json script.jsbash

HTML 리포트 생성

# k6-reporter 설치
npm install -g k6-html-reporter

# JSON 결과를 HTML로 변환
k6-html-reporter --resultFile results.json --reportTitle "부하 테스트 결과"bash

Grafana + InfluxDB 연동

# InfluxDB로 메트릭 전송
k6 run --out influxdb=http://localhost:8086/k6 script.js

# Docker Compose로 환경 구성
# grafana/k6-grafana-dashboard 사용 가능bash

CI/CD 통합

GitHub Actions

name: Performance Test

on:
  push:
    branches: [main]
  pull_request:

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

      - name: Run k6 load test
        uses: grafana/k6-action@v0.3.1
        with:
          filename: tests/load-test.js
        env:
          BASE_URL: ${{ secrets.STAGING_URL }}

      - name: Upload results
        uses: actions/upload-artifact@v3
        with:
          name: k6-results
          path: results.jsonyaml

GitLab CI

k6-test:
  stage: test
  image: grafana/k6
  script:
    - k6 run --out json=results.json tests/load-test.js
  artifacts:
    paths:
      - results.json
    when: alwaysyaml
💡
팁: Threshold 실패 시 k6 exit code가 99가 되므로 CI 파이프라인이 자동으로 실패 처리됩니다. 별도 조건 체크 없이 배포 게이팅이 가능합니다.

k6 Cloud (분산 실행)

단일 머신을 초과하는 대규모 부하가 필요한 경우 Grafana k6 Cloud를 활용합니다.

# k6 Cloud 로그인
k6 login cloud --token YOUR_TOKEN

# 클라우드에서 실행 (전 세계 여러 지역)
k6 cloud script.js

# 특정 지역 지정
k6 cloud --linger script.jsbash
// 클라우드 전용 옵션
export const options = {
  ext: {
    loadimpact: {
      projectID: 123456,
      name: 'My Load Test',
      distribution: {
        Seoul:      { loadZone: 'amazon:kr:seoul',         percent: 60 },
        Virginia:   { loadZone: 'amazon:us:ashburn',       percent: 40 },
      },
    },
  },
};javascript

도구 비교

항목k6JMeternGrinder
스크립트 언어JavaScriptGUI / GroovyGroovy / Jython
설치 복잡도매우 간단Java 필요컨트롤러+에이전트
CI/CD 통합⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
분산 테스트k6 CloudRemote JMeter기본 내장
학습 곡선낮음중간중간
리소스 사용낮음높음 (JVM)중간
GUI없음 (CLI)풍부한 GUI웹 UI
🚀
k6 추천 상황: 개발자가 코드로 테스트를 관리하고, CI/CD 파이프라인에 자동화된 성능 게이팅이 필요한 경우.

더 자세한 내용은 TestForge Docs부하 테스트 가이드에서 확인하세요.