Web

[Web] 성능테스트에 대하여(with K6)

MarrRang 2024. 11. 29. 09:27

최근에 K6를 사용한 부하테스트를 진행한 경험이 있었습니다. 진행하면서 알게된 사실들을 정리해보려 합니다.

 

주요 용어

Response Time - 응답시간

사용자의 요청(Request)이 발생하고 시스템이 응답(Response) 할때 까지의 시간

Request Interval - 요청주기(Think time)

사용자가 시스템에 방문 후 요청을 발생 시키는 주기

참조: https://dewble.tistory.com/entry/concept-of-performance-test

 

참조: https://dewble.tistory.com/entry/concept-of-performance-test

Throughput - 처리량

시스템이 주어진 시간 동안 처리할 수 있는 작업의 양을 측정하는 중요한 성능 지표
단위는 tps, pps, rps, hit/sec 등등이 있다.

 

참조: https://dewble.tistory.com/entry/concept-of-performance-test

Saturation Point - 임계점

시스템이 처리할 수 있는 최대 성능에 도달했을 때를 나타내는 지점

부하 테스트에서 임계점을 파악하는 것은 시스템의 한계를 이해하고 최적의 성능 수준을 유지하기 위해 매우 중요

참조: https://dewble.tistory.com/entry/concept-of-performance-test

K6

K6는 성능 테스트(Performance Testing)와 부하 테스트(Load Testing)를 위한 오픈소스 도구.

특히, 개발자 친화적인 설계로 유명하며, 스크립트를 작성하고 실행하는 데 JavaScript를 사용합니다. 시스템의 안정성과 확장성을 평가하는 데 적합합니다.

K6 주요 특징

 

  • JavaScript 기반 스크립트
    • K6는 JavaScript와 ES6+ 문법을 지원
    • JSON과 같은 데이터를 처리하기 용이하여, REST API 또는 GraphQL 테스트에 적합
  • 개발자 친화적
    • 코드를 기반으로 테스트를 정의하므로, 개발자들이 기존 워크플로우에 쉽게 통합 가능.
  • 경량 및 빠른 실행
    • Go 언어로 구현되어 매우 빠름.
    • 실행 속도가 빠르며 메모리 사용량이 적습니다.
  • 풍부한 기능
    • HTTP/HTTPS 요청 지원.
    • WebSocket, gRPC, Kafka와 같은 다양한 프로토콜 지원(플러그인을 통해 확장 가능).
    • 내장 통계 및 커스터마이징 가능한 보고 기능.
  • 확장 가능
    • 클라우드 또는 온프레미스에서 실행 가능.
    • 대규모 부하 테스트를 위해 클러스터를 쉽게 확장할 수 있음.

 

테스트 과정

테스트 과정을 간단하게 정리하자면 아래와 같습니다.

 

1. 테스트 항목 선정

  • 호출이 많이 되는 서비스 API
  • 로직 상 부하가 예상되는 API
  • ...

2. 각 항목에 대한 적절한 통과 지표 설정

3. 스크립트 작성 및 지표 확인

4. API 개선

 

 

스크립트 예시

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

import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";

// 테스트 수행 시나리오 및 옵션 설정
export const options = {
    systemTags: ['scenario', 'status', 'method'],
    scenarios: {
        constant_request_rate: {
            executor: 'constant-arrival-rate',
            rate: 600,
            timeUnit: '1s',
            duration: '1m',
            preAllocatedVUs: 720,
            maxVUs: 900,
        },
    },
    tags: {
        name: 'example-content',
    },
    summaryTrendStats: ['avg', 'min', 'med', 'max', 'p(95)', 'p(99)', 'count'],
};

export function setup() {
    return createAuthToken(bz_r);
}

export function executeTest(data) {
    ... // 주요 테스트 내용
}

export function handleSummary(data) {
    console.log(textSummary(data, { indent: " ", enableColors: true }))

    return {
        "summary.html": htmlReport(data)
    };
}

export default function (data) {
    executeTest(data);
};

 

 

성능 개선 방향

 

  • 수평 확장 (Horizontal Scaling):
    • 더 많은 서버를 추가해 부하를 분산.
    • 예: 로드 밸런서와 함께 다중 서버 구성.
  • 수직 확장 (Vertical Scaling):
    • 서버의 하드웨어 성능(CPU, 메모리 등)을 업그레이드.
  • 병목 자원 최적화:
    • 캐싱 활용, 데이터베이스 쿼리 최적화, 효율적인 코드 작성.
  • 부하 분산:
    • 요청을 여러 서버로 나눠 처리.
    • 예: CDN(Content Delivery Network) 활용.
  • 큐잉 시스템 도입:
    • 급격히 증가하는 요청을 큐에 저장하고 순차적으로 처리.
  • 비동기 처리:
    • 느린 작업을 비동기적으로 처리해 응답 속도 개선.

정리

성능테스트를 진행하면서 어떤 것이 중요한 포인트인가에 대해서 생각하게 되는 계기가 있었습니다. 성능테스트에 대해서 여러 의견을 나누던 중 2가지 의견이 있었습니다.

 

1. 성능테스트에서는 특정 API를 통해 단일 어플리케이션과 서버가 견딜 수 있는 최대 성능을 계산해서 그 값으로 앞으로의 트래픽에 대응하는 것이 중요하다.

2. 결국 서비스 시에는 여러 복합적인 요청을 서버가 처리하고 그 처리들이 동시에 이루어졌을 때를 대비해야하고 그러니 최대 성능을 계산하는 것보다는 req_duration을 원하는 범위 내로 들어오게 하는게 더 중요하다.

 

물론 둘 다 맞는 얘기 입니다. 1번은 서버를 효율적으로 관리하는 측면, 2번은 사용자 경험을 중요시 하는 측면에서 맞는 의견이라고 보여집니다.

다만, 저는 서비스의 비즈니스 요건을 충족하는 것과 우선은 사용자의 경험이 중요하다고 생각해 2번의 의견에 손을 들었습니다. 결국 서비스는 사용자가 없다면 아무 소용이 없으니까요.

반응형