성능 테스트 기초
성능 테스트의 정의
성능 테스트는 특정 워크로드 하에서 시스템의 응답성, 안정성, 확장성, 자원 사용량을 측정하는 소프트웨어 테스트입니다. 기능이 올바르게 동작하는지를 확인하는 기능 테스트와 달리, 응답 시간/처리량/자원 사용률처럼 정량적으로 측정 가능한 비기능 요구사항을 검증합니다.
테스트를 실행하기 전에는 시스템의 비즈니스 목표부터 정의해야 합니다. 목표가 없으면 테스트 결과가 만족스러운 수준인지 판단할 기준 자체가 없기 때문입니다. 테스트를 실행한 뒤에는 가상 사용자 수, 초당 요청 수, 오류율, 응답 시간, latency, throughput 같은 지표와 그 지표들 사이의 상관관계를 분석해 병목(bottleneck)과 결함을 찾아냅니다.
성능 테스트의 목적
성능 테스트의 목적은 속도, 응답성, 안정성, 확장성, 자원 사용량 같은 비기능 속성을 측정하는 데 있습니다. 이를 통해 시스템이 정의된 성능 목표와 요구사항을 충족하는지 판단하고, 병목을 식별하며, 성능 회귀(regression)를 탐지합니다.
테스트 유형에 따라 얻을 수 있는 정보도 달라집니다. 부하 테스트는 정상 트래픽에서의 기준 성능을 제공하고, 스트레스 테스트는 시스템이 버틸 수 있는 한계와 실패 지점을 제공하며, 소크 테스트는 장시간 운영에서만 드러나는 문제를 제공합니다. 테스트 하나만으로는 전체 그림을 얻을 수 없기 때문에, 목적에 맞게 여러 유형을 조합해서 사용해야 합니다.
성능 테스트가 왜 필요한가
현대 애플리케이션은 한 곳에서만 장애를 일으키지 않습니다. 문제는 대개 서비스, 데이터베이스, 서드파티 시스템, 인프라가 동시에 상호작용하는 전체 워크플로우에서 나타납니다. 단위 테스트나 API 테스트는 이런 문제를 드러내지 못합니다. 데이터베이스 쿼리 하나는 단독으로 실행하면 문제없이 동작하지만, 수백 명이 동시에 같은 쿼리를 실행시키면 타임아웃을 일으킬 수 있습니다. 마이크로서비스도 개별 요청은 빠르게 처리하지만, 하위 의존 서비스가 느려지면 함께 저하됩니다.
성능 테스트가 필요한 이유는 다음과 같이 정리됩니다.
- 통합 지점의 문제 발견: 개별 컴포넌트가 아니라 전체 시스템이 함께 동작할 때만 드러나는
병목을 찾아냅니다. - 비용 절감: 개발 단계에서 발견한 성능 문제는 빠르게 수정할 수 있지만, 테스트 단계로 넘어가면 수정 비용이 약 15배로 늘어납니다.
- 비즈니스 영향 방지: 응답 시간이 1초인 사이트는 5초인 사이트보다 전환율이 약 3배 높습니다. 반대로 성능이 나쁘면 기술 지원 요청 증가, 평점 하락, 평판 손상으로 이어집니다.
- 프로덕션 장애 예방: 스테이징 환경에서 문제를 미리 잡으면, 고객 불만이나 모니터링 경보를 통해 문제를 뒤늦게 발견하는 상황을 막을 수 있습니다.
부하테스트와의 차이
부하 테스트(load test)와 성능 테스트를 단순 비교하는 것은 성립하지 않습니다. 성능 테스트는 부하 테스트, 스트레스 테스트, 소크(내구성) 테스트, 스파이크 테스트 등을 포괄하는 상위 개념이기 때문입니다.
부하 테스트는 예상되는 트래픽 조건에서 시스템이 어떻게 동작하는지 확인합니다. 가상 사용자 수 또는 초당 요청 수로 예상 부하를 가하고, 실제 측정값(응답 시간, 처리량, 오류율, 자원 사용량)을 기대치와 비교해 현재 빌드가 배포 가능한 상태인지 판단합니다.
스트레스 테스트는 다른 목표를 가집니다. 부하 테스트가 실제 운영과 유사한 부하를 재현하는 데 초점을 둔다면, 스트레스 테스트는 시스템의 포화점(saturation point)과 첫 병목을 찾아내는 데 초점을 둡니다. 이상적인 애플리케이션은 부하가 늘어날수록 처리량도 함께 늘어나고, 응답 시간은 유지되거나 캐싱/최적화 덕분에 오히려 줄어듭니다. 하지만 특정 지점을 넘어서면 가상 사용자를 늘려도 초당 요청 수가 정체되거나 오히려 줄어들며, 이 지점에서 오류가 발생하고 심하면 요청 처리 자체가 멈춥니다.
정리하면 부하 테스트는 "예상 트래픽에서 목표를 만족하는가"를 검증하고, 스트레스 테스트는 "한계는 어디이고 어떻게 무너지는가"를 검증합니다. 두 테스트는 도구와 방법론을 공유하지만, 답하려는 질문 자체가 다릅니다.
성능 테스트의 종류
성능 테스트는 하나의 테스트가 아니라, 서로 다른 질문에 답하는 여러 테스트 유형의 집합입니다.
부하 테스트(Load Test): 예상되는 실제 트래픽 규모에서 시스템 동작을 검증합니다. 응답 시간, 처리량, 자원 사용량에 대한 기준 성능을 제공합니다.스트레스 테스트(Stress Test): 정상 용량을 초과하는 부하에서 시스템이 어떻게 저하되고 회복하는지 확인합니다. 최대 부하 용량, 실패 지점, 복구 시간을 파악합니다.스파이크 테스트(Spike Test): 트래픽이 갑자기 급증했다가 빠르게 줄어드는 상황을 재현합니다. 급증 구간의 응답, 오류 처리, 복구 여부를 확인합니다.소크 테스트(Soak/Endurance Test): 정해진 부하를 몇 시간에서 며칠에 걸쳐 유지하며 메모리 누수, 커넥션 풀 고갈, 점진적인 성능 저하처럼 장시간 운영에서만 드러나는 문제를 찾아냅니다.확장성 테스트(Scalability Test): 부하나 자원이 늘어남에 따라 성능이 어떻게 변하는지 측정해, 수직/수평 확장 시 시스템이 비즈니스 요구를 따라갈 수 있는지 검증합니다.

