1. 가설 : 문제점 제기
가설 1
가설 2
2. 어떻게 테스트 해볼 수 있을까? -> 부하테스트 -> k6 테스트 : 왜 k6 ?
코드 구현
k6는 크게 두 가지 방식으로 부하를 만들 수 있다.
💡Closed Model (vus / ramping-vus executor)
- 이전 Iteration이 끝나야 다음 Iteration이 시작되는 모델
(Iteration : Virtual User(VU)가 default() 함수를 한 번 처음부터 끝까지 실행하는 것을 의미)
"The next iteration doesn't start until the previous one finishes."
- 흐름 예시
VU 1 -> HTTP 요청 -> 응답 대기 -> 응답 완료 -> 다음 요청 시작
- 새로운 요청 시작 시점이 이전 요청이 언제 끝났는지에 의존한다.
- 코드 예시
예시
❗️문제점
- 부하가 없는 정상적인 서버의 응답시간이 100ms 라고 가정했을 때, 1초동안 약 10번의 요청을 보낼 수 있다.
- 그런데 부하로 인해 서버가 느려지고 응답시간이 2초가 되었지만, closed model 은 응답을 받아야 VU가 다음 요청을 보낼 수 있기 때문에 오히려 부하가 줄어드는 현상이 생긴다.
- 이 현상을 Coordinated Omission 이라고 한다.
"Slower response times means longer iterations and a lower arrival rate."
응답이 느려질수록 요청 도착률(Arrival Rate)도 함께 줄어드는 문제
- 흐름 예시
응답시간
100ms
↓
1초에
10번 요청
----------------
응답시간
2초
↓
2초에
1번 요청
💡Open Model (constant-arrival-rate / ramping-arrival-rate executor)
- Closed Model의 문제를 해결하기 위해 나온 모델
- 핵심은, 응답이 끝났는지와 관계없이 새로운 요청을 시작한다는 것
"VU iterations arrive independently of iteration completion."
- 흐름 예시
1초 -> 무조건 요청 시작 -> 응답 기다리지 않음 -> 2초 -> 또 요청 시작
- 코드 예시
예시
❗️왜 Open Model이 필요할까?
- 실제 서비스는 사용자가 응답이 느리다고 새로운 사용자가 안 들어오는 것은 아니다.
- 예를 들어, 네이버에서
- 따라서, Open Model 이 현실 트래픽을 더 잘 모방한다고 할 수 있다.
💡비교
| 항목 | Closed Model | Open Model |
| 요청 시작 기준 | 이전 Iteration 종료 후 시작 | 정해진 시간마다 시작 |
| 응답시간 영향 | 받음 | 받지 않음 |
| 부하량 | 응답이 느려질수록 감소 | 일정하게 유지 |
| 현실 트래픽 재현 | 상대적으로 낮음 | 높음 |
| 대표 Executor | constant-vus, ramping-vus | constant-arrival-rate, ramping-arrival-rate |
- Open : 이 API의 최대 지속 가능 처리량(천장)은 어디인지 = 한계점 찾기(capacity test)
- Closed : 한계 안에서 동시성이 오를 때 어떻게 저하되고, 리팩토링으로 얼마나 개선됐는지 = 저하 특성 + 전후 비교
프로젝트에 적용된 파일 구조
product/load-test/
├── README.md # 실행 방법, 사전 준비(시딩), 결과 해석
├── seed/
│ └── seed.sql # 테스트용 상품+재고를 DB에 직접 삽입 (정적)
├── lib/
│ └── config.js # 공통: BASE_URL, 핫 productId 풀, 헬퍼
├── scenario1-lock-contention.js # [Closed] PUT /v1/stocks — 락 경합
└── scenario2-stock-lookup.js # [Open] GET /v1/stocks/{id} — DB 부하
- lib/config.js — 두 시나리오가 공유하는 상수(서버 주소, productId 목록)를 한 곳에서 관리하여 유지보수성을 용이하게한다.
- 시나리오별 파일 분리 — 부하 모델(closed/open)과 executor 설정이 완전히 다르므로 각각 독립 실행
- seed/seed.sql — 시딩을 코드(k6)와 분리, 테스트 전에 딱 한 번 실행하는 준비물
3. 수치화
참고 자료
1) Grafana Docs : Open and closed models
https://grafana.com/docs/k6/latest/using-k6/scenarios/concepts/open-vs-closed/
Open and closed models | Grafana k6 documentation
Open and closed models Different k6 executors have different ways of scheduling VUs. Some executors use the closed model, while the arrival-rate executors use the open model. In short, in the closed model, VU iterations start only when the last iteration f
grafana.com
'Projects > hub-eleven' 카테고리의 다른 글
| [동시성 처리] Redisson은 어떻게 Redis Pub/Sub을 이용해 재시도(Retry) 로직을 구현할 수 있을까? (0) | 2026.06.24 |
|---|---|
| [트러블슈팅] Redisson 분산 락 적용 중 트랜잭션 커밋 순서 문제를 해결한 과정 (2) (0) | 2026.06.23 |
| [트러블슈팅] Redisson 분산 락 적용 중 트랜잭션 커밋 순서 문제를 해결한 과정 (1) (0) | 2026.06.22 |
| [동시성 처리] 재고 감소 락 추상화 및 Redisson 락 구현 (아키텍처 구조 보완 필요) (0) | 2026.06.02 |
| [동시성 처리] RedissonClient Bean 설정 클래스 추가 (2) (리소스 보완 필요) (0) | 2026.05.28 |