FEAT : 온보딩 반복일정 등록 API 중복 요청 방어 - #368
Conversation
📝 Walkthrough개요Redisson 분산 락 유틸을 즉시 획득 방식으로 리팩토링하고, 친구 팔로우에서 락 기능을 제거하며, 온보딩 루틴 저장에 새로운 락 기반 처리와 중복 저장 검증을 도입합니다. 변경사항동시성 락 관리 리팩토링
온보딩 루틴 저장 락 및 중복 방지
테스트 통합 및 확장
시퀀스 다이어그램sequenceDiagram
participant Client
participant OnboardingController
participant OnboardingLockService
participant OnboardingService
participant RoutineRepository
Client->>OnboardingController: saveRoutines(request)
OnboardingController->>OnboardingLockService: saveRoutinesWithLock(request, user)
OnboardingLockService->>OnboardingService: saveRoutines(request, user)
OnboardingService->>RoutineRepository: existsByUser(user)
alt 반복일정 이미 존재
RoutineRepository-->>OnboardingService: true
OnboardingService-->>OnboardingLockService: 예외 발생
else 반복일정 미존재
RoutineRepository-->>OnboardingService: false
OnboardingService->>OnboardingService: 루틴 엔티티 변환 및 저장
end
예상 코드 리뷰 노력🎯 3 (Moderate) | ⏱️ ~25 분 관련 이슈
관련 PR
제안 레이블
시
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Test Results57 tests 57 ✅ 4s ⏱️ Results for commit 2a0bc98. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/main/java/umc/teumteum/server/domain/user/service/OnboardingServiceImpl.java`:
- Around line 352-357: The validateRoutineNotSaved method currently throws
OnboardingException with UserErrorStatus.INVALID_STEP which is ambiguous for
duplicate routine saves; add a new enum value
UserErrorStatus.ROUTINE_ALREADY_REGISTERED (e.g., HttpStatus.CONFLICT, code
"ONBOARDING4092", message "반복일정이 이미 등록되어 있습니다.") and update
validateRoutineNotSaved to throw new
OnboardingException(UserErrorStatus.ROUTINE_ALREADY_REGISTERED) when
routineRepository.existsByUser(user) returns true so the error clearly signals a
duplicate routine registration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7f8da0af-a933-4578-bce1-928db8839487
📒 Files selected for processing (11)
src/main/java/umc/teumteum/server/domain/friend/controller/FriendController.javasrc/main/java/umc/teumteum/server/domain/friend/service/FriendLockService.javasrc/main/java/umc/teumteum/server/domain/friend/service/FriendLockServiceImpl.javasrc/main/java/umc/teumteum/server/domain/user/controller/OnboardingController.javasrc/main/java/umc/teumteum/server/domain/user/repository/RoutineRepository.javasrc/main/java/umc/teumteum/server/domain/user/service/OnboardingLockService.javasrc/main/java/umc/teumteum/server/domain/user/service/OnboardingLockServiceImpl.javasrc/main/java/umc/teumteum/server/domain/user/service/OnboardingServiceImpl.javasrc/main/java/umc/teumteum/server/global/util/RedissonLockUtil.javasrc/test/java/umc/teumteum/server/integration/user/service/OnboardingLockServiceTest.javasrc/test/java/umc/teumteum/server/unit/user/service/OnboardingServiceTest.java
💤 Files with no reviewable changes (2)
- src/main/java/umc/teumteum/server/domain/friend/service/FriendLockServiceImpl.java
- src/main/java/umc/teumteum/server/domain/friend/service/FriendLockService.java
👀 관련 이슈
#367
✨ 작업한 내용
1. 온보딩 반복일정 등록 API에 사용자 단위 no-wait 분산락을 적용했습니다.
현재 서비스는 동일 계정의 다중 세션 로그인이 가능한 구조이므로, 여러 기기나 세션에서 같은 사용자의 반복일정 저장 요청이 동시에 들어올 수 있습니다. 반복일정 등록 API는 한 번의 요청에서 여러 개의 Routine을 저장하고, 오늘 요일에 해당하는 반복일정을 기반으로 Schedule까지 함께 생성하는 사용자 단위 작업입니다.
처음에는
user_id, weekday, start_time, end_time조합에 대한 DB 유니크 제약을 고려했지만, 이는 동일한 Routine row의 중복만 방지할 수 있습니다. 동일 사용자가 여러 세션에서 서로 다른 반복일정 목록으로 동시에 등록 요청을 보내는 경우에는 각 요청의 데이터가 서로 다르므로 유니크 제약에 걸리지 않고 모두 저장될 수 있다고 판단했습니다.이 경우 사용자 입장에서는 하나의 반복일정 등록 작업만 수행했다고 기대하지만, 실제로는 여러 요청이 모두 성공하여 Routine과 Schedule이 중복 생성되거나 서로 다른 등록 결과가 함께 반영될 수 있습니다. 이에 반복일정 등록 작업 전체를 사용자 단위로 보호하기 위해 no-wait 분산락을 적용했습니다. 동일 사용자의 등록 요청이 동시에 들어오면 하나의 요청만 처리하고, 나머지 요청은 즉시 실패시켜 동일 사용자의 반복일정 등록 작업이 동시에 수행되지 않도록 보장했습니다.
2. 기존 반복일정 저장 여부 검증을 추가했습니다.
현재 서비스는 동일 계정의 다중 세션 로그인이 가능한 구조이므로, 한 기기에서 반복일정 저장을 완료한 뒤 다른 기기에서 뒤늦게 동일 API를 호출할 수 있습니다. 분산락은 동시에 들어온 요청만 제어할 수 있고, 첫 요청이 완료된 이후의 시간차 재호출은 막을 수 없기 때문에 기존 반복일정 저장 여부 검증을 추가했습니다.
3. 온보딩 반복일정 등록 API 테스트를 추가했습니다.
4. 팔로우 API의 분산락을 제거했습니다.
기존에는 중복 팔로우 요청을 방어하기 위해 DB 유니크 키와 분산락을 모두 적용하려 했으나, 팔로우의 경우 핵심 정합성이
follower_user_id,following_user_id조합의 중복 저장 방지로 귀결되기 때문에 DB 유니크 키만 사용하는 것이 더 적합하다고 판단했습니다. 분산락을 유지하면 Redis 의존성, 락 획득/해제 처리, 장애 시 영향 범위가 추가되는 반면, 팔로우 API에서 얻는 이점은 유니크 제약 위반을 사전에 줄이는 정도에 가깝습니다.따라서 모든 중복 요청 방어에 분산락을 일괄 적용하기보다는, DB 제약으로 해결 가능한 경우와 애플리케이션 레벨의 동시성 제어가 필요한 경우를 구분해 적용했습니다. 온보딩 반복일정 등록 API처럼 동일 사용자의 여러 세션에서 서로 다른 데이터로 요청이 들어올 수 있고, 사용자 단위 등록 작업 전체의 중복 실행을 제어해야 하는 경우에는 분산락을 적용했습니다. 반면 팔로우 API처럼
follower_user_id,following_user_id조합 자체가 중복 방지 기준이 되는 경우에는 DB 유니크 키와 예외 변환만으로 단순하고 명확하게 처리하도록 정리했습니다.5. 온보딩 리마인드 알림 등록 API의 중복 저장 방어를 추가했습니다.
리마인드 알림 등록 API는 온보딩 흐름상 반복일정 등록 이후 호출되는 단계입니다. 반복일정 등록 API에서 사용자 단위 락과 기존 저장 여부 검증을 통해 다중 세션의 반복일정 등록 성공을 1회로 제한하므로, 리마인드 알림 단계에서는 주로 버튼 연타나 동일 요청의 중복 저장을 방어하면 된다고 판단했습니다. 리마인드 알림은
user_id,minutes_before조합, 스케줄 리마인더는schedule_id,reminder_time조합이 중복 방지 기준으로 명확하므로, 분산락 대신 DB 유니크 키와 예외 변환으로 처리했습니다.🌀 PR Point
X
🍰 참고사항
X
📷 스크린샷 또는 GIF
X
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Refactor