실무에서는 대개 부하 테스트로 먼저 기준 성능을 확립한 뒤, 릴리스 전이나 예상되는 트래픽 이벤트(블랙 프라이데이, 마케팅 캠페인 등)를 앞두고 스트레스 테스트와 스파이크 테스트를 추가합니다. 소크 테스트는 커넥션 풀링, 캐싱, 세션 관리처럼 메모리에 영향을 주는 변경이 있을 때 주기적으로 수행하는 것이 일반적입니다.
SLA SLO SLI
성능 테스트의 통과/실패 기준은 임의로 정하는 숫자가 아니라, 서비스가 지켜야 할 SLO에서 그대로 도출됩니다. 예를 들어 SLO가 "P95 응답 시간 300ms 이하"라면, 부하 테스트의 합격 기준도 동일하게 "P95 300ms 이하"가 됩니다. SLI(Service Level Indicator), SLO(Service Level Objective), SLA(Service Level Agreement)는 이 기준을 정의하고 측정하는 세 가지 개념이며, 서로 포함 관계를 이룹니다.

SLA
SLA는 서비스 제공자와 사용자 사이에 맺는 계약입니다. 가동시간, 응답 시간 같은 특정 지표에 대한 약속과, 이를 어겼을 때의 책임(환불, 서비스 크레딧, 계약 해지 등)을 명시합니다. 주로 법무/비즈니스 팀이 작성하며, 유료 서비스에서만 사용됩니다.
SLO
SLO는 SLA를 지키기 위해 내부적으로 설정하는 목표입니다. 지표(metric), 목표치(target), 측정 기간(time window) 세 요소로 구성됩니다. SLA가 "월 가동시간 99.9% 이상"을 약속한다면, SLO는 "30일 동안 가동시간 99.9% 이상 유지"처럼 더 구체적인 내부 기준으로 번역됩니다. 이 경우 허용되는 다운타임은 월 43.2분입니다.
SLI
SLI는 SLO가 실제로 충족되고 있는지를 확인하는 측정값입니다. SLO가 "99.9% 가동시간"이라는 목표라면, SLI는 그 기간 동안 실제로 측정된 가동시간(예: 99.92%)입니다. SLI 값이 SLO 목표치 이상을 유지해야 SLA 위반을 피할 수 있습니다.
정리
세 개념의 관계는 다음과 같이 정리됩니다.
SLI: 실제 측정값 — 지금 얼마나 잘하고 있는가SLO: 내부 목표치 — 얼마나 잘해야 하는가SLA: 외부 계약 — 약속을 어기면 어떻게 되는가
SLO를 관리할 때 빠지지 않는 개념이 error budget(오류 예산)입니다. SLO가 99.99% 가동시간이라면 남은 0.01%가 곧 error budget이며, 30일 기준으로 약 4분의 허용 다운타임에 해당합니다. 이 예산은 신뢰성만 추구하느라 새 기능 배포나 실험을 멈추지 않도록, 팀에게 허용된 위험의 양을 알려주는 역할을 합니다.
핵심 지표
RPS TPS
RPS(Requests Per Second)는 초당 처리되는 HTTP 요청 수를 의미합니다. TPS(Transactions Per Second)는 초당 완료된 트랜잭션 수를 의미하며, 여기서 트랜잭션은 하나 이상의 요청으로 구성된 논리적 업무 단위입니다. 예를 들어 로그인 하나가 인증 요청, 세션 발급 요청, 프로필 조회 요청 3개로 이루어진다면, 이 로그인은 1개의 트랜잭션이지만 3개의 요청으로 집계됩니다.
처리량(Throughput)은 이 둘을 아우르는 상위 개념으로, 단위 시간당 시스템이 처리한 작업량을 뜻합니다. 초당 바이트 수, RPS, TPS 모두 처리량을 표현하는 방식입니다.
응답 시간과 Latency
응답 시간(Response Time)은 요청을 보낸 시점부터 응답을 완전히 받는 시점까지 걸리는 전체 시간입니다. 네트워크 왕복 지연, 서버 처리 시간, 응답 데이터 전송 시간을 모두 포함합니다.
latency는 더 포괄적인 지연 개념입니다. 네트워크 관점에서는 요청이 목적지에 도달하는 편도 지연이나, 다시 돌아오는 왕복 지연(RTT, Round-Trip Time)을 가리키는 경우가 많습니다. 다만 실무에서는 응답 시간과 같은 의미로 섞어 쓰이는 경우도 흔해서, 자료마다 정의가 조금씩 다를 수 있다는 점을 감안해서 읽어야 합니다.
응답 시간을 구간별로 나누면 다음과 같습니다.
TTFB(Time To First Byte): 요청을 보낸 시점부터 응답의 첫 바이트를 받는 시점까지의 시간입니다. 네트워크 지연과 서버가 응답을 준비하는 처리 시간이 여기 포함됩니다.응답 시간의 부분집합이며, 응답을 전부 받는 시간까지는 포함하지 않습니다.Content Download Time: 첫 바이트가 도착한 시점부터 전체 응답을 다 받는 시점까지의 시간입니다. 응답 크기와 대역폭에 좌우됩니다.평균 응답 시간: 전체 응답 시간의 합을 요청 수로 나눈 값입니다.

