이 프로젝트는 동시성 제어가 필요한 쿠폰 발급 기능을 포함하고 있으며, 이를 해결하기 위해 Redisson 기반의 분산 락을 도입했다.
Redisson은 Redis 위에서 동작하는 Java 기반의 분산 도구로, 분산 락, 캐시, 메시징 기능을 제공하며 tryLock()과 unlock() 같은 친숙한 API를 통해 락을 손쉽게 구현할 수 있게 해준다.
비관적 락은 DB 레벨에서 락을 걸기 때문에 성능 부담이 크고 병목이 생길 수 있음
낙관적 락은 충돌 시 retry 비용이 크고, 충돌이 빈번한 상황(선착순 발급)에서는 적합하지 않음
분산락 (Redisson 기반)은 Redis의 빠른 응답 속도와 락 TTL, 재시도, 해제 등의 기능 덕분에 트래픽이 많은 이벤트 처리에 최적
처음에는 Redis의 decrement()를 먼저 호출해서 재고를 차감하고, 이후 DB에 쿠폰을 저장하려 했다. 하지만 이 방식에는 문제가 있었다:
쿠폰 수량을 Redis에서 먼저 줄이는데,
DB에서 유저가 이미 쿠폰을 발급받은 사용자라는 조건이 걸리면 저장이 실패함
이미 줄어든 Redis 재고는 다시 increment()로 되돌려야 했고,
예외 처리 로직이 복잡해지고 신뢰성이 떨어졌음
이러한 한계로 인해 튜터의 조언에 따라 아래와 같은 순서로 전환하게 됐다:
decrement)redis는 직접 setnx/set 등을 조작해 락을 획득해야하지만 Redisson은 tryLock(), unlock()으로 간단히 획득하능하다.
또한 코드가 더 간결해진다.
이 프로젝트는 단일 서버 기반의 개발/학습 환경에서 동작하므로, Redisson의 여러 모드 중 가장 단순한 Single Server Mode를 사용했다.

RedissonConfig 설정은 공식문서에 따르면 다음과 같다.

Redisson이 제공하는 분산 락 인터페이스 중 하나로, java.util.concurrent.locks.Lock과 유사한 구조를 가지고 있다.
tryLock(long waitTime, long leaseTime, TimeUnit unit)
-`waitTime`: 락 획득을 시도하는 최대 시간
- `leaseTime`: 락이 자동 해제되는 시간 (죽은 락 방지)
unlock(): 락 해제