[Test] 분산테스트(Locust)의 사용자 수를 늘리면 무조건 좋을까?

조시현·2025년 5월 16일
post-thumbnail

Locust 사용자 수 늘리면 성능이 올라간다고요?

저는 Locust 사용자 수를 200으로 올렸더니 RPS가 떨어졌습니다. 왜 이런 현상이 생겼을까요?

부하 테스트를 처음 시작하면 대부분 한 가지 가정을 하게 됩니다.
바로 "사용자 수를 늘리면 더 많은 요청이 발생하고, 따라서 RPS도 자연스럽게 증가할 것이다"라는 믿음입니다.

저 또한 처음에는 같은 생각을 했습니다. 실제 서비스에서 수백, 수천 명의 사용자가 동시에 접속하는 상황을 상상하며, Locust의 사용자 수를 늘리는 것으로 그 상황을 재현하려 했습니다. 하지만 결과는 완전히 달랐습니다.

처음엔 사용자 수를 늘리면 성능이 당연히 좋아질 거라 생각했습니다.
하지만 50명에서 200명까지 늘릴수록 오히려 RPS는 줄고, 응답 시간은 길어지고, 실패율은 치솟았습니다.
기대와는 정반대의 결과였습니다.

그제야 깨달았습니다. 단순히 사용자 수만 늘린다고 해서 시스템의 성능이 높아지는 것이 아니라는 것을요.
이 포스트에서는 이런 착각이 왜 생기는지, 실제 테스트에서 어떤 결과가 나타났는지, 그리고 어떻게 테스트를 설계해야 하는지를 정리해보았습니다.


테스트는 이렇게 구성했습니다

시나리오 개요

부하 테스트 도구로는 Locust를 사용했습니다. 최대한 단순하면서도 실제 사용 환경에 가까운 형태로 테스트 시나리오를 구성했습니다. 테스트 대상은 POST /api/accounts/transfer/main-to-main API로, 매 요청마다 계좌 ID와 금액을 랜덤하게 설정했습니다.

사용된 주요 파라미터는 아래와 같습니다:

  • 사용자 수: 25 / 50 / 75명 (단계별로 측정)
  • wait_time: constant(0) 설정 → 지연 없이 최대 속도로 요청
  • 요청 본문:
payload = {
    "fromAccountId": random_account_id(),
    "toAccountId": another_random_id(),
    "amount": random_amount()
}
  • 목표: 최대 처리량(RPS), 평균 응답 시간, 최대 응답 시간, 실패율 측정

또한 Locust의 HttpUser 클래스를 활용해, 사용자당 무한 루프 형태로 반복 요청을 보낼 수 있도록 구성했습니다. 모든 요청은 무작위 계좌 간 송금으로 구성되며, 테스트의 본질은 얼마나 많은 요청을 빠르게, 안정적으로 처리할 수 있는지를 측정하는 데 있었습니다.

테스트 결과 요약 및 시각화

이번 테스트에서는 사용자 수를 25명, 50명, 75명으로 나누어 Locust를 통해 동일한 시나리오로 부하를 가했습니다. 각 조건에서 수집된 결과를 다음 표와 같이 정리하였습니다.

사용자 수요청 수실패율평균 응답 시간최대 응답 시간RPS
25명63,2810.40%56.58ms1957ms526.99
50명73,8810.69%80.73ms244ms615.44
75명67,9341.04%131ms36172ms566.17

👉 결론적으로, 50명의 설정이 RPS, 응답 안정성, 실패율 모든 면에서 가장 우수했습니다.

이 데이터를 통해 여러 가지 흥미로운 점을 확인할 수 있었습니다.

  • RPS 기준으로는 50명이 가장 높았습니다.
  • 응답 시간 안정성 면에서는 50명이 가장 좋은 결과를 보였습니다.
  • 75명에서는 최대 응답 시간이 무려 36초를 초과하며, 극단적인 성능 저하를 보였습니다.
  • 실패율 또한 사용자 수가 증가할수록 상승하는 경향을 보였습니다.

이를 통해 단순히 사용자 수를 늘리는 것이 항상 성능 향상으로 이어지지 않는다는 사실을 데이터로 확인할 수 있었습니다.


사용자 수가 많을수록 성능이 하락한 이유

그렇다면 왜 사용자 수를 늘렸을 때 RPS가 떨어지고 실패율이 높아지는 현상이 발생했을까요? 그 원인을 분석해보면 다음과 같은 이유들을 들 수 있습니다.

1. Python GIL로 인한 스레드 병목

