밤빵's 개발일지
[TIL]20240830 locust,nGrinder 부하테스트 본문
🫨Locust와 nGrinder를 이용한 부하 테스트
부하 테스트(Load Testing)는 소프트웨어 애플리케이션의 성능을 측정하고, 다수의 사용자 요청을 처리할 수 있는 시스템의 한계를 파악하는 중요한 절차이다. 결제 기능과 같이 민감한 데이터를 처리하는 백엔드 시스템에서는 고가용성, 안정성, 성능 최적화가 매우 중요하다. 그래서 Locust와 nGrinder 같은 도구를 사용해 부하 테스트를 수행하면 시스템이 얼마나 많은 사용자 요청을 견딜 수 있는지, 그리고 응답 시간은 어떤지 등을 확인할 수 있다. 이번 개발일지에서는 Locust와 nGrinder라는 두 가지 부하 테스트 도구에 대해 알아보고, 예시 코드를 통해 이를 결제 기능에 어떻게 적용할 수 있는지 지금 구현 중인 코드에 적용해봤다!
▶Locust란?
Locust는 Python 기반의 부하 테스트 도구로, 사용자가 정의한 스크립트에 따라 가상 사용자(virtual user)를 생성하고, 이들이 API를 호출하여 시스템의 성능을 테스트할 수 있게 해준다.
Locust의 주요 특징은 다음과 같다.
→ Python 스크립트 기반의 유연한 시나리오 작성:
사용자가 Python 코드를 이용해 테스트 시나리오를 작성할 수 있으며, 이는 복잡한 테스트 시나리오도 쉽게 구현할 수 있게 해준다. ( Locust 자체는 Python으로 작성되지만, 테스트 대상은 Python이 아니어도 된다.)
→ 분산 테스트 지원:
여러 대의 서버에서 테스트를 병렬로 실행할 수 있어 대규모 부하 테스트가 가능하다.
→ 웹 UI 제공:
테스트 실행 중 실시간으로 결과를 모니터링할 수 있는 웹 기반 UI를 제공한다.
▶Locust를 이용한 부하 테스트 예시
▽ 결제 기능의 /api/payments/complete 엔드포인트에 대해 Locust를 사용해 부하 테스트를 수행하는 간단한 예시
from locust import HttpUser, TaskSet, task, between
class PaymentTaskSet(TaskSet):
@task
def complete_payment(self):
# 결제 완료 API 호출 예시
self.client.post("/api/payments/complete", json={
"impUid": "test_uid",
"amount": 1000,
"status": "paid"
})
class WebsiteUser(HttpUser):
tasks = [PaymentTaskSet]
wait_time = between(1, 5)
→ PaymentTaskSet이라는 TaskSet을 정의하고, complete_payment 메서드를 통해 결제 완료 API를 호출하는 시나리오를 작성했다. HttpUser 클래스는 Locust의 가상 사용자로, 이 사용자들이 API를 호출하여 시스템에 부하를 가하게 된다.
▽ Locust 예시에 해당하는 Spring Boot 코드
위 Python 코드는 complete_payment 메서드를 통해 /api/payments/complete 엔드포인트를 호출한다. 이와 대응되는 Spring Boot 코드는 아래와 같다.
// 결제 완료 메서드
@Transactional
public PaymentResponseDto completePayment(PaymentRequestDto paymentRequestDto) {
String url = portOneConfig.getApiUrl() + "/payments/" + paymentRequestDto.getImpUid();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + portOneConfig.getApiKey());
ResponseEntity<PaymentResponseDto> response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), PaymentResponseDto.class);
if (response.getStatusCode() == HttpStatus.OK) {
PaymentResponseDto paymentResponseDto = response.getBody();
// 결제 정보 저장
Payment payment = new Payment(
paymentRequestDto.getImpUid(),
paymentResponseDto.getAmount(),
paymentResponseDto.getStatus(),
paymentResponseDto.getReceiptUrl(),
"결제 완료",
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
);
paymentRepository.save(payment);
return paymentResponseDto;
} else {
throw new RuntimeException("결제 완료 처리 실패: " + response.getStatusCode());
}
}
→ 이 예시 코드는 Spring Boot 기반의 REST API에서 결제 완료 처리를 수행하는 메서드로, 이와 같은 API를 대상으로 Locust를 통해 다수의 요청을 보내어 부하를 가함으로써, 시스템의 안정성과 성능을 테스트할 수 있다.
▶nGrinder란?
nGrinder는 네이버에서 개발한 부하 테스트 도구로, 대규모 부하 테스트를 손쉽게 실행하고 관리할 수 있게 해준다. nGrinder는 Jython 기반의 스크립트 작성 방식을 사용하며, 테스트 시나리오 작성이 쉽고, GUI 기반의 테스트 관리 및 실행 환경을 제공한다.
→ GUI 기반의 관리 환경:
nGrinder는 테스트 환경을 쉽게 설정하고 관리할 수 있는 GUI를 제공하여, 복잡한 테스트 환경에서도 쉽게 사용할 수 있다.
→ 대규모 분산 부하 테스트 지원:
여러 에이전트를 통해 대규모 분산 부하 테스트를 지원하며, 수천 대의 가상 사용자를 동원한 테스트가 가능하다.
→ 통합된 리포트와 모니터링:
테스트 실행 중 실시간 모니터링을 제공하고, 테스트 종료 후에는 통합된 리포트를 통해 결과를 분석할 수 있다.
▶ nGrinder를 이용한 부하 테스트 예시
nGrinder는 Jython 스크립트를 사용하여 테스트 시나리오를 작성한다. 아래는 결제 기능에 대한 부하 테스트 시나리오 예시이다.
from net.grinder.script import Test
from net.grinder.script.Grinder import grinder
from net.grinder.plugin.http import HTTPRequest
test1 = Test(1, "Complete Payment")
request1 = HTTPRequest()
test1.record(request1)
class TestRunner:
def __call__(self):
result = request1.POST("/api/payments/complete", {
"impUid": "test_uid",
"amount": 1000,
"status": "paid"
})
grinder.logger.info("Response: %s" % result.text)
→ 이 코드에서는 HTTPRequest 객체를 사용하여 POST 요청을 /api/payments/complete 엔드포인트로 보내는 방식으로 결제 기능에 대한 부하 테스트를 작성했다. grinder.logger.info를 통해 응답을 로깅할 수 있다.
▶부하 테스트 예시와 설명
부하 테스트는 다양한 환경에서 애플리케이션의 안정성을 평가하기 위한 중요한 단계이다. 예를 들어, 다음과 같이 결제 완료를 처리하는 API에 대한 부하 테스트를 수행할 수 있다.
▷결제 완료 API : 위의 Spring Boot 예시코드
→위에서 Python과 Jython으로 부하 테스트 예시를 작성한 것과 같은 API를 대상하여 Spring Boot에서도 부하 테스트가 가능하다. 이는 시스템의 안정성과 성능을 테스트하는데 유용하다.
▶ Locust와 nGrinder의 선택 기준
분LocustnGrinder
기반 언어 | Python | Jython (Python for JVM) |
지원 언어 | Python 스크립트로 테스트 시나리오 작성. 그러나 HTTP, WebSocket, gRPC 등 다양한 프로토콜로 다른 언어로 작성된 API 테스트 가능 | Jython, Groovy, Scala 등 다양한 스크립트 언어를 지원하며, 대상 애플리케이션은 Java, Python, Node.js, Ruby 등 다양한 언어로 작성 가능 |
프로토콜 지원 | HTTP, WebSocket, gRPC 등 다양한 프로토콜 지원 | HTTP 등 다양한 프로토콜 지원 |
분산 테스트 | 여러 대의 서버에서 분산된 부하 테스트 지원 | 여러 에이전트 머신에서 분산된 부하 테스트 지원 |
특징 | 실시간 모니터링 가능한 웹 UI 제공 | GUI 기반의 관리 환경 제공 |
장점 | Python에 익숙한 개발자에게 적합, 코드 기반으로 유연한 시나리오 작성 가능 | Java, Jython 등 다양한 스크립트 언어에 익숙한 환경에서 사용하기 좋음. 대규모 분산 부하 테스트에 유리 |
→ Locust는 Python에 익숙하고, 코드 기반으로 유연한 시나리오 작성이 필요할 때 적합하다.
→ nGrinder는 GUI 기반의 관리가 필요하고, Java나 Jython에 익숙한 환경에서 사용하기 좋다.
▶내용 요약
Locust와 nGrinder를 활용한 부하 테스트에 대해 알아보고, 각 도구의 특징과 장점, 결제 기능을 예시로 들어 부하 테스트를 어떻게 수행할 수 있는지 정리 할 수 있었다.부하 테스트는 애플리케이션의 안정성을 보장하기 위한 중요한 과정이고, 이를 통해 시스템의 성능을 검증하고 최적화할 수 있다. 예시 코드 만들어보려니까 파이썬 코드를 내놔서 이거 스프링은 못하는건가? 했는데 언어의 제한이 따로 없기도하고, 다양한 언어를 지원하기도 해서 그냥... 영 쓸모없는 일은 아니였다. 결제시스템이나 사용자 트래픽이 많은 애플리케이션에서는 부하 테스트가 중요하다고 해서 한번 해봤던건데 매번 여러 테스트들을 보면서 느끼는거지만 나는 테스트같은거랑 너무 안 맞는거 같다..!
'개발Article' 카테고리의 다른 글
[WIL]20240901 N+1문제해결 : 프로젝트 코드에서 해결하기 (1) | 2024.09.01 |
---|---|
[TIL]20240831 API 게이트웨이 (0) | 2024.08.31 |
[TIL]20240829 웹훅(Webhook) (0) | 2024.08.29 |
[TIL]20240828 인 컨텍스트 러닝(In-Context Learning) (1) | 2024.08.28 |
[TIL]20240827 Spring batch (0) | 2024.08.27 |