Redis를 사용하여 선착순 쿠폰 시스템을 만들어보기로 했다.
쿠폰에 초점이 맞춰진만큼 로그인 기능 등은 안넣고 오로지 쿠폰 발급만 구현하려고 한다.
🎯 시스템 구성 목표
- 로그인 없이 (단, userId는 요청에 포함)
- 선착순 쿠폰 발급
- 쿠폰 재고는 Redis로 관리
- 쿠폰 발급 결과만 DB에 저장
- 빠른 응답 최우선
✅ API 설계
구분 | 내용 |
Method | POST |
URL | /api/coupons/issue |
요청 Body | { "userId": "string", "couponId": "string" } |
응답 | 성공: { "success": true, "message": "쿠폰 발급 성공" } 실패: { "success": false, "message": "쿠폰 소진" } |
✅ ERD 설계
[Coupon] (쿠폰 종류 관리 테이블)
- coupon_id (PK) : bigint (auto increment)
- name : varchar
- total_quantity : int
- created_at : timestamp
- updated_at : timestamp
[CouponIssue] (쿠폰 발급 이력 테이블)
- id (PK) : bigint (auto increment)
- user_id : varchar
- coupon_id (FK) : bigint
- issued_at : timestamp
- Coupon 테이블은 "어떤 쿠폰이 몇 장 있는지" 정의
- CouponIssue 테이블은 "누가 어떤 쿠폰을 언제 발급받았는지" 기록
✅ Redis 구조
키 이름 예시 | 타입 | 설명 |
coupon:{couponId}:stock | String (Integer) | 쿠폰 잔여 수량 관리 |
coupon:1234:stock = 500 (500장 남음)
- 발급할 때마다 DECR 명령어로 -1 감소
- 0 이하면 발급 불가 처리
✅ 동작 흐름도
[Client]
↓ POST /api/coupons/issue
[Server]
↓
1. Redis 쿠폰 수량 조회 & 감소 (DECR)
2. 만약 수량 0 미만이면 실패 응답
3. 수량 0 이상이면 성공 응답
4. 발급 이력 DB에 저장 (CouponIssue)
✅ 1차 프로젝트 구성 요약
항목 | 기술/구성 |
백엔드 | Spring Boot (Java) |
DB | MariaDB |
In-memory 캐시 | Redis |
부하 테스트 도구 | k6 + InfluxDB + Grafana |
기본 구조 | Redis로 수량관리, MariaDB로 발급이력 저장 |
📈 초기 개발/테스트 포인트
- Race Condition 방지: Redis DECR는 원자 연산이므로 별도 락 필요 없음.
- 초과 발급 방지: DECR 결과를 무조건 체크해야 함 (0 이하면 발급 실패)
- 중복 발급 방지(추후): userId+couponId를 Redis에 임시 저장하면 강화 가능
- DB 저장 실패 대비: 로그 남기고, 필요하면 재시도
'프로젝트 > 쿠폰' 카테고리의 다른 글
[쿠폰] 테스트를 위한 k6 + InfluxDB + Grafana 구성 (1) | 2025.04.30 |
---|---|
[쿠폰] 쿠폰 발급 수정 (saveAll, @Transactional) (0) | 2025.04.29 |
[쿠폰] 쿠폰 발급 (Redis Stream, CustomDbWorker) (0) | 2025.04.29 |
[쿠폰] 쿠폰 조회 (Redis 예외처리) (0) | 2025.04.28 |
[쿠폰] 쿠폰 생성 (@Transactional, CustomException) (0) | 2025.04.28 |