다만 평균만 보고 판단하면 위험합니다. 소수의 극단적으로 느린 요청이 평균에 묻혀 사라지기 때문입니다. 그래서 실무에서는 평균과 함께 반드시 Percentile을 함께 확인합니다.
Percentile
Percentile(백분위수)은 전체 요청 중 특정 비율이 어느 응답 시간 이하로 완료됐는지를 나타내는 지표입니다. P95 응답 시간이 400ms라면, 전체 요청의 95%가 400ms 이하로 처리됐고 가장 느린 5%만 그보다 오래 걸렸다는 뜻입니다.
주요 백분위수는 다음과 같이 해석됩니다.
P50(중앙값): 사용자 절반은 이보다 빠르고, 절반은 이보다 느립니다.P90: 가장 빠른 일부를 제외한, 대다수 사용자가 체감하는 속도를 보여줍니다.P95: SLO/SLA에서 가장 흔히 기준으로 삼는 지표입니다. 느린 5%는 이 기준 밖에 있습니다.P99: 가장 느린 1%, 즉 사용자가 실제로 겪는 최악의 경험을 보여줍니다. GC, DB 경합, 네트워크 문제로 인한tail latency가 여기서 드러납니다.

평균이 건강해 보여도 P99가 나쁘면, 소수의 실사용자가 심각하게 느린 경험을 하고 있다는 뜻입니다. 서비스 규모가 커질수록 이 소수는 실제로는 수천 명 단위가 될 수 있습니다.
백분위수를 다룰 때 흔한 실수는 백분위수 자체를 평균 내는 것입니다. 여러 서버의 P99를 단순 평균하면 수학적으로 의미 없는 값이 나옵니다. 정확한 집계를 위해서는 HDR 히스토그램처럼 전체 분포를 보존하는 방식으로 병합해야 합니다.
동시 사용자와 VU
동시 사용자(Concurrent Users)는 특정 시점에 시스템을 동시에 사용하고 있는 실제 사용자 수를 의미합니다. VU(Virtual User)는 부하 테스트 도구가 실제 사용자를 흉내 내기 위해 만들어내는 가상의 스레드/프로세스를 의미합니다.
두 개념은 밀접하지만 다른 층위에 있습니다. VU는 부하를 발생시키는 시뮬레이션 주체이고, 동시 사용자는 그 VU들이 특정 시점에 얼마나 많이 활성 상태인지를 나타내는 결과값입니다. 즉 VU로 동시 사용자를 흉내 냅니다.
VU와 동시 사용자의 관계
VU는 테스트 스크립트의 반복(iteration)을 개별적으로, 동시에 실행하는 시뮬레이션된 사용자입니다. k6 기준으로 보면 VU 하나는 시나리오를 계속 반복 실행하는 병렬 while(true) 루프이며, 각 VU는 한 번에 하나의 반복만 실행하는 단일 스레드 구조로 동작합니다.
VU를 구현하는 방식은 도구마다 다릅니다. JMeter처럼 VU 하나를 OS 스레드 하나로 구현하는 도구는 VU 수가 늘어날수록 로드 제너레이터 자체의 CPU/메모리 소비가 급격히 커집니다. k6나 Gatling처럼 스레드보다 가벼운 방식으로 VU를 처리하는 도구는 같은 하드웨어로 훨씬 많은 VU를 동시에 굴릴 수 있습니다. 다만 VU를 늘리는 것 자체도 CPU/메모리 비용이 들기 때문에, 테스트 도중 VU를 계속 추가하면 로드 제너레이터가 과부하되어 결과가 왜곡될 수 있다는 점은 어떤 도구든 마찬가지입니다.
VU 수와 동시 사용자 수가 항상 같은 값은 아닙니다. VU 하나는 시나리오를 반복 실행하는 동안 요청을 보내는 시간과 Think Time으로 쉬는 시간을 오갑니다. Think Time이 길수록 VU는 대부분의 시간을 대기 상태로 보내고, 실제로 서버에 요청을 보내는 순간은 짧아집니다. 그래서 100개의 VU를 투입했다고 해서 항상 서버 입장에서 100명이 동시에 요청하는 것은 아니며, 그 관계는 시나리오의 Think Time과 워크로드 모델에 따라 달라집니다.
부하를 설계하는 방식도 이 관계에 영향을 줍니다. VU를 시스템에 투입하는 방식은 워크로드 모델(workload model)에 따라 달라집니다.
오픈 모델(Open Model): 현재 시스템에 얼마나 많은 사용자가 남아있는지와 무관하게, 정해진 비율로 새 VU를 계속 유입시킵니다. 서버가 느려지더라도 목표한 요청률을 유지하기 위해 필요한 만큼 VU를 동적으로 추가/해제하므로, "초당 얼마나 많은 요청이 들어오는가"를 재현하는 데 적합합니다. 사용자가 응답을 기다리지 않고 계속 유입되는 실제 웹 트래픽 상황을 재현합니다.닫힌 모델(Closed Model): 동시 사용자 수를 고정값으로 유지하며, 기존 VU가 빠져나가야 새 VU가 들어옵니다. 반복 실행 속도가 응답 시간에 따라 자연스럽게 달라지므로, "몇 명이 쓰고 있는가"를 재현하는 데 적합합니다. 사용자 풀이 제한된 사내 시스템 같은 상황을 재현합니다.
같은 처리량이라도 어떤 모델을 쓰느냐에 따라 시스템에 가해지는 실제 압력이 달라지기 때문에, 테스트 목적에 맞는 모델을 선택해야 합니다.

