💻 백엔드

🔥 Locust! 첫 Locust 부하테스트 도전기

twoweekhee 2025. 5. 30. 10:11

지난번 k6로 부하테스트를 진행한 후 꽤 만족스러웠는데, 이번엔 팀에서 "Locust도 한번 써보자!"는 의견이 나왔어요. 실제로 써보니 웹 UI로 실시간 컨트롤할 수 있는 점과 Python 환경의 친숙함이 정말 매력적이더라고요! 🐛✨

 

📋 목차

  1. k6에서 Locust로 넘어온 이유
  2. Locust 웹 UI의 놀라운 편리함
  3. Python 환경의 강력한 장점들
  4. 실제 구현하면서 느낀 차이점들
  5. 팀원들이 특히 좋아한 기능들
  6. 성능 테스트 결과와 UI 활용
  7. Python 개발자라면 Locust를 선택해야 하는 이유

🤔 k6에서 Locust로 넘어온 이유

k6로 이미지 처리 API 부하테스트를 성공적으로 마친 후, 팀 회고에서 이런 의견들이 나왔어요:

백엔드 개발자: "k6 좋긴 한데... 터미널에서만 보는 게 아쉬워요" 팀장: "실시간으로 조정하면서 테스트할 수는 없을까요?" 

그래서 "웹 UI가 있고 Python 기반"이라는 Locust의 매력에 끌려 도전하게 되었습니다! 🎯

🖥️ Locust 웹 UI의 놀라운 편리함

k6 vs Locust: 테스트 컨트롤 방식

k6 (이전 경험):

k6 run --vus 50 --duration 300s script.js
# 한 번 실행하면 멈추고 또 스크립트 고치고 재시작 기다려야 함... 😅

Locust (이번 경험):

locust -f locustfile.py
# 브라우저에서 http://localhost:8089 접속!

웹 UI로 할 수 있는 것들

  1. 실시간 사용자 수 조정 🎛️
    • 테스트 중간에 사용자 수를 늘리거나 줄일 수 있어요!
    • "50명에서 시작해서 점점 늘려보자" → 클릭 몇 번으로 가능
  2. 즉시 중단 및 재시작 ⏯️
    • 뭔가 이상하다 싶으면 바로 STOP 버튼 클릭
    • k6에서는 Ctrl+C 눌러야 했는데...
  3. 실시간 그래프 모니터링 📊
  4. 팀원들이 모니터에 둘러서서: "어? 응답시간 급상승!" "사용자 수 더 늘려볼까?" "오, 이제 안정화되네!"
  5. CSV 다운로드 💾
    • 테스트 결과를 바로 CSV로 다운로드
    • 추후 분석용으로 정말 편했어요

실제 사용 시나리오

# 웹 UI에서 이런 식으로 조정 가능
"""
1. 사용자 10명으로 시작
2. 5분 후 → 50명으로 증가
3. 응답시간 보고 판단 → 100명으로 증가
4. 문제 발견 → 즉시 중단
5. 코드 수정 후 → 바로 재시작
"""

팀원 반응: "이거 진짜 편하다... 게임하는 느낌!" 🎮

🐍 Python 환경의 강력한 장점들

1. 친숙한 개발 환경

우리 팀 대부분이 Python 개발자라서:

# 이런 코드가 눈에 익숙해요
from locust import HttpUser, task, between
import requests
import json
import random

class ImageAPITestUser(HttpUser):
    host = "http://your-api-server.com:8080"
    wait_time = between(0.1, 0.5)
    
    def on_start(self):
        # Python스럽게 초기화!
        self.test_images = [
            "image1.jpg", "image2.jpg", "image3.jpg"
        ]

k6 JavaScript vs Locust Python:

// k6 - JavaScript (다소 어색)
export default function () {
    let payload = JSON.stringify({...});
    // 문법이 익숙하지 않아서 매번 구글링...
}
# Locust - Python (매우 친숙!)
@task
def test_api(self):
    payload = {"key": "value"}  # 딕셔너리 그대로!
    # 평소 쓰던 방식 그대로

2. 강력한 디버깅 환경

