-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
📋 상위 이슈
🔍 문제점
웨이팅 등록 서비스()의 멱등키 처리에서 다음 세 가지 문제가 발견되었습니다:
1. 멱등키 검증 순서 문제
- 현재: 웨이팅 번호 생성(line 67) → Redis 시퀀스 증가 → 멱등키 확인(line 74)
- 문제: 동일한 Idempotency-Key로 재요청 시에도 일일 시퀀스가 소모됨
- 영향: 시퀀스 번호 낭비, 웨이팅 번호 불일치 가능성
2. Null/빈 멱등키 처리 누락
- 현재: Idempotency-Key 헤더가 null이거나 빈 문자열일 때 검증 없이 Redis에 저장/조회
- 문제: "null" 키로 Redis 오염, 모든 null 요청이 같은 엔트리 공유
- 영향: 서로 다른 요청이 동일한 멱등 응답을 받을 수 있음
3. Race Condition (find→save 패턴 비원자성)
- 현재:
findByKey()→ 없으면 →save()패턴 사용 - 문제: 두 연산 사이에 다른 요청이 끼어들 수 있음 (redisTemplate.set()은 SETNX가 아님)
- 영향: 동시 요청 시 양쪽 모두 등록 로직 실행, 중복 웨이팅 생성 가능
✅ 해결 방안
1. 멱등키 검증 순서 변경
// BEFORE: line 67-74
String waitingNumber = generateWaitingNumber(storeId, timestamp);
String idempotentKey = httpServletRequest.getHeader("Idempotency-Key");
Optional<WaitingIdempotencyValue> existingIdempotencyValue =
waitingIdempotencyRepository.findByKey(idempotentKey);
// AFTER: 멱등키 검증을 먼저 수행
String idempotentKey = httpServletRequest.getHeader("Idempotency-Key");
Optional<WaitingIdempotencyValue> existingIdempotencyValue =
waitingIdempotencyRepository.findByKey(idempotentKey);
if (existingIdempotencyValue.isPresent()) {
return existingIdempotencyValue.get().getResponse();
}
String waitingNumber = generateWaitingNumber(storeId, timestamp);2. Null/빈 멱등키 검증 추가
String idempotentKey = httpServletRequest.getHeader("Idempotency-Key");
if (idempotentKey == null || idempotentKey.trim().isEmpty()) {
throw new InvalidIdempotencyKeyException(); // 또는 적절한 처리
}3. 원자적 연산으로 변경
- Option A: Redis
setIfAbsent()사용
Boolean success = redisTemplate.opsForValue()
.setIfAbsent(key, value, duration);
if (!success) {
// 이미 존재하는 경우
return redisTemplate.opsForValue().get(key);
}- Option B: Lua 스크립트 활용 (더 복잡한 로직에 적합)
local key = KEYS[1]
local value = ARGV[1]
local ttl = ARGV[2]
if redis.call('EXISTS', key) == 1 then
return redis.call('GET', key)
else
redis.call('SET', key, value, 'EX', ttl)
return value
end📍 영향 범위
- 파일:
nowait-app-user-api/src/main/java/com/nowait/applicationuser/waiting/service/WaitingService.java - 라인: 64-78, 112-114
- 관련 클래스:
WaitingIdempotencyRepository
🔗 참고 링크
- PR: Refactor : User 웨이팅 등록 및 삭제 기능 리팩토링 #349
- 리뷰 코멘트: Refactor : User 웨이팅 등록 및 삭제 기능 리팩토링 #349 (comment)
👤 담당자
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels