[k6] 부하테스트

2025. 11. 4. 16:19·프로젝트/끼니콩

부하테스트 ? 

부하테스트는 일반적으로 실제 요구 부하를 서버가 견뎌낼 수 있는지 확인하는 작업 중 하나이다. 이 작업을 통해 애플리케이션의 건강성을 판단해볼 수 있다. 

 

실행 단계 

1) k6 설치

brew install k6

 

2) 스크립트 파일 작성

k6는 `javascript`를 사용한다.

실제 피크 타임을 가정하여 200명의 유저가 몰릴 때 안정성을 확인하고자 스크립트를 작성했다. 

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

export const options = {
  stages: [
    { duration: '30s', target: 50 },   // 0 → 50명으로 30초 동안 증가
    { duration: '1m',  target: 200 },  // 50 → 200명으로 1분 동안 증가
    { duration: '3m',  target: 200 },  // 200명 유지 (피크 타임)
    { duration: '1m',  target: 50 },   // 천천히 감소
    { duration: '30s', target: 0 },    // 종료
  ],
  thresholds: {
    http_req_duration: ['p(95)<500'],  // 95% 요청이 500ms 미만이어야 함
    http_req_failed: ['rate<0.01'],    // 에러율 1% 미만
  },
};

const headers = {
  'User-Agent': 'Mozilla/5.0 ...',
  'Accept': 'application/json,text/plain,*/*',
  'Referer': 'https://kkinikong.store/',
};

export default function () {
  const res = http.get('https://kkinikong.store/api/v1/store/map', { headers });

  check(res, { 'status is 200': (r) => r.status === 200 });

  // 유저가 실제로 다음 행동을 하기 전의 대기 시간
  sleep(Math.random() * 3); // 0~3초 랜덤
}

 

그리고 두 번째 테스트에서는 베이스라인 테스트를 진행해보았다. 서버가 최상의 컨디션일 때 낼 수 있는 기본 실력을 측정하는 과정이라고 생각하면 쉽다. 사용자가 10명뿐인 상황에서 응답이 잘 오는지 확인해보는 것이다. 코드에서 인덱스 튜닝을 진행했기 때문에, 인덱스 튜닝이 잘 이루어지고 있는지 파악하는 과정이기도 하다. 

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

export const options = {
  // 소수의 인원으로 짧게 실행하여 '순수 응답 속도' 확인
  vus: 10, 
  duration: '1m', 
  thresholds: {
    // 인덱스 튜닝을 했으니 0.2초 이내 응답을 목표
    http_req_duration: ['p(95)<200'], 
    http_req_failed: ['rate<0.01'],
  },
};

const headers = {
  'User-Agent': 'k6-baseline-test',
  'Accept': 'application/json',
};

export default function () {
  const res = http.get('https://kkinikong.store/api/v1/store/map?size=20', { headers });

  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time check': (r) => r.timings.duration < 500, // 개별 요청이 0.5초 이내인지
  });

  sleep(1);
}

 

그리고 세 번째 테스트에서는 가벼운 부하를 주며 확인해보려고 한다. 기본 체력을 확인했으니, 다시 부하를 조금 높여보며 인덱스가 버텨주는 임계점을 찾는 것이다. 100명의 사용자가 몰렸을 때의 응답 속도가 잘 유지되는지 확인해보는 과정이다. 

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

export const options = {
  stages: [
    { duration: '30s', target: 100 }, // 30초 동안 100명까지 빠르게 증가
    { duration: '2m',  target: 100 }, // 100명 유지 (여기서 인덱스 성능이 판가름 납니다)
    { duration: '30s', target: 0 },   // 종료
  ],
  thresholds: {
    // 100명일 때도 95%의 유저가 0.5초(500ms) 이내에 응답받는 것을 목표로 
    http_req_duration: ['p(95)<500'], 
    http_req_failed: ['rate<0.01'],
  },
};

const headers = {
  'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  'Accept': 'application/json,text/plain,*/*',
  'Referer': 'https://kkinikong.store/',
};

export default function () {
  const res = http.get('https://kkinikong.store/api/v1/store/map?size=20', { headers });

  check(res, { 
    'status is 200': (r) => r.status === 200,
    'under 1s': (r) => r.timings.duration < 1000 
  });

  // 현실적인 유저 대기 시간
  sleep(Math.random() * 2); 
}

 

3) 터미널에서 실행

k6 run [파일명]

4) 결과 확인 

먼저 첫 번째 부하테스트 결과를 확인하면 다음과 같다. 

  • 성공률 : 총 16,341번의 요청 중 단 한 번의 에러도 없었다. 서버가 죽지 않고 끝까지 모든 요청을 처리해냈다. 
  • 응답속도 : 부하테스트 설정 시에 유저가 0.5초 이내에 응답을 받기를 원했지만, 실제로는 4.3초나 걸렸다. 평균은 1.72초, 가장 오래 걸린 유저는 9.65초까지 기다렸다. 사용자가 지도를 켰는데, 4-9초 뒤에 가맹점이 뜬다는 상황으로 보인다. 
  • 주요 지표 분석 
    • `http_reqs` : 서버가 초당 약 45개의 요청을 처리했다. 
    • `data_received` : 테스트동안 서버로부터 약 49MB의 데이터를 받았다. 
    • `iteration_duration` : 유저 한 명이 요청을 보내고 `sleep`까지 포함해 한 사이클을 도는데 평균 3.22초가 걸렸다. 

두 번째 부하테스트 결과를 보면

인덱스 튜닝은 잘 이루어지고 있다는 것을 파악할 수 있다. 평균 응답 속도가 162ms라는 것은 db에서 데이터를 찾는 속도가 매우 비약적으로 개선되었다는 증거이다. 

  • 평균 응답 시간 : 162.54ms 
  • 95% 응답 시간 : 3884.26ms 
  • 최소 응답 시간 : 36.85ms
  • 최대 응답 시간 : 3.84s

그리고 세 번째 부하테스트는 다음과 같이 나온다. 

100명 규모에서도 잘 되는 것을 확인할 수 있다. 사용자 10명에서 

  • 평균 응답 시간 : 563ms 
  • 95% 응답 시간 : 1.17s
  • 초당 처리량 : 53.16s

결론 

사용자가 늘어남(10명 -> 100명)에 따라 지표가 384.26ms에서 1.17s로 약 3배 증가했다. 이는 특정 수준 이상의 동시 접속자가 발생할 경우, db 조회 외의 자원이 성능의 병목이 되고 있음을 시사한다. 또한 200명 규모 테스트에서는 응답 시간 역시 많이 튀며 현재의 단일 서버 사양으로는 200명의 동시 접속자가 유입되는 '피크 타임'을 안정적으로 감당하기에는 물리적 한계가 존재함을 확인했다. 

 

'프로젝트 > 끼니콩' 카테고리의 다른 글

대용량 데이터 (csv파일) db에 넣기 with JdbcTemplate -2  (0) 2025.12.19
[JVM] JVM GC 튜닝  (0) 2025.10.14
'프로젝트/끼니콩' 카테고리의 다른 글
  • 대용량 데이터 (csv파일) db에 넣기 with JdbcTemplate -2
  • [JVM] JVM GC 튜닝
erika0915
erika0915
백엔드 개발자가 되고 싶어요 .
  • erika0915
    erikoding
    erika0915
  • 전체
    오늘
    어제
    • 분류 전체보기 (78)
      • 프로젝트 (13)
        • 끼니콩 (3)
        • 덕메랑 (3)
        • handDoc (7)
        • Haeil (0)
      • Java (9)
        • 클린코더스 (0)
      • Spring (30)
      • Redis (3)
      • CS (7)
        • 운영체제 (3)
        • 컴퓨터구조 (0)
        • 네트워크 (4)
      • DevOps (2)
      • 코딩테스트 (0)
      • Tech (14)
        • TDD (1)
        • 정리 (5)
        • 우테코 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    docker
    AI
    도커
    깃
    운영체제
    MongoDB
    springboot
    파인튜닝
    코드레빗
    promtail
    자바
    레디스
    OS
    Network
    github
    java
    TDD
    CoolSMS
    STT
    네트워크
    몽고디비
    지라
    스프링부트
    jira
    깃허브
    coderabbit
    git
    Spring
    스프링
    redis
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
erika0915
[k6] 부하테스트

티스토리툴바