@task
def debug_friendly_test(self):
    try:
        response = self.client.post("/inference", json=payload)
        print(f"Status: {response.status_code}")  # 실시간 로그
        
        if response.status_code != 200:
            print(f"Error: {response.text}")  # 에러 내용 바로 확인
            
    except Exception as e:
        print(f"Exception: {e}")  # Python 예외 처리

팀원 피드백: "디버깅이 진짜 쉬워졌어요! print 찍고 바로 확인할 수 있어서"

3. 라이브러리 생태계 활용

import os
from datetime import datetime
import pandas as pd  # 데이터 분석도 가능!
from dotenv import load_dotenv  # 환경변수 관리
import requests  # 익숙한 HTTP 라이브러리

class AdvancedTestUser(HttpUser):
    def setup_test_data(self):
        # pandas로 테스트 데이터 준비
        df = pd.read_csv('test_data.csv')
        return df.to_dict('records')
    
    @task
    def complex_scenario(self):
        # 복잡한 비즈니스 로직도 Python으로 쉽게!
        test_data = self.setup_test_data()
        # ...

🔍 실제 구현하면서 느낀 차이점들

환경 설정의 편리함

k6 때의 아쉬움:

# 환경변수 설정이 좀 복잡했어요
export API_HOST="http://localhost:8080"
export TEST_IMAGE_URL="https://..."
k6 run -e API_HOST=$API_HOST script.js

Locust의 편리함:

# .env 파일 만들고
load_dotenv()

class TestUser(HttpUser):
    host = os.getenv('API_HOST')  # 익숙한 방식!
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.api_key = os.getenv('API_KEY')
        self.test_images = os.getenv('TEST_IMAGES').split(',')

복잡한 시나리오 구현

# 이런 복잡한 로직도 Python이라 편해요!
class RealWorldTestUser(HttpUser):
    
    def on_start(self):
        """사용자별 초기화 - 실제 사용자 플로우 모사"""
        self.login()
        self.user_preferences = self.get_user_preferences()
    
    def login(self):
        """로그인 프로세스"""
        response = self.client.post("/auth/login", json={
            "username": f"testuser_{random.randint(1, 1000)}",
            "password": "testpass"
        })
        self.auth_token = response.json().get('token')
    
    @task(3)  # 가중치 3
    def process_image(self):
        """메인 이미지 처리 작업"""
        headers = {"Authorization": f"Bearer {self.auth_token}"}
        # 복잡한 로직들...
    
    @task(1)  # 가중치 1
    def health_check(self):
        """가벼운 헬스체크"""
        self.client.get("/health")

👥 팀원들이 특히 좋아한 기능들

1. 실시간 협업 가능

PM: "개발자들이 뭘 테스트하는지 실시간으로 볼 수 있어서 좋아요!" QA: "중간에 조건 바꿔서 테스트해달라고 바로 요청할 수 있어서 편해요!"

2. 직관적인 그래프

웹 UI에서 볼 수 있는 것들:
📈 초당 요청 수 (RPS) 실시간 그래프
📊 응답 시간 분포도
⚠️  에러율 변화 추이
👥 현재 활성 사용자 수

3. 테스트 중 실시간 조정

실제 대화:

팀장: "사용자 50명에서 시작해볼까요?"
개발자: (클릭 몇 번) "시작했습니다!"
팀장: "응답시간 괜찮네요, 100명으로 늘려보세요"
개발자: (슬라이더 조정) "늘렸습니다!"
팀장: "오, 이거 재미있네요!" 😄

📊 성능 테스트 결과와 UI 활용

웹 UI를 통한 실시간 모니터링

테스트하면서 웹 UI로 이런 것들을 실시간으로 확인했어요:

  1. 점진적 부하 증가 실험
    • 10명 → 30명 → 50명 → 80명으로 단계적 증가
    • 각 단계에서 응답시간 변화를 실시간 관찰
  2. 임계점 발견
  3. 사용자 50명: 평균 응답시간 2.1초 ✅ 사용자 70명: 평균 응답시간 3.8초 ⚠️ 사용자 80명: 평균 응답시간 8.2초 ❌
  4. 즉시 대응
    • 80명에서 응답시간 급증 발견
    • 바로 사용자 수를 70명으로 조정
    • 안정화 확인 후 다시 점진적 증가

