🚨테스트 전에 꼭 해둘 것 3가지🚨
(1) 강의 정원(capacity)을 100으로 세팅
- lecture 테이블에서 capacity를 100으로
- enrolled(또는 enrolledCount)를 0으로 초기화
(2) 스케줄러가 admitted를 풀어줘야 함
현재 스케줄러:
@Scheduled(fixedDelay = 3000)
batchSize =1;
이대로면 admitted가 너무 천천히 풀려서 테스트가 오래 걸려.
테스트할 때만 임시로 추천:
- fixedDelay = 1000 (1초)
- batchSize = 20 또는 50
이유: admitted가 빨리 풀려야 “enroll 동시성”이 제대로 발생함.
(3) 서버 로그 너무 많으면 느려질 수 있음
대량 테스트 때 log.info가 너무 많으면 성능이 왜곡될 수 있어. (가능하면 줄이기)
1️⃣ JMeter 테스트 플랜 목표 구조
너가 만들 JMeter 트리는 이렇게 될 거야:
EnrollConcurrencyTest
└─ Thread Group (Users=300, RampUp=30, Loop=1)
├─ HTTP Request Defaults (localhost:8080)
├─ 01_enqueue (POST /api/lectures/1/queue)
│ └─ JSON Extractor: userKey = $.userKey
├─ While Controller (status != SUCCESS && maxLoop > 0)
│ ├─ 02_poll_me (GET /api/lectures/1/queue/me?userKey=${userKey})
│ │ └─ JSON Extractor: status = $.status
│ ├─ Constant Timer (200ms~1000ms)
│ └─ JSR223 PostProcessor (maxLoop 감소)
├─ If Controller (status == SUCCESS)
│ └─ 03_enroll (POST /api/lectures/1/enroll?userKey=${userKey})
├─ Summary Report
└─ View Results in Table (초반 확인용)
핵심은:
- 유저마다 enqueue해서 userKey를 받고
- SUCCESS 될 때까지 폴링하고
- SUCCESS인 애들만 enroll을 때려서
- DB가 정원을 넘지 않는지 확인하는 것!
2️⃣ JMeter에서 “하나씩 클릭해서 만드는 방법”
Step A) Thread Group 만들기
Test Plan 우클릭 → Add → Threads → Thread Group
- Users: 300 (처음은 100으로 시작해도 OK)
- Ramp-up: 30
- Loop Count: 1
Step B) HTTP Request Defaults
Thread Group 우클릭 → Add → Config Element → HTTP Request Defaults
- Protocol: http
- Server: localhost
- Port: 8080
Step C) 01_enqueue 만들기
Thread Group 우클릭 → Add → Sampler → HTTP Request
- Name: 01_enqueue
- Method: POST
- Path: /api/lectures/1/queue
C-1) JSON Extractor로 userKey 뽑기
01_enqueue 우클릭 → Add → Post Processors → JSON Extractor
- Names of created variables: userKey
- JSON Path expressions: $.userKey
- Match No.: 1
- Default Values: NOT_FOUND
3️⃣ SUCCESS 될 때까지 폴링 반복 만들기 (While Controller)
Step D) maxLoop 변수 초기화 (한 번만)
Thread Group 우클릭 → Add → Config Element → User Defined Variables
- Name: maxLoop
- Value: 200
- (폴링 최대 200번까지만, 무한루프 방지)
- Name: status
- Value: QUEUED
- (초기값)
Step E) While Controller 추가
Thread Group 우클릭 → Add → Logic Controller → While Controller
While Condition에 아래를 넣어:
${__groovy(vars.get('maxLoop').toInteger() > 0 && vars.get('status') != 'SUCCESS')}
뜻:
- maxLoop가 0보다 크고
- status가 SUCCESS가 아닐 동안 반복
Step F) While 안에 02_poll_me 만들기
While Controller 우클릭 → Add → Sampler → HTTP Request
- Name: 02_poll_me
- Method: GET
- Path: /api/lectures/1/queue/me
- Parameters:
- userKey = ${userKey}
F-1) poll 응답에서 status 뽑기
02_poll_me 우클릭 → Add → Post Processors → JSON Extractor
- Names of created variables: status
- JSON Path expressions: $.status
- Match No : 1
- Default Values: UNKNOWN
이제 매 폴링마다 ${status}가 QUEUED/SUCCESS/NOT_IN_QUEUE로 업데이트돼.
Step G) While 안에 Timer 추가 (폴링 간격)
While Controller 우클릭 → Add → Timer → Constant Timer
- 200ms~1000ms 추천
- 실전 폴링은 1초가 흔한데,
- 테스트는 빨리 끝내려면 200~500ms도 괜찮아 (자소서엔 “테스트용으로 간격 조절”이라고 쓰면 됨)
예: 200
Step H) maxLoop 감소시키기 (무한루프 방지)
While Controller 우클릭 → Add → Post Processors → JSR223 PostProcessor
Language: groovy
Script:
def n = vars.get('maxLoop') as int
vars.put('maxLoop', String.valueOf(n - 1))
이제 폴링이 무한으로 돌지 않고 최대 200회 안에 끝나.
4️⃣ SUCCESS인 경우에만 enroll 호출하기
Step I) If Controller 추가
Thread Group 우클릭 → Add → Logic Controller → If Controller
Condition에 넣기:
${__groovy(vars.get('status') =='SUCCESS')}
Step J) 03_enroll 만들기 (If 안에)
If Controller 우클릭 → Add → Sampler → HTTP Request
- Name: 03_enroll
- Method: POST
- Path: /api/lectures/1/enroll
Parameters:
- userKey = ${userKey}
(너 컨트롤러가 @RequestParam String userKey 형태라서 이게 정확히 맞아)
5️⃣ 실행 전에 “1명으로 정상동작 확인” (이거 꼭!)
처음부터 300명 돌리면 뭐가 문제인지 못 찾아.
확인용 설정
- Users: 1
- Ramp-up: 1
- maxLoop: 10
- Timer: 200
실행 후 View Results in Table에서 흐름이:
- enqueue 1번
- poll 여러 번
- SUCCESS 나오면 enroll 1번
이렇게 나오면 완벽.
6️⃣ 본 테스트(동시성) 추천 값
- 먼저: Users 100 / Ramp-up 20
- 성공하면: Users 300 / Ramp-up 30
- 더 욕심내면: Users 1000 / Ramp-up 100
7️⃣ “성공” 판단 기준(가장 중요)
JMeter 결과도 중요하지만, 이 테스트의 진짜 성공은 DB 정합성이야.
✅ 테스트가 끝난 뒤 DB에서 확인:
- Enrollment 테이블 row 수가 정확히 100인지
- Lecture.enrolled가 정확히 100인지
- “정원 마감” 에러가 일부 발생해도 괜찮음(그건 정상)
- 중요한 건 “초과 저장”이 없어야 함
정원 100인데 Enrollment가 101 이상이면 동시성 실패.
'프로젝트 > 스프링 부트 3 백엔드 개발자 되기 Blog + 선착순 강의 프로젝트' 카테고리의 다른 글
| ⏰🚨 동시성 테스트 중 500 Internal Server Error 발생 원인과 해결 (1) | 2026.02.23 |
|---|---|
| ⏰🚨 Enroll 동시성 테스트에서 신청이 거의 발생하지 않은 문제(JMeter) (0) | 2026.02.15 |
| ⏰💡 폴링 API 부하 테스트 (500명 실험) (0) | 2026.02.15 |
| ⏰💡 JMeter 구성 요소 해석해보기 (1) | 2026.02.15 |
| ⏰💡 폴링 API 부하테스트 진행 방법 (JMeter) (0) | 2026.02.15 |