성능 테스트(Performance Testing)는 우리가 제작한 웹 애플리케이션의 효율성과 안정성을 평가하는데 핵심적인 역할을 한다. 성능 테스트를 통해 애플리케이션의 견고함을 검증하고 사용자 경험을 최적화하는 단계를 밟을 수 있기 때문이다. 이번 포스팅에서는 성능 테스트 도구 중 하나인 k6에 대해 알아보고자 한다.
< 목차 >
- k6
- Installation & Testing
- 기본 개념
- 테스트 결과 해석
1. k6
k6는 성능 테스트를 위한 오픈 소스 도구로 API, 마이크로서비스 아키텍쳐를 가진 시스템, 웹 사이트 등과 같은 다양한 웹 서비스들의 성능 측정과 부하 테스트에 사용된다. k6를 사용하면 사용자가 실제로 웹 사이트에 방문하거나 API를 호출할 때 발생할 수 있는 다양한 시나리오를 시뮬레이션하여 서비스가 예상한 것만큼의 사용자 트래픽을 처리할 수 있는지 확인할 수 있다. 이를 통해 개발자는 시스템의 성능이 요구사항을 충족하는지 또는 특정 부하 하에서 어떤 지점에서 병목현상이 발생하는지 등을 파악할 수 있다.
k6 외에도 다음과 같은 유명한 성능 테스트 도구들이 있으니 참고하면 좋을 듯 하다.
- JMeter
- Gatling
- Locust
2. Installation & Testing
👉 MacOS
MacOS를 사용한다면 Homebrew를 통해 간단하게 설치할 수 있다.
## 설치
$ brew install k6
## 설치 확인
$ k6 version
👉 Windows
https://k6.io/docs/get-started/installation/
Simple Testing
k6 설치를 완료했다면 간단한 테스팅을 진행해 보도록 하자. 우선 Visual Studio Code 혹은 본인이 사용하고 있는 코드 에디터를 열어서 Javascript 파일을 하나 생성해준다. (참고로 k6는 Javascript 기반으로 스크립트를 작성하기 때문에 기본적인 Javascript 문법은 숙지하고 있어야 한다)
// script.js
import http from 'k6/http';
export default function() {
http.get('https://test.k6.io')
}
위의 스크립트는 단일 사용자가 "https://test.k6.io"에 대해 요청을 보내는 간단한 테스트 예제이다. 여기서 "https://test.k6.io"는 k6에서 제공하는 간단한 테스트 웹사이트이다.
스크립트를 작성했다면, 아래 명령어를 통해 테스트를 진행해 보도록 하자. 테스트 실행 결과가 출력되는 것을 확인할 수 있을 것이다.
## Run
$ k6 run [filename].js
3. 기본 개념
테스트 결과를 살펴보면 VUs를 포함하여 http_reqs, iterations 등과 같은 용어들이 나온다. 테스트를 진행했다고 한들 출력된 결과물을 해석할 수 없다면 무용지물이 되는 셈이다. 성능 테스트를 진행할 때 자주 등장하는 용어들의 개념에 대해 정리하고 넘어가도록 하자.
👉 VUs
VUs는 실제 사용자를 모방한 가상 사용자(Virtual Users)를 의미한다. VUs를 통해 웹 사이트나 애플리케이션의 동시 접속 능력을 테스트 할 수 있다. 예를 들어 가게를 소유하고 있다고 가정해보자. 가게에 물건을 사러 들어오는 사람 각각은 웹 사이트를 방문하는 사용자와 같다. 그리고 가게를 방문하는 사람은 한 사람이 아닌 100명, 1000명 혹은 그 이상이 될 수도 있다. 이러한 동시 방문자를 모방한 것이 k6에서의 VUs, "가상 사용자"이다. k6에서 VUs를 통해 동시 방문자들을 시뮬레이션하여 웹 사이트가 얼마나 많은 사용자들을 동시에 처리할 수 있는지 평가할 수 있다.
👉 Requests
가게에서 물건을 요청하는 것처럼 웹 사이트에서 텍스트, 그림 혹은 동영상을 클릭할 때마다 우리의 컴퓨터는 웹 사이트의 서버에 해당 항목을 요청한다. Requests는 사용자가 웹 사이트의 요소에 접근할 때 서버에 보내는 요청으로 성능 테스트에서 이러한 요청들은 웹 사이트의 응답 시간과 처리 능력을 측정하는데 중요한 역할을 한다.
👉 Latency
가게 주인에게 물건을 요청했다고 해서 물건이 바로 바로 내 눈앞에 나타나는 것은 아니다. 물건을 요청하고 받는데까지 시간이 걸리는 것처럼 서버에 보내진 요청들에 대한 응답 역시 시간이 소요된다. Latency는 이처럼 요청을 보내고 응답을 받는데까지 걸리는 시간을 의미한다. latency가 짧을수록 사용자 경험은 더 좋아지며, 긴 latency는 사용자의 불만을 초래할 수 있다. 성능 테스트에서는 이 latency를 측정하여 웹 사이트가 얼마나 빠르게 응답하는지를 평가할 수 있다.
👉 Throughput
가게 주인이 시간당 얼마만큼의 고객을 응대할 수 있는지에 따라 주인의 능력이 평가된다. 이처럼 웹 사이트 역시 특정 시간 동안 처리할 수 있는 요청의 수가 있다. Throughput은 일정 시간 동안 처리할 수 있는 요청의 수를 의미하며 높은 throughput은 웹 사이트가 많은 사용자를 효과적으로 처리할 수 있음을 의미한다. 성능 테스트에서는 웹 사이트의 throughput을 측정하여 동시에 얼마만큼의 사용자를 처리할 수 있는지 그 능력을 평가한다.
👉 Iterations
가게 주인에게 특정 물건을 여러 번 보여달라고 요청하는 것처럼 성능 테스트에서 "iterations"는 동일한 요청 또는 작업을 여러 번 반복하는 것을 의미한다. 예를 들어, 로그인 프로세스를 여러 번 반복하여 웹 사이트가 반복된 로그인 시도를 어떻게 처리하는지 평가할 수 있다. 같은 작업을 여러 번 반복함으로써 시스템의 반복 작업 처리 능력을 평가할 수 있는 것이다.
4. 테스트 결과 해석
앞선 테스트와 달리 k6의 옵션을 설정하면 다양한 성능 측정 시나리오를 구성할 수 있다. 예를 들어, 다음과 같이 VUs 수와 테스트 지속 시간을 지정하여 복잡한 사용자 행동을 시뮬레이션 해볼 수도 있다.
import http from 'k6/http';
// additional options
export const options = {
vus: 10,
duration: '10s',
};
export default function () {
http.get('https://test.k6.io');
}
다음은 위의 스크립트를 실행한 결과물로 10명의 가상 사용자(vus: 10)를 10초 동안(duration: '10s') 사용한 결과물이다.
Iterations를 살펴보면 497이 출력된 것을 확인할 수 있다. 10초 동안 10명의 가상 사용자를 사용하여 497번의 반복을 수행한 것이다. 이는 'https://test.k6.io'로 요청을 보내는 함수가 497번 실행되었음을 의미한다. 또한 http_reqs를 살펴보면 해당 값 역시 497인 것을 확인할 수 있다. 이는 497번의 요청(requests)을 수행한 것으로 리다이렉션(redirection)이 없고 단일 주소를 호출하는 경우에는 iterations(반복 횟수)와 http_reqs(요청 수)가 동일한 값을 갖게 된다.
여기서 한 가진 의문점은 "10초 동안 10명의 가상 사용자가 왜 10번의 요청만 보내지 않았는가?" 이다. 이는 k6가 가상 사용자들로 하여금 작성된 함수를 가능한 한 많이 실행시키도록 하기 때문이다. 예를 들어, vus를 10이 아닌 1로 설정한다고 할지라도 한 명의 가상 사용자는 http.get() 요청이 완료될 때까지 기다린 다음 다시 함수를 실행시키는 과정을 반복하게 된다. 이러한 일련의 과정은 할당된 시간(duration) 내에 가능한 한 많이 반복된다. 하지만 실제 사용자처럼 시뮬레이션을 하고자 한다면 함수 호출 사이 사이에 어느 정도의 인터벌을 갖는 것이 필요하다. 실제 사용자는 10초 안에 가능한 한 많이 반복적으로 해당 주소를 호출하지 않을 것이기 때문이다. 이 때 사용하는 것이 바로 sleep() 함수이다. sleep() 함수를 사용할 경우, 사용자는 인자값으로 전달된 시간(초)동안 기다리게 된다.
import http from 'k6/http';
import { sleep } from 'k6';
// additional options
export const options = {
vus: 1,
duration: '10s',
};
export default function () {
http.get('https://test.k6.io');
sleep(1); // sleep takes a number in seconds
}
k6는 테스트 실행 후 http_req_duration, http_reqs, iterations 등과 같은 다양한 측정 항목들을 수집하여 애플리케이션의 성능을 다각도로 분석할 수 있게 도와준다. 여기서는 다양한 지표들 중 http_req_duration에 대해서만 조금 더 알아보도록 하자.
👉 http_req_duration
요청을 보낸 후 응답을 받을 때까지 걸린 시간을 측정한 것으로 해당 항목의 평균(avg), 최소값(min), 중앙값(med), 최대값(max), 백분위수가 나와있다. 여기서 우리는 백분위수에 주목하는 것이 중요하다. p(90), p(95)와 같은 백분위수를 통해 우리는 얼마만큼의 요청들이 특정 시간 내에 완료되었는지를 확인할 수 있기 때문이다.
- p(90) = 191.41ms
- 'p'는 percentile(백분위수)를 의미한다
- 이는 90%의 요청이 주어진 지연 시간 이하로 처리되었음을 의미한다
- p(90) = 191.41ms → 90%의 요청이 191 밀리초 이하로 처리되었다
많은 사람들이 평균값을 우선적으로 바라보곤 한다. 하지만 단순한 평균보다는 백분위수를 바라보는 것이 중요할 때가 많다. p(90), p(95)와 같은 백분위수는 시스템 성능의 일관성과 신뢰성을 평가하는데 유용한 지표가 된다. 평균은 단지 몇 개의 느린 요청만으로도 값이 왜곡될 수 있기 때문에 백분위수가 전체 사용자 경험을 더 정확하게 반영한다고 볼 수 있다.
'Testing' 카테고리의 다른 글
k6 - 성능 테스트 유형 (0) | 2024.01.04 |
---|