
티켓팅 서비스에서 가장 위험한 순간 중 하나는
한 사용자가 동시에 여러 번 예약 요청을 보내는 상황입니다.
예를 들어
- 예약 버튼 연타
- 브라우저 여러 개 실행
- 새로고침 반복
- 악의적인 API 반복 호출
이런 상황에서 중복 예약이 발생하면
- booking 중복 생성
- booked_count 증가 오류
- 초과 예약
문제가 발생할 수 있습니다.
특히 선착순 티켓팅 서비스에서는 반드시 검증해야 하는 부분이라고 생각했습니다.
현재 제 프로젝트는 Redis 기반 대기열 시스템을 사용하고 있습니다.
대기열을 통과하면 아래와 같은 입장권을 발급합니다.
admitted:concert:{concertId}:user:{userId}
admitted:concert:1:user:2
이 key가 존재해야 예약 API 호출이 가능합니다.
즉,
입장권은 반드시 1번만 사용 가능해야 합니다.
그런데 문득 이런 생각이 들었습니다.
"동일 사용자가 동시에 여러 번 요청하면 정말 1번만 예약될까?"
그래서 직접 테스트해봤습니다.
1️⃣ 테스트 목표
이번 테스트에서 검증하고 싶었던 건 3가지였습니다.
👉 동일 사용자 중복 예약 방지
50번 동시에 요청해도 예약은 1건만 생성되어야 합니다.
👉admitted 없는 요청 차단
입장권이 없으면 예약 자체가 실패해야 합니다.
👉 booked_count 정합성 유지
예약 1건이면 booked_count도 정확히 1 증가해야 합니다.
2️⃣ 테스트 환경
- Backend : Spring Boot
- DB : MySQL
- Queue : Redis
- 테스트 도구 : Apache JMeter
테스트 API
POST /api/concerts/{concertId}/booking
3️⃣ 테스트 전 데이터 초기화
기존 데이터를 먼저 제거했습니다.
delete from booking
where concert_id = 1
and user_id = 2;
예약 수 초기화
update concert
set booked_count = 0
where id = 1;
4️⃣ Redis 입장권 발급
Redis에 입장권을 단 1개만 발급했습니다.
SETEX admitted:concert:1:user:2 600 1
의미:
- concertId = 1
- userId = 2
- TTL 600초
즉,
예약 가능 권한은 딱 1개만 존재하는 상태입니다.
5️⃣ 단일 요청 테스트
먼저 Postman으로 정상 동작 여부를 확인했습니다.
POST /api/concerts/1/booking
결과
200 OK
DB 확인 결과
- booking 1건 생성
- booked_count 1 증가
정상 동작 확인 완료
6️⃣ JMeter 동시 요청 테스트
이제 핵심 테스트입니다.
Apache JMeter 설정
- Thread : 50
- Ramp-up : 1초
- Loop Count : 1
- Synchronizing Timer : 50
즉,
동일 사용자가 동시에 50번 예약 요청을 보내는 상황
을 만들었습니다.
테스트 직전 다시 admitted를 발급했습니다.
SETEX admitted:concert:1:user:2 600 1
7️⃣ 테스트 결과
총 요청 수
50건
성공
1건
실패
49건
실패 응답
{
"message": "입장 권한이 없습니다. (입장권이 없거나 만료/이미 사용됨)",
"status": 409
}
처음 결과를 봤을 때 오히려 안심했습니다.
제가 원했던 결과였기 때문입니다.
8️⃣ DB 검증
예약 개수 확인
select count(*)
from booking
where concert_id = 1
and user_id = 2;
결과
1
booked_count 확인
select booked_count
from concert
where id = 1;
결과
1
즉,
- 중복 예약 없음
- booked_count 정합성 유지
- 초과 예약 없음
모두 확인했습니다.
9️⃣ 왜 이런 결과가 나왔을까?
예약 로직은 다음 흐름으로 동작합니다.
admitted 조회
→ admitted 삭제
→ 예약 생성
첫 번째 요청만
admitted 존재 → 성공
나머지 요청은
admitted 없음 → 실패
결과적으로 Redis 입장권이 1회성 토큰처럼 동작하고 있었습니다.
🔟 이번 테스트에서 배운 점
처음에는 Redis를 단순한 대기열 저장소라고 생각했습니다.
하지만 실제로 테스트해보니 Redis는
- 대기열 관리
- 중복 예약 방지
- 데이터 정합성 보호
역할까지 수행하고 있었습니다.
그리고 무엇보다
"잘 될 것 같아"
가 아니라
실제로 동시 요청 테스트로 검증했다
는 점이 가장 의미 있었습니다.
'프로젝트 > 공연 티켓팅 프로젝트' 카테고리의 다른 글
| 🎟️ Docker-compose up 한 번으로 실행되는 백엔드 만들기 (1) | 2026.05.18 |
|---|---|
| 🎟️ MySQL 인덱스 실험: 예약 만료 배치 쿼리 성능 개선 (10만 건 실험) (1) | 2026.05.13 |
| 🎟️ 결제 API는 정말 중복 결제를 막을 수 있을까? (1) | 2026.04.27 |
| 🎟️ 예약 API 동시성 테스트 (다중 사용자 경쟁) 결과 보고 (1) | 2026.04.27 |
| 🎟️ 선착순 강의에서 공연 티켓팅으로 확장한 이유 (2) | 2026.04.17 |