자원 사용률
자원 사용률(Resource Utilization)은 시스템이 부하를 처리하는 동안 CPU, 메모리, 디스크 I/O, 네트워크 같은 인프라 자원을 얼마나 소비하는지를 나타냅니다. 클라이언트 쪽에서 측정하는 응답 시간/처리량이 증상을 보여준다면, 자원 사용률은 그 증상의 원인을 보여줍니다.
주요 자원 지표는 다음과 같습니다.
CPU 사용률: (1 - 유휴 시간 / 전체 시간) × 100으로 계산합니다. 지속적으로 80%를 넘기면 응답 시간이 가파르게 증가하기 시작합니다. 60% 미만을 안전, 60~80%를 경고, 80% 이상 지속을 위험 구간으로 보는 것이 일반적인 기준입니다.메모리 사용률: 사용 중인 메모리 / 전체 메모리 × 100으로 계산합니다. 힙 메모리가 가비지 컬렉션 주기마다 완전히 회복되지 않고 계속 쌓이면 메모리 누수를 의심할 신호입니다.디스크 I/O: 디스크에 데이터를 읽고 쓰는 속도입니다. 데이터베이스 중심 시스템에서는 CPU보다 먼저 병목이 되는 경우가 많습니다.네트워크 사용률: 로드 제너레이터와 테스트 대상 사이의 연결 상태, 재전송률, 왕복 시간(RTT)을 포함합니다. 이 값이 높으면 애플리케이션이 아니라 네트워크 자체를 측정하고 있는 것일 수 있습니다.
자원 사용률은 테스트 도중 반드시 클라이언트 지표와 함께 관찰해야 합니다. 클라이언트 쪽 P99 응답 시간이 튀는 시점과 서버 쪽 CPU 포화 시점이 겹친다면, "느리다"는 증상이 "이 서버가 병목이다"라는 원인으로 좁혀집니다.
오류 유형
오류율(Error Rate)은 실패한 요청의 비율이지만, 단일 숫자로만 보면 원인을 진단하기 어렵습니다. 오류를 유형별로 나눠 봐야 병목의 위치를 좁힐 수 있습니다.
4xx: 클라이언트 쪽 오류입니다. 잘못된 요청, 인증 실패, 유효하지 않은 파라미터처럼 클라이언트가 보낸 요청 자체에 문제가 있는 경우입니다. 급증한다면 테스트 스크립트나 API 스펙 변경을 먼저 의심해야 합니다.5xx: 서버 쪽 오류입니다. 애플리케이션 예외, 자원 고갈, 설정 오류처럼 서버가 요청을 처리하는 과정에서 실패했다는 뜻입니다. 소수라도 발생하면 반드시 원인을 조사해야 합니다.Connection Timeout: 서버와 TCP 연결 자체를 맺지 못해 발생하는 오류입니다. 커넥션이 거부되거나 핸드셰이크가 완료되지 못한 경우로, 서버가 다운됐거나 연결 큐가 가득 찼을 가능성을 가리킵니다.Read Timeout: 연결은 맺었지만 정해진 시간 안에 응답을 받지 못해 발생하는 오류입니다. 서버가 요청을 처리하는 데 너무 오래 걸리고 있다는 신호입니다.
4xx와 5xx, Connection Timeout과 Read Timeout은 원인이 완전히 다르기 때문에, 오류율을 하나의 숫자로만 보지 않고 엔드포인트/상태 코드/오류 유형별로 나눠서 관찰해야 실제 병목을 좁혀갈 수 있습니다.
병목과 시스템 한계
병목
병목(Bottleneck)은 시스템의 처리량, 응답 시간, 확장성을 제한하는 특정 지점입니다. 시스템 전체가 아니라 자원 하나 — 느린 데이터베이스 쿼리, 메모리 누수, 네트워크 혼잡, 비효율적인 알고리즘 등 — 가 전체 성능을 끌어내립니다. 병목이 되는 자원을 해소하기 전까지는 다른 자원을 아무리 늘려도 전체 성능은 개선되지 않습니다.
병목을 찾을 때는 클라이언트 지표(응답 시간, 오류율)로 증상을 먼저 확인하고, 서버 지표(CPU, 메모리, 디스크 I/O, 네트워크)로 원인을 좁혀갑니다. 부하를 걸어 시스템을 시뮬레이션하고, 지표를 관찰하며 이상치/추세/상관관계를 baseline과 비교하는 것이 일반적인 절차입니다.
포화점
포화점(Saturation Point)은 부하를 계속 늘려도 처리량이 더 이상 증가하지 않는 지점입니다. 가상 사용자를 계속 추가해도 초당 요청 수가 정체되거나, 응답 시간이 늘어나면서 오히려 줄어들기 시작합니다. 이 지점에서 CPU, 커넥션 풀, 스레드 풀 같은 특정 자원이 이미 한계에 도달해, 더 이상 추가 부하를 받아들이지 못하는 상태가 됩니다.
포화점을 파악하는 것은 클라우드 환경에서 특히 중요합니다. 디스크 용량, IOPS, 네트워크 트래픽 단위로 과금되는 환경에서는, 시스템이 과도하게 프로비저닝되지도 부족하지도 않은 최적의 운영 지점을 찾는 기준이 되기 때문입니다.
변곡점
변곡점(Knee Point)은 처리량-응답 시간 곡선에서 처리량 증가세가 꺾이고 지연이 급격히 늘어나기 시작하는 지점입니다. 성능 곡선은 대개 세 구간으로 나뉩니다. 부하가 늘어도 응답 시간이 안정적인 평탄 구간, 처리량 증가세가 꺾이기 시작하는 변곡 구간, 처리량은 거의 늘지 않으면서 지연만 기하급수적으로 증가하는 지수 구간입니다.
변곡점은 시스템의 최적 운영 임계값을 나타냅니다. 이 지점을 넘어서 운영하면, 부하를 더 받아도 처리량 이득은 거의 없이 지연만 계속 늘어나는 비효율적인 상태가 됩니다. 그래서 실무에서는 시스템을 변곡점 근처, 또는 그 이전에서 운영하는 것을 목표로 삼습니다.