CSV 다운로드로 상세 분석

# 다운로드한 CSV 데이터로 추가 분석
import pandas as pd

df = pd.read_csv('locust_stats.csv')
print(df.describe())  # 통계 요약
# 평소 사용하던 pandas로 분석!

🐍 Python 개발자라면 Locust를 선택해야 하는 이유

1. 학습 곡선이 거의 없음

# 평소 Python 개발하는 방식 그대로!
class MyTestUser(HttpUser):
    def setup_method(self):
        # 평소 쓰던 setUp 방식
        pass
    
    @task
    def my_test(self):
        # 평소 쓰던 requests 라이브러리 방식
        response = self.client.get("/api/test")
        assert response.status_code == 200

2. 기존 Python 도구들과 완벽 호환

# 기존에 쓰던 도구들 그대로 사용 가능
import pytest
import logging
import configparser
from my_utils import custom_helper  # 기존 유틸리티 함수들

class TestUser(HttpUser):
    def use_existing_tools(self):
        # 기존 프로젝트의 헬퍼 함수 재사용
        data = custom_helper.prepare_test_data()
        logger.info("테스트 시작")  # 기존 로깅 설정 그대로

3. IDE 지원의 완벽함

# VS Code, PyCharm 등에서 완벽한 지원
class TestUser(HttpUser):
    def test_with_autocomplete(self):
        # 자동완성, 타입 힌팅 모두 지원
        response: requests.Response = self.client.post(...)
        # 디버깅 브레이크포인트도 설정 가능!

4. 팀 내 지식 공유 용이

시니어 개발자: "기존 Python 코드 패턴 그대로 쓰면 되니까 리뷰하기도 편해요" 주니어 개발자: "새로 배울 게 없어서 바로 기여할 수 있어요!"

🚀 우리 팀의 결론

Locust를 선택하는 상황들

  1. Python 개발팀: 당연히 Locust! 🐍
  2. 실시간 협업 필요: 웹 UI의 장점 활용
  3. 복잡한 시나리오: Python의 유연성 필요
  4. 점진적 테스트: UI로 실시간 조정하며 테스트

실제 운영 방식

# 우리 팀의 표준 Locust 설정
class StandardTestUser(HttpUser):
    """팀 표준 부하테스트 템플릿"""
    
    host = os.getenv('TARGET_HOST')
    wait_time = between(0.1, 0.5)
    
    def on_start(self):
        """표준 초기화 프로세스"""
        self.setup_auth()
        self.load_test_data()
    
    # 표준 메서드들...

팀 내 부하테스트 문화 변화

이전 (k6 시절):

  • 개발자 혼자 터미널에서 테스트
  • 결과 공유는 슬랙으로 스크린샷

현재 (Locust 도입 후):

  • 팀원들이 함께 모니터 보며 테스트
  • 실시간으로 조건 변경하며 실험
  • PM, QA도 함께 참여 가능

💡 Python 개발자들에게 추천하는 이유

  1. 기존 스킬셋 100% 활용 🎯
  2. 학습 비용 거의 제로 📚
  3. 팀 내 지식 공유 용이 👥
  4. 웹 UI로 협업 가능 🖥️
  5. 복잡한 로직 구현 자유롭게 🧠

🎯 마무리

k6도 훌륭한 도구지만, Python 환경에 익숙한 개발팀이라면 Locust가 확실히 더 매력적이에요. 특히 웹 UI를 통한 실시간 컨트롤과 모니터링 기능은 팀 협업에 정말 큰 도움이 되었습니다.

무엇보다 "새로 배워야 할 것이 거의 없다"는 점이 가장 큰 장점이었어요. 평소 Python 개발하던 방식 그대로 부하테스트를 작성할 수 있으니까요! 🚀

Python 개발팀이라면 망설이지 말고 Locust로 부하테스트 시작해보세요!


Tags: #Locust #Python부하테스트 #웹UI #실시간모니터링 #부하테스트 #개발팀경험담 #Python개발자 #팀협업 #성능테스트 #UI컨트롤