Locust 부하테스트🔍 설계해보자!

임규성·2025년 4월 24일
1

1. 부하테스트

서버 개발을 마무리하면서 부하테스트를 해보고 1) 성능 높이기 2) 사용자 수에대한 비용 발생 예상을 해볼 발판이 될 것이다.

2. 부하테스트 환경

  • 언어 : Python
  • 프레임워크 : Locust
  • IDE : Pycharm

2. 부하 테스트란? 범위는?

정의

부하테스트는 말 그대로 서버에 부하를 줘서 안정성과 성능을 체킹하는 과정입니다.
범위는 테스트의 목적에 따라서 다를 수가 있는데

범위

현재는 포괄적인 안정성을 확인하고 병목지점을 확인하는 절차이기 때문에 모든 api에 대해서 측정을 하는 것을 목표로 한다!
또한 스케줄러 기반으로 동작하는 api는 부하가 걸릴 위험이 없기때문에 제외한다.

3. API 선별

외부 api와의 영향이 없는 api는 다 가져오는 것으로 한다.
또한 데이터의 필요유무에따라서 성능이 달라질 수 있는 api를 분류해봤습니다.

기준 3가지

데이터 초기화 필요없다
-> 1)데이터 필요 ❌
더미 데이터 초기화가 필요하지만 매 api마다 필요하지 않다.
-> 2)데이터 초기화만 필요 ✅
데이터가 매 api마다 수정이 필요하다
-> 3)데이터 매번 수정 필요 ✅


4. 구체적 설계

Section 0 : Initial-Setting

Spring-Boot
1) 가상의 주차장을 30개 만들어야함
값은 랜덤하게 들어가는 것으로 합니다. 또한 이에 맞는 요금규칙도 만들어야합니다.
2) ddl이 create가 되어야하며, 오직 Performance-test에 활용하는 데이터만이 DB에 존재해야합니다.
3) 유저 3명을 만듭니다

유저 a : ID : performTUser1 PW : performTUser1
즐겨찾기 하는 주차장이 10개입니다.
유저 b : ID : performTUser2 PW : performTUser2
즐겨찾기 하는 주차장이 없습니다.
유저 c : ID : performTUser3 PW : performTUser3

4) 유저 a,b,c기반의 parkingHistory를 랜덤하게 90개 만듭니다.
이때 연도는 2023년 1월 1일부터 2025년 12월 31일까지 랜덤입니다.
모든 간격의 데이터가 균등하게 있어야합니다.
이때 유저상태에 따른 주차현재 상태는 아래와 같습니다.
유저 a -> 주차 ❌
유저 b -> 주차 ✅ 2시간 정도 경과
유저 c -> 주차 ✅ 30분 초과 x 위의 주차장과 달라야함

5) 유저 a,b,c기반의 Alarm을 랜덤하게 120개 만듭니다.
이때 알람종류 3가지도 균등하게 들어가야 합니다.
이때 각 3가지에 대해서 읽은 알람 안읽은 알람을 반반 나눕니다.

Locust

Section 1 : 데이터 필요 ❌

1) CSRF 토큰 발급 (GET)

큰 설계 방식은 필요하지 않습니다. 단순히 api요청을 하면 됩니다.


Section 2 : 데이터 초기화만 필요 ✅

1) 주차장 리스트 불러오기 (GET)

Spring boot Side
1) 30개 정도 가상 데이터를 spring-boot post-constructer로
performanceTest spring-profile일때만 생성하기
2) 또한 유저도 다양하면 좋기 때문에
유저a) 즐겨찾기 10개 이상 유저 -> 1페이지가 전부 북마크 데이터인 경우
유저b) 즐겨찾기 없는 유저 -> 즐겨찾기 쿼리를 안쓰는 경우
유저c) 즐겨찾기 3개정도 유저 -> 1페이지중의 일부만 즐겨찾기 인 경우

Locust Side
1) 이후 locust에서 위경도 쿼리값을 바꿔가며 요청 보내기
-> 다양한 위치에서 보낸다는 것 모킹


2) 주차장 사용 이력 리스트 불러오기 (GET)

Spring boot Side
1) 주차 이력 데이터를 위 3명의 유저 a,b,c에 대해서 120개를 만듭니다.
2) 해당 이력은 2023년 1월 1일부터 2025 12월 31일까지만 만듭니다. 또한 최대한 다양하게

Locust Side
3) 다양한 쿼리(Page, StartTime등)를 바꿔가며 요청을 보냅니다.

3) 주차장 즐겨찾기 생성(POST) + 주차장 즐겨찾기 제거(DELETE)

Locust Side
0) 유저 b(즐겨찾기 존재 X)를 사용해줍니다.
1) 두 api는 무조건 순서에 맞춰서 실행해서 에러가 발생하지 않게 합니다.
2) 생성한 id와 삭제한 id를 Random하게 바뀝니다.

4. 회원 알람 불러오기 (GET)

