개념
k6란
k6는 코드로 부하 테스트 시나리오를 작성하는 오픈소스 도구다. 모듈 12(레슨 3)에서 배운 코드 기반 API 테스트와 구조가 비슷하지만, 한 번의 요청이 아니라 수백~수천 개의 가상 사용자(Virtual User)가 동시에 요청을 보내는 상황을 시뮬레이션한다는 점이 다르다.
기본 스크립트 구조
import http from "k6/http"
import { check, sleep } from "k6"
export const options = {
vus: 100, // 가상 사용자 100명
duration: "30s", // 30초 동안 실행
}
export default function () {
const res = http.get("https://api.example.com/products")
check(res, {
"상태 코드는 200이다": (r) => r.status === 200,
"응답 시간이 500ms 이내다": (r) => r.timings.duration < 500,
})
sleep(1)
}vus(가상 사용자 수)와 duration(지속 시간)을 조정하면, 레슨
2에서 배운 부하·스트레스·스파이크 테스트를 각각 만들 수 있다.
// 스트레스 테스트 — 부하를 점점 늘려가며 한계 지점을 찾음
export const options = {
stages: [
{ duration: "1m", target: 100 }, // 1분 동안 100명까지 증가
{ duration: "1m", target: 500 }, // 1분 동안 500명까지 증가
{ duration: "1m", target: 1000 }, // 1분 동안 1000명까지 증가
],
}결과 지표 읽는 법
k6를 실행하면 다음과 같은 결과가 나온다.
http_req_duration..........: avg=245ms min=89ms med=210ms max=1.2s p(95)=480ms
http_req_failed.............: 2.3% 23 out of 1000
vus_max......................: 100http_req_duration(응답 시간) — 평균만 보면 안 된다.p(95)(95번째 백분위수, 즉 요청의 95%가 이 시간 안에 끝났다는 뜻)가 실제 사용자 체감에 더 가깝다 — 평균은 소수의 매우 빠른 응답에 가려 전체 그림을 왜곡할 수 있다http_req_failed(실패율) — 요청이 에러 응답(모듈 9 레슨 2의 4xx/5xx)을 받은 비율. 이 비율이 올라가는 시점이 시스템이 부하를 못 견디기 시작하는 지점이다vus_max— 이 결과가 몇 명의 동시 사용자에서 나온 것인지
평균의 함정
평균 응답 시간 245ms → "괜찮아 보인다"
p(95) 응답 시간 480ms → "실제로는 20명 중 1명이 거의 0.5초를 기다린다"모듈 6(레슨 5)에서 배운 지표 해석의 정직함이 여기서도 중요하다 — 평균만 보고 "문제없다"고 판단하면, 실제로 많은 사용자가 겪는 느린 경험을 놓칠 수 있다.
병목 지점 찾기
부하를 늘려가며 http_req_duration과 http_req_failed를
관찰하면, 어느 지점부터 급격히 나빠지는지가 드러난다.
동시 사용자 500명: 평균 250ms, 실패율 0%
동시 사용자 1000명: 평균 260ms, 실패율 0.1%
동시 사용자 1500명: 평균 1200ms, 실패율 8% ← 여기서 급격히 나빠짐이 "급격히 나빠지는 지점"이 바로 레슨 2에서 배운 스트레스 테스트가 찾으려는 시스템의 실질적 한계다.
실무에서 왜 필요한가
"부하 테스트 결과 평균 응답 시간 250ms로 양호합니다"라는 보고는 얼핏 안심되지만, p(95)나 실패율을 함께 보지 않으면 실제 사용자 경험을 왜곡해서 전달할 수 있다. k6로 직접 스크립트를 짜고 결과를 해석할 수 있는 QA는, 개발팀이나 인프라팀에 "정확히 어느 지점부터 문제가 시작되는지"를 근거 있는 숫자로 전달할 수 있다.