Breaking Point
Breaking Point는 시스템이 더 이상 정상적으로 동작하지 못하고 실패하는 부하 지점입니다. 응답 시간이 폭증하거나, 오류율이 급증하거나, 요청 처리 자체가 멈추는 시점입니다. 스트레스 테스트는 이 지점을 의도적으로 찾기 위해, 예상 부하를 훨씬 초과하는 수준까지 부하를 계속 끌어올립니다.
Breaking Point를 찾는 과정에서는 다음을 함께 확인합니다.
- 정확히 어떤 자원(DB 커넥션 한도, 스레드 풀 고갈, API 레이트 리미터 등)이 한계를 만들었는지
- 시스템이 완만하게 성능을 낮추며 버티는지, 아니면 그대로 크래시하는지
- 부하를 걷어냈을 때 얼마나 빨리 정상 상태로 회복하는지
Breaking Point는 병목/포화점/변곡점과 달리 통과/실패를 가리는 값이 아니라, 시스템의 한계와 그 이후 회복 능력을 파악하기 위한 탐색 지점입니다.
시나리오 설계 개념
리틀의 법칙
리틀의 법칙(Little's Law)은 대기행렬 이론에서 나온 공식으로, 시스템 안에 있는 요청 수와 처리량, 응답 시간 사이의 관계를 나타냅니다. 부하 테스트에 적용하면 다음처럼 씁니다.
N = X × (R + Z)
N: 동시 사용자 수X: 처리량(초당 요청 수)R: 평균 응답 시간Z:Think Time(사용자가 요청 사이에 쉬는 시간)
이 공식이 실무에서 쓸모 있는 이유는, 네 값 중 셋만 알아도 나머지 하나를 역산할 수 있기 때문입니다. 예를 들어 시간당 세션 수와 평균 세션 지속 시간을 안다면, 별도의 부하 도구 없이도 동시 사용자 수 = 시간당 세션 수 × 평균 세션 지속 시간(초) / 3600이라는 식으로 목표 동시 사용자 수를 추정할 수 있습니다. 이렇게 추정한 값은 특정 순간의 평균일 뿐이므로, 실제 테스트 목표치는 평균이 아니라 트래픽이 가장 몰리는 피크 구간을 기준으로 잡아야 합니다.
Think Time과 Ramp-up
Think Time은 실제 사용자가 요청과 요청 사이에 머무는 시간을 의미합니다. 실제 사용자는 페이지를 읽거나 폼을 채우는 동안 서버를 끊임없이 두드리지 않습니다. Think Time 없이 가상 사용자가 요청을 곧바로 연속해서 보내면, 실제로는 발생하지 않을 만큼 비현실적으로 높은 부하가 만들어집니다. 그래서 실무에서는 고정된 지연이 아니라 편차가 있는 Think Time을 넣어, 실제 사용자 행동의 변동성을 재현합니다.
Ramp-up은 목표 동시 사용자 수까지 부하를 끌어올리는 구간입니다. 전체 테스트 시간의 5~15% 정도를 차지하는 것이 일반적이며, 시스템이 트래픽에 맞춰 워밍업하거나 오토스케일링할 시간을 벌어줍니다. 사용자를 한꺼번에 투입하면 실제로는 일어나지 않을 만큼 급격한 부하가 걸리므로, 점진적으로 늘리는 Linear Ramp-up이나 일정 구간마다 계단식으로 늘리는 Step Ramp-up 방식을 씁니다. Ramp-up이 끝나고 목표 부하를 유지하는 구간은 Hold Time이라고 부르며, 이 구간에서 시스템이 부하를 견디며 성능이 안정적으로 유지되는지 확인합니다.
Ramp-up 구간에서 이미 응답 시간이 나빠지기 시작한다면, 목표 부하에 도달하기도 전에 시스템이 한계에 가까워지고 있다는 신호입니다.
Warm-up과 Cold Start
Warm-up은 실제 측정을 시작하기 전에, 시스템이 안정적인 상태(steady state)에 도달할 때까지 미리 부하를 가하는 구간입니다. JVM 기반 시스템이 대표적인 예입니다. JVM은 시작 직후 인터프리터 모드로 실행되다가, JIT 컴파일러가 자주 실행되는 코드를 점진적으로 컴파일하고, 가비지 컬렉터도 실제 할당 패턴에 맞춰 적응해갑니다.
이렇게 아직 최적화가 끝나지 않은 시작 직후 상태를 Cold Start라고 부릅니다. 이 구간에서는 지연 시간이 인위적으로 높게, 처리량은 인위적으로 낮게 측정되고 GC 정지도 불규칙하게 튑니다. 실제 운영 중 상태와는 다르게 동작하기 때문에, 이 구간의 데이터를 그대로 테스트 결과에 포함시키면 시스템의 실제 성능이 아니라 Cold Start의 특성을 측정하게 됩니다.
그래서 실무에서는 목표 부하로 2~5분 정도 Warm-up을 돌리고, 이 구간의 측정값은 모두 버린 뒤, 지연 시간/처리량/GC 동작이 안정된 뒤부터 실제 측정을 시작합니다. 고정 힙 크기(-Xms, -Xmx) 설정이나 G1 가비지 컬렉터, 티어드 컴파일 같은 JVM 튜닝 옵션은 이 Warm-up 구간의 변동성을 줄이는 데 도움이 됩니다.

Reference
- Functional Testing vs. Performance Testing: Why Use Both? - Perforce BlazeMeter
- Why Performance Testing Is Important - Perforce BlazeMeter
- Performance Testing vs. Load Testing vs. Stress Testing - Perforce BlazeMeter
- Stress Testing, Soak Testing and Spike Testing Best Practices - Perforce BlazeMeter
- End-to-End Performance Testing - Gatling
- Load Testing vs Stress Testing: Key Differences (2026 Guide) - Gatling
- What's the Difference Between SLAs, SLOs and SLIs? - PagerDuty
- What are Service-Level Objectives (SLOs)? SLO vs. SLA vs. SLI - Atlassian
- 10 Performance Testing Metrics to Watch Before You Ship - Gatling
- Key Performance Test Metrics to Track - Perforce BlazeMeter
- Workload Models in Load Testing - Gatling
- Bottleneck Testing: What It Is & How It Works - Perforce BlazeMeter
- Performance Bottlenecks: How to Avoid Them - Gatling
- What Is Stress Testing? - Gatling
- How to Calculate Concurrent Users in Performance Testing With Google Analytics - Perforce BlazeMeter
- Calculate Concurrent Users for Load Tests - Grafana k6 Docs
- JMeter Ramp Up Period: The Ultimate Guide - Perforce BlazeMeter
- A Comprehensive Guide to Using JMeter Timers - Perforce BlazeMeter
- Scaling Load Tests the Right Way with Gatling
- Reference Glossary of Gatling Concepts - Gatling Docs
- API Load Testing - Grafana k6 Docs
- Latency Percentiles for Load Testing Analysis - Gatling
- Open and Closed Models - Grafana k6 Docs
- Error Codes - Grafana k6 Docs
- Scenarios - Grafana k6 Docs
- Executors - Grafana k6 Docs
- Arrival-rate VU allocation - Grafana k6 Docs
- Constant VUs - Grafana k6 Docs
- Ramping VUs - Grafana k6 Docs
- Shared Iterations - Grafana k6 Docs
- Per VU Iterations - Grafana k6 Docs
- Constant Arrival Rate - Grafana k6 Docs
- Ramping Arrival Rate - Grafana k6 Docs