Spring boot Side
1) 유저 a,b,c에따른 알람을 120개 만듭니다.
2) 만들때는 알람 종류 3가지에 대해서 여러가지를 만듭니다.

Locust Side
1) 유저 a,b,c 가 동시에 호출을 하면서 쿼리의 종류도 다양하게 바꿉니다.

5. 읽지않은알림확인 (GET)

4번에서 수행한 Spring-boot 데이터를 활용해줍니다.
Locust Side
1) 유저 a,b,c 가 동시에 호출합니다.

6. 주차장 이용상태 불러오기 (GET)

Spring boot Side
1) 유저 a,b,c에 따른 주차상태를 갱신합니다.
2) 유저 a -> 주차 ❌
3) 유저 b -> 주차 ✅ 2시간 정도 경과
4) 유저 c -> 주차 ✅ 30분 초과 x 위의 주차장과 달라야함

7. 정산시작 (GET)

Locust Side
위 주차가 되어있는 유저 b,c를 대상으로 호출

8. 로그인한 사용자 이름 가져오기 (GET)

Spring boot Side
기존 유저 a) b) c)를 사용

Locust Side
위 유저 3명을 대상으로 호출

9. 로그인한 사용자 정보 가져오기 (GET)

Spring boot Side
기존 유저 a) b) c)를 사용

Locust Side
위 유저 3명을 대상으로 호출

10. 로그인한 사용자 정보 수정 (PUT)

Spring boot Side
기존 유저 a) b) c)를 사용

Locust Side
위 유저 3명을 대상으로 호출

11. 로그인한 사용자 비밀번호 변경 (PUT)

Spring boot Side
기존 유저 a) b) c)를 사용

Locust Side
위 유저 3명을 대상으로 호출


Section 3 : 데이터 매번 수정 필요 ✅

해당 섹션의 api들에 대해서 설명을 해보겠습니다.해당 색션의 구현은 두가지 선택사항이 발생합니다.

A : 실제 똑같은 요청을 하기 위해서는 매 API 요청마다 값을 초기화 해야함
예시) 알람 읽기 api라면 해당 api호출 이후 다시 target alarm들을 안읽음 상태로 바꿔야함
이렇게 된다면 추가 트랜잭션이 계속 발생하게 될 것이고, 이때문에 실제 운영서버에서 발생하지 않는 트랜잭션이 추가로 많이 발생함!!
-> 따라서 해당 API는 간접적으로만 성능을 테스트한다.

B : 데이터의 형태가 실제와 다르지 않더라도 같은 쿼리를 던지기 때문에 같은 트랜잭션이 발생할 것임
따라서 해다 색션 api중 결국 같은 트랜잭션이 발생하는 API에 대해서는 추가 데이터 초기화 없이 요처을 보낼 것임
즉 보내는 SQL문에 차이가 없다는뜻!!
-> 따라서 결국 연산자체가 같은 API이기 때문에 성능테스트에 포함한다.

B를 선택하겠습니다!!

연산자체가 같다면 성능테스트를 해보는게 좋다고 판단함!!

1. 회원 알람 읽기 (PUT)❌

데이터의 값이 다름에 따라 던지는 SQL이 다르기 때문에 제외

2. 회원 알람 선택 삭제 (DELETE)❌

해당 삭제를 해버리면 다른 테스트에서 사용하는 데이터들이 없어지므로 제외

3. 주차장 사용 이력 리스트 삭제 (DELETE) ✅

해당 api는 엔티티를 즉시 삭제하지않고 30일 보관하기 때문에 같은 쿼리를 날린다 -> 데이터의 형태가 달라도... 따라서 포함!!

Spring boot Side
기존 유저 a) b) c)의 120개의 History를 사용

Locust Side
위 유저 3명을 대상으로 DELETE 호출

14. 인증번호 확인 (POST)❌

해당 삭제를 해버리면 레디스 내부의 값이 사라져서 매 api마다 다시 만들어 줘야해서 제외


5. 여러 이슈들

Q1. 실제 성능 테스트의 부하 사용자수만큼 사용자 계정을 만드는것이 합리적인지 않은가요?

1) 먼저 테스트시마다 사용자수가 바뀔수 있기 때문에 완벽히 맞추는거는 비용이 많이 발생합니다.
세션 관리등 여러가지가 필요하기 때문입니다.
2) 여러 case의 유저만 만든다면 괜찮지 않을까라는 생각?
-> 각 case마다 성는이 다를것이고 이에 병목지점이 나올것이기 때문이라고 생각합니다.

Q2. Locust말고 Spring-boot-test에서 스레드를 여러개만들고 시간 측정하면 되지 않는가?

1) "자동차 속도 측정을 집 안에서 페달 밟으면서 해도 되지 않냐?” 라는 말이랑 거의 같다.
2) 실제 환경에서 관여되는 네트워크 latency, I/O wait, DB connection pool, 캐시 hit/miss 등이 제대로된 환경이 아니기 때문이다.


4. 코드

profile
삶의 질을 높여주는 개발자

0개의 댓글