Locust는 Python으로 작성되어 있으며, Python은 한 번에 하나의 작업만 처리할 수 있는 '직렬 처리' 제약(GIL)을 갖고 있어, 여러 요청이 동시에 들어오면 오히려 서로 경합하게 됩니다. 마치 한 줄로 줄 선 사람들처럼 순서대로만 처리할 수 있는 구조입니다. 이로 인해 멀티스레딩 환경에서는 동시성이 실제로는 병렬성이 되지 못하고, 오히려 경쟁 상황이 발생합니다.

2. Locust 자체의 리소스 소모 증가

사용자 수가 많아질수록 Locust 자체가 사용하는 CPU 및 메모리 자원이 급격히 증가합니다. 특히 wait_time이 0일 때는 모든 유저가 무한 루프로 요청을 날리기 때문에 Python 인터프리터가 감당해야 할 부하가 기하급수적으로 늘어납니다.

3. 네트워크 I/O 병목

네트워크 연결 수가 증가하면서 커널 레벨에서 소켓 핸들 관리와 패킷 전송 큐에 병목이 발생할 수 있습니다. 이는 클라이언트 측 Locust뿐 아니라 테스트 대상 서버에서도 병목 요소로 작용할 수 있습니다.

4. 테스트 대상 시스템의 처리 한계

서버가 처리할 수 있는 최대 동시 요청 수, 커넥션 풀 크기, 스레드 개수 등 물리적 한계에 도달하면 큐에 요청이 쌓이고, 응답 지연이나 오류가 발생합니다.


📌 핵심 인사이트
"성능 테스트에서 가장 중요한 건 사용자 수가 아니라, 실제 RPS + 실패율 + 안정적인 응답 시간입니다."

현실적인 테스트 전략: 사용자 수가 아닌, 처리량 기준 접근

단순히 사용자 수를 늘려서 부하를 주는 것만으로는 시스템의 실제 성능을 제대로 파악하기 어렵습니다. 진짜 중요한 것은 얼마나 많은 요청을 안정적으로 처리할 수 있는지를 확인하는 것이며, 이를 위해서는 다음과 같은 전략이 필요합니다.

1. 점진적인 사용자 증가 테스트 (Ramp-Up Test)

한 번에 많은 사용자를 투입하는 것이 아니라, 10명 → 25명 → 50명 → 75명 순으로 점진적으로 증가시키며 테스트를 수행하는 방식입니다. 이렇게 하면 어느 시점에서부터 성능 저하가 시작되는지를 확인할 수 있습니다.

이 방식은 시스템이 실제 환경에서 어떻게 반응하는지 측정하는 데 더 유용합니다.

2. 실패율과 응답 시간 기준 최적점 도출

RPS가 가장 높다고 해서 그 설정이 무조건 좋은 것은 아닙니다. 실패율이 낮고, 평균/최대 응답 시간이 안정적인 시점을 기준으로 최적의 사용자 수를 판단하는 것이 중요합니다.

3. 시스템 리소스 모니터링 병행

테스트 도중에는 htop, netstat, Grafana, Prometheus 등 다양한 모니터링 도구를 활용하여 CPU, 메모리, 네트워크, 디스크 I/O 사용량을 반드시 확인해야 합니다. 시스템 외부 지표 없이 테스트 지표만 본다면 병목의 원인을 정확히 파악할 수 없습니다.


정리 및 실무 팁

이번 테스트를 통해 얻은 가장 큰 교훈은 다음과 같습니다.

"사용자 수를 늘리는 것이 항상 성능 향상을 의미하지는 않는다."

시스템의 실제 처리 성능을 측정하기 위해서는 다음 사항들을 반드시 고려해야 합니다.

  • 사용자 수는 점진적으로 늘려야 하며, 성능 임계점을 확인하는 것이 중요합니다.
  • 단순히 높은 RPS만을 기준으로 삼지 말고, 오류율응답 시간의 안정성까지 포함하여 판단해야 합니다.
  • 테스트 시나리오는 실제 유저의 행동을 반영할 수 있도록 랜덤성과 대기 시간을 적절히 구성해야 합니다.
  • Locust 자체의 성능 한계도 고려하여 분산 테스트 방식을 적절히 활용해야 합니다.

실무 적용 팁 요약

  • 사용자 수는 점진적으로 올리며 병목 위치 찾기
  • 최대 처리량(RPS) 기준 최적 사용자 수 도출
  • 테스트 시나리오는 현실 반영 + 랜덤성 포함
  • 시스템 모니터링 도구와 병행하여 진짜 병목을 찾기
profile
Luck favors the prepared. Chance favors the prepared mind

0개의 댓글