기타

대규모 트래픽 상황을 가정한 서버 부하 테스트(python, locust)

카늬 2025. 12. 3. 17:00

1. 대규모 트래픽이 왜 중요한가?

최근 아이온2 출시 당시, 많은 유저가 동시 접속을 시도해 서버가 터지고, 스트리머들도 수 시간 동안 접속 대기 또는 반복 접속을 하다 포기하는 상황을 보게되었다 이 과정을 보며 느꼈던 점이 대규모 트래픽은 선택이 아니라 필수로써 한때 채용공고에서 “대규모 트래픽 경험”이 필수 자격으로 적힌 경우가 많았는데, 이제 와서 보니 그 이유를 확실히 체감하게 되었다.

그래서 나 역시 서버를 직접 운영할 개발자로서 "내가 서버를 운용하게 되었을 경우 비슷한 상황이 들이닥치면 어떻게 해야할까?" 라는 시뮬레이션을 해 보기로 했다.


2. 시나리오 설정

  1. 나는 특정 게임의 정보를 제공하는 사이트를 운영하고 있다.
  2. 해당 게임의 신규·복귀 유저 유입 시즌이 도래했다.
  3. 2025년 11월 26일 기준 게임 계정 수는 479,571개이며 신규유저가 유입되는것도 포함되는 상황을 생각한다면
    최악의 경우 약 50만 번의 요청이 단시간에 몰릴 수도 있다.
  4. 이 상황을 로컬/서버 환경에서 시뮬레이션하고 문제점있다면 해결 방법을 찾아서 반영해보자

3. 트래픽 부하 방법 조사

처음에는 가지고 있던 Postman Runner를 사용해 보려고 했지만, 다음과 같은 이유로 사용을 포기하였다.

  • 동시 요청을 발생시키지 않음 (순차 요청)
  • 응답을 동시에 받는 상황을 만들 수 없음

부하 테스트 도구로는 의미가 없다고 판단하였다.

 

많이 사용되는 부하 테스트 도구

  • Locust (Python 기반, 추천)
    → 설치 간단, UI 제공, 동시유저·RPS 제어 가능, Python 사용해 시나리오 작성 가능
  • k6 (JavaScript 기반)
  • JMeter (전통적, 강력하지만 무거움)
  • 그 외 nGrinder, SOAP UI등 존재

사용 도구 결론

Locust 사용

개발 환경이 Python이며 스크립트 작성이 매우 편리하기 때문에 최적이여서 내 상황에 가장 알맞다고 판단하였다.


4. Locust 설치 및 실행

설치

pip install locust

실행 명령어

python -m locust

locust 명령어가 정상적으로 실행이 되지 않을 경우

"Windows Store"에서 Python를 설치하여 사용 시 Scripts 경로가 PATH에 잡히지 않아 오류가 발생하여 python경로를 다시 확인하여 locust.exe파일을 찾아주어야 한다.(필자가 그러하였다.)

#locust.exe 위치 예시
C:\Users\user\AppData\Local\Packages\ PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\ LocalCache\local-packages\Python312\Scripts\locust

 

 

그 외 해결방법으로는 해당 경로를 환경 변수 PATH에 추가하여 명령어를 실행시켜주면 된다.

 

5. Locust 사용 방법 

테스트 스크립트 만들기

프로젝트 폴더에 locustfile.py 생성

#locustfile.py
from locust import HttpUser, TaskSet, task, between
import random

class UserBehavior(TaskSet):
    wait_time = between(1, 3)  

    @task(1)
    def get_categories(self):
        self.client.get("/api/categories/")#작성하신 api로 엔드포인트로 바꿔주세요
    
    @task(1)
    def get_contents(self):
        self.client.get("/api/contents/")

    @task(1)
    def get_items(self):
        self.client.get("/api/items/")

    autocomplete_keyword=["파편", "수호", "파괴", "돌파석", "융화"]
    @task(2)
    def get_autocomplete(self):
        item_keyword=random.choice(self.autocomplete_keyword)
        self.client.get(f"/api/autocomplete/?item_keyword={item_keyword}")

    search_keyword=["운명의 파편 주머니(소)", "운명의 파괴석", "운명의 수호석", "운명의 돌파석"]
    @task(3)
    def get_search(self):
        search_keyword=random.choice(self.search_keyword)
        self.client.get(f"/api/search/?search_keyword={search_keyword}")

    @task(3)
    def get_prices(self):
        content_id= 27
        self.client.get(f"/api/prices/?content_id={content_id}")


class LocustUser(HttpUser):
    tasks = [UserBehavior]
  • HttpUser = 가상의 사용자
  • @task = 반복적으로 수행할 동작( @task(3)는 비중 3을 부여하는 의미입니다. )

결론적으로 유저 1명이 "UserBehavior"에 있는 task들을 실행시킨다는 의미

 

 

Locust 실행하기

 
locust 혹은 python -m locust로 실행
 

웹 UI 접속 : http://localhost:8089

 

테스트 설정값 입력

주요 설정값

  • Number of Users : 목표하는 동시 접속자 수)
  • Spawn rate : 0명부터 초당 증가되는 유저 수
  • Host : 테스트할 서버 주소(예시 : localhost:8000)

Start 버튼을 클릭하여 부하 테스트 시작

 

테스트 결과 분석

 

Locust에서 알려주는 내용

  • RPS (초당 요청 수)
  • Failures/s (초당 에러 수)
  • P95 ( 전체 데이터셋을 순서대로 나열했을 때 하위 95%에 해당하는 값들을 포함하는 위치의 값  )
  • P99 ( 전체 데이터의 99%가 해당 값보다 작거나 같다는 뜻)
  • Users (요청하는 사용자 수)

해당사항을 참고하여 확인할 것

  • 어느 시점부터 응답시간이 급격히 증가하는가
  • 얼마나 많은 유저까지 안정적으로 처리 가능한가
  • 어떤 API가 가장 느린가
  • DB/서버 병목이 어디인가

6. 테스트 결과

Locust 테스트를 돌려본 결과

  • 동시 접속자 20~30명 수준에서도 모든 API의 응답시간이 11~18초로 상승한다.
  • RPS는 7~8로 유지되지만 동시 요청이 쌓여 응답 대기열이 밀리는 상황 발생.

결론

동시요청 20~30명 이상에서 처리 속도가 급격히 떨어지는 병목 발생하므로 해당상황에 있어 대부분 원인은 DB 커넥션 부족 + 인덱스 미사용 + 캐시 없음 라고 하니 해당사항들을 하나하나 도입하여 전, 후 처리속도를 비교해보자

'기타' 카테고리의 다른 글

대규모 트래픽 상황을 가정한 서버개선(index, redis)  (0) 2025.12.05