-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 랜덤 인카운터 추가, jwt 를 이용한 일시적인 이벤트 생성, 하루에 인카운터, 배틀 횟수 제한 토큰 생성 #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
""" Walkthrough이 변경사항은 게임 내 배틀 및 인카운터 매칭 시스템에 JWT 기반 토큰 버킷을 도입하고, 관련 API 및 도메인 로직을 대대적으로 리팩터링합니다. 주요 엔티티와 DTO, 서비스, 컨트롤러, 저장소 계층이 토큰 기반 인증 및 매칭으로 전환되었으며, 골드 손실 로직과 로그 메시지 등도 일부 개선되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller
participant UseCase
participant DomainService
participant TokenBucketRepo
participant JwtUtil
Client->>Controller: 배틀 요청(BattleRequest: battleToken)
Controller->>UseCase: battle(playerId, BattleRequest)
UseCase->>JwtUtil: battleToken에서 enemyId 추출
UseCase->>DomainService: getRandomEnemyCharacter(userId, playerId)
DomainService->>TokenBucketRepo: 토큰 버킷 조회 및 consumeBattleToken()
DomainService-->>UseCase: 적 캐릭터 반환
UseCase-->>Controller: BattleHistoryResponse 반환
Controller-->>Client: 결과 응답
Client->>Controller: 인카운터 선택(EncounterChoiceRequest: encounterToken)
Controller->>UseCase: encounterChoice(userId, EncounterChoiceRequest)
UseCase->>JwtUtil: encounterToken에서 encounterId 추출
UseCase->>DomainService: getRandomEncounter(playerId)
DomainService->>TokenBucketRepo: 토큰 버킷 조회 및 consumeEncounterToken()
DomainService-->>UseCase: 인카운터 반환
UseCase-->>Controller: EncounterResultResponse 반환
Controller-->>Client: 결과 응답
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms (1)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (2)
src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java (2)
107-136: 중복된 보상 처리 로직 리팩토링배틀 종료 시 보상 처리 로직이 중복되어 있습니다. 별도 메서드로 추출하여 코드 중복을 제거하세요.
+private void processBattleReward(GameCharacter player, boolean isPlayerWinner, BattleLog battleLog) { + if (isPlayerWinner) { + player.earnGold(100L); + battleLog.add("전투 승리보상으로 100 골드가 지급되었습니다."); + } else { + player.loseGold(25L); + battleLog.add("패배하여 25 골드를 갈취당했습니다."); + } +} // battle 메서드 내부 if (!alive) { battleLog.setPlayerWin(attacker == playerContext); - - if (attacker == playerContext) { - player.earnGold(100L); - battleLog.add("전투 승리보상으로 100 골드가 지급되었습니다."); - } else { - player.loseGold(25L); - battleLog.add("패배하여 25 골드를 갈취당했습니다."); - } + processBattleReward(player, attacker == playerContext, battleLog); return battleLog; } // 두 번째 부분도 동일하게 수정 if (!alive) { battleLog.setPlayerWin(defender == playerContext); - - if (defender == playerContext) { - player.earnGold(100L); - battleLog.add("전투 승리보상으로 100 골드가 지급되었습니다."); - } else { - player.loseGold(25L); - battleLog.add("패배하여 25 골드를 갈취당했습니다."); - } + processBattleReward(player, defender == playerContext, battleLog); return battleLog; }
187-199: 토큰 소비 순서 및 빈 리스트 처리 필요
- 토큰이 먼저 소비되어 실패 시에도 돌아오지 않습니다.
- 인카운터 목록이 비어있을 경우
IndexOutOfBoundsException이 발생할 수 있습니다.public RandomEncounter getRandomEncounter(Long playerId) { GameCharacterMatchTokenBucket playerTokenBucket = matchTokenBucketRepository.findByCharacterId(playerId) .orElseThrow(() -> new GameException(GameExceptionCode.PLAYER_TOKEN_BUCKET_NOT_EXISTS)); - playerTokenBucket.consumeEncounterToken(); - List<RandomEncounter> encounters = encounterRepository.findAllEncounters(); + + if (encounters.isEmpty()) { + throw new GameException(GameExceptionCode.NO_AVAILABLE_ENCOUNTERS); + } int randomIndex = ThreadLocalRandom.current().nextInt(encounters.size()); - - return encounters.get(randomIndex); + RandomEncounter selectedEncounter = encounters.get(randomIndex); + + playerTokenBucket.consumeEncounterToken(); + return selectedEncounter; }
🧹 Nitpick comments (4)
src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skilldecorator/DefencePenetrationDecorator.java (1)
44-47: 로그 문구 일관성 검토
LEGENDARY 등급 메시지에추가 상승을 사용한 반면, 다른 등급에서는추가 증가를 사용 중입니다. 전체 표현 통일을 검토해주세요.src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacter.java (1)
105-107: 골드 손실 로직 개선 승인
loseGold메서드 추가로 골드 손실 로직이 명확해졌습니다.Math.max를 사용하여 골드가 음수가 되지 않도록 보장한 점이 좋습니다.매개변수 검증을 추가하면 더 안전합니다:
public void loseGold(long gold) { + if (gold < 0) { + throw new IllegalArgumentException("골드 손실량은 음수일 수 없습니다."); + } this.gold = Math.max(0L, this.gold - gold); }src/main/java/org/ezcode/codetest/common/security/util/JwtUtil.java (1)
26-26: 게임 토큰 만료 시간 검토가 필요합니다.60초의 만료 시간은 보안상 우수하지만, 실제 게임 플레이 시나리오를 고려할 때 너무 짧을 수 있습니다. 사용자가 인카운터나 배틀을 선택하는 데 충분한 시간인지 검토해보시기 바랍니다.
게임 플레이 테스트를 통해 60초가 충분한 시간인지 확인해보시기 바랍니다.
src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java (1)
176-185: 토큰 소비 순서 개선 필요토큰이 실제 매칭 작업 전에 소비되어, 매칭이 실패해도 토큰은 돌아오지 않습니다. 매칭 성공 후 토큰을 소비하거나, 실패 시 보상 메커니즘을 고려해보세요.
public GameCharacter getRandomEnemyCharacter(Long userId, Long playerId) { GameCharacterMatchTokenBucket playerTokenBucket = matchTokenBucketRepository.findByCharacterId(playerId) .orElseThrow(() -> new GameException(GameExceptionCode.PLAYER_TOKEN_BUCKET_NOT_EXISTS)); - playerTokenBucket.consumeBattleToken(); - - return characterRepository.findRandomCharacter(userId) - .orElseThrow(() -> new GameException(GameExceptionCode.RANDOM_CHARACTER_MATCHING_FAIL)); + GameCharacter randomCharacter = characterRepository.findRandomCharacter(userId) + .orElseThrow(() -> new GameException(GameExceptionCode.RANDOM_CHARACTER_MATCHING_FAIL)); + + playerTokenBucket.consumeBattleToken(); + return randomCharacter; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (34)
src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/BattleRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/EncounterChoiceRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/RandomEncounterSaveRequest.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/EncounterResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/MatchingBattleResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/MatchingEncounterResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java(6 hunks)src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java(4 hunks)src/main/java/org/ezcode/codetest/common/security/hander/CustomSuccessHandler.java(1 hunks)src/main/java/org/ezcode/codetest/common/security/util/JwtUtil.java(3 hunks)src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacter.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacterMatchTokenBucket.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/encounter/EncounterLog.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/encounter/RandomEncounter.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/MatchTokenBucketRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java(6 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AmbushBanditsBad.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AmbushBanditsGood.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AncientRuinsTrap.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/BossEncounterBad.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/GamblingBad.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/StatSpeed.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/TreasureCacheFound.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/WildBeastsAttack.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/WildBeastsEscape.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skilldecorator/DefencePenetrationDecorator.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/ButterflySkill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/DefencePenetrationSkill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/NoSkill.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java(4 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java (1)
Learnt from: chat26666
PR: ezcode-my/backend#64
File: src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java:0-0
Timestamp: 2025-06-15T04:37:29.231Z
Learning: EncounterChoiceRepositoryImpl in src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/EncounterChoiceRepositoryImpl.java is intentionally a skeleton implementation that is work-in-progress and will be completed later.
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (75)
src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/ButterflySkill.java (1)
39-43: 텍스트 변경 승인
로그 메시지 표현을 “내장이 나왔습니다”에서 “내장이 삐져 나왔습니다”로 더 생동감 있게 다듬은 것은 적절합니다. 기능 로직에 영향이 없으므로 승인합니다.src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/BattleRequest.java (2)
6-13: DTO 정의 적절
BattleRequest에@Schema와@NotBlank를 활용해 배틀 토큰 입력을 명확히 검증하도록 한 점이 좋습니다.
10-11: 컨트롤러 파라미터 유효성 검증 확인
해당 DTO를 받는 컨트롤러 메서드에@Valid또는@Validated어노테이션이 적용되어 있어야 합니다. 적용 여부를 확인해주세요.src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/TreasureCacheFound.java (1)
53-53: 로그 메시지 공백 수정 승인
“%s(은)는 200 골드를 얻었습니다.”로 공백을 올바르게 조정한 것은 사용자 가독성 향상에 기여합니다. 로직에는 영향이 없으므로 승인합니다.src/main/java/org/ezcode/codetest/common/security/hander/CustomSuccessHandler.java (1)
49-56: 메서드명 변경 반영 확인
jwtUtil.createAccessToken(...)으로 호출을 변경하신 부분이JwtUtil의 시그니처와 완전히 일치하는지 확인이 필요합니다.src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/DefencePenetrationSkill.java (1)
26-27: 배틀 로그 메시지 간소화 승인불필요한 설명 문구를 제거하여 로그 메시지가 더 간결하고 직관적으로 개선되었습니다.
src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/GamblingBad.java (1)
24-24: 골드 손실 로직 명확화 승인
earnGold(-lossGold)대신loseGold(lossGold)를 사용하여 골드 손실 로직이 더 명확하고 직관적으로 개선되었습니다. 이는 음수 값 사용을 피하고 코드의 가독성을 높입니다.src/main/java/org/ezcode/codetest/application/usermanagement/auth/service/AuthService.java (4)
71-76: JWT 토큰 생성 메서드명 변경 승인
createToken에서createAccessToken으로 변경하여 토큰 유형을 명확히 구분하도록 개선되었습니다.
86-92: JWT 토큰 생성 메서드명 변경 승인기존 사용자 가입 시에도 동일하게
createAccessToken메서드를 사용하여 일관성을 유지하고 있습니다.
123-129: JWT 토큰 생성 메서드명 변경 승인로그인 프로세스에서도
createAccessToken메서드를 사용하여 토큰 유형을 명확히 구분하고 있습니다.
185-192: JWT 토큰 생성 메서드명 변경 승인토큰 갱신 시에도
createAccessToken메서드를 사용하여 전체 인증 흐름에서 일관성을 유지하고 있습니다.src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AmbushBanditsBad.java (1)
47-47: 골드 손실 로직 명확화 승인
earnGold(-lostGold)대신loseGold(lostGold)를 사용하여 골드 손실을 명시적으로 처리하도록 개선되었습니다. 다른 encounter 전략들과 일관성을 유지하는 좋은 변경사항입니다.src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AncientRuinsTrap.java (1)
35-35: 골드 손실 로직 명확화 승인
earnGold(-lostGold)대신loseGold(lostGold)를 사용하여 골드 손실 로직을 명확하게 처리하도록 개선되었습니다. 전체 encounter 전략 구현체들에서 일관성 있는 골드 관리 방식을 유지하고 있습니다.src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/BossEncounterBad.java (2)
30-30: playerContext 사용으로 일관성 개선방어력 계산에서
character.getRealStat().getDef()대신playerContext.getDef()을 사용하도록 변경한 것은 다른 인카운터 전략들과의 일관성을 위한 좋은 개선입니다.
43-43: 남은 체력 로그 추가로 가시성 향상보스 공격 후 플레이어의 남은 체력을 로그에 추가한 것은 디버깅과 게임 진행 상황 파악에 도움이 됩니다.
src/main/java/org/ezcode/codetest/domain/game/model/encounter/EncounterLog.java (1)
25-25: 로그 메시지 포맷 변경의 가독성 영향 검토 필요메시지를 개행 문자(
"\n") 대신 공백(" ")으로 연결하는 변경은 긴 인카운터 로그의 가독성에 영향을 줄 수 있습니다. 특히 여러 메시지가 포함된 경우 텍스트가 한 줄로 연결되어 읽기 어려워질 수 있습니다.UI에서 의도된 변경인지, 아니면 다른 포맷팅 방식이 필요한지 확인해 주세요.
src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/AmbushBanditsGood.java (1)
48-48: 골드 차감 로직 개선
character.earnGold(-lost)대신character.loseGold(lost)를 사용하는 것은 의도를 더 명확하게 표현하는 좋은 개선입니다. 골드 손실 로직이 더 직관적이고 읽기 쉬워졌습니다.src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/EncounterResponse.java (1)
22-26: 인카운터 선택지 텍스트 필드 추가
choice1Text와choice2Text필드 추가로 API 응답이 더욱 풍부해졌습니다. 적절한 스키마 설명과 함께 인카운터 상호작용을 위한 필수적인 정보를 제공합니다.src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/NoSkill.java (2)
32-32: 공격 실패 메시지 개선으로 몰입감 향상공격 실패 시 더욱 상세하고 서술적인 메시지로 변경하여 게임의 몰입감과 사용자 경험이 개선되었습니다.
50-50: 스턴 효과 메시지 간소화스턴 효과 메시지를 더 간결하고 명확하게 변경하여 가독성이 향상되었습니다.
src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/EncounterChoiceRequest.java (1)
10-12: JWT 토큰 기반 보안 접근 방식 적용 승인
encounterToken필드 추가가 올바르게 구현되었습니다.@NotBlank검증과 적절한 Swagger 문서화가 포함되어 있어 보안성과 API 문서화 측면에서 우수합니다.src/main/java/org/ezcode/codetest/application/game/dto/request/encounter/RandomEncounterSaveRequest.java (2)
29-35: 인카운터 선택지 텍스트 필드 추가 승인새로운
choice1Text와choice2Text필드가 적절한 검증과 문서화와 함께 올바르게 추가되었습니다. 사용자 인터페이스에서 명확한 선택지 제공이 가능해집니다.
44-45: 빌더 패턴 업데이트 확인
toRandomEncounter()메서드에서 새로운 필드들이 올바르게 매핑되었습니다.src/main/java/org/ezcode/codetest/domain/game/model/encounter/RandomEncounter.java (2)
37-41: 엔티티 필드 추가 승인새로운
choice1Text와choice2Text필드가nullable = false제약조건과 함께 올바르게 추가되었습니다. 데이터 무결성이 보장됩니다.
51-59: 생성자 및 빌더 패턴 업데이트 확인새로운 필드들이 생성자와 빌더 패턴에 올바르게 포함되어 일관성이 유지되었습니다.
src/main/java/org/ezcode/codetest/domain/game/repository/MatchTokenBucketRepository.java (2)
7-13: 토큰 버킷 저장소 인터페이스 승인표준 저장소 패턴을 따르는 깔끔한 인터페이스입니다.
Optional반환 타입 사용과 메서드 시그니처가 적절합니다.
11-11: 동시성 처리 고려사항 확인 필요토큰 버킷의 특성상 동시 접근이 빈번할 수 있습니다. 구현체에서 적절한 동시성 제어(예: 비관적 락)가 적용되었는지 확인해주세요.
#!/bin/bash # 토큰 버킷 저장소 구현체에서 동시성 제어 확인 rg -A 10 "class.*MatchTokenBucketRepository.*Impl" --type java rg -A 5 "@Lock\|LockModeType\|pessimistic\|optimistic" --type javasrc/main/java/org/ezcode/codetest/application/game/dto/response/encounter/MatchingBattleResponse.java (2)
14-15: JWT 토큰 기반 적 ID 관리 승인
enemyId에서enemyIdToken으로 변경하여 JWT 토큰 기반 보안이 적용되었습니다. 이는 클라이언트가 직접 적 ID를 조작하여 무한 배틀을 시도하는 보안 문제를 해결합니다.
18-21: 정적 팩토리 메서드 업데이트 확인
of메서드가 새로운 토큰 매개변수를 올바르게 처리하도록 업데이트되었습니다.src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacter.java (4)
94-95: 포맷팅 개선 승인코드 일관성을 위한 포맷팅 변경입니다.
109-109: 메서드 시그니처 포맷팅 개선 승인매개변수 포맷팅이 일관성 있게 개선되었습니다.
105-107: 새로운loseGold메서드 추가가 적절합니다.골드 손실 로직이 명확하게 분리되어 가독성이 향상되었고,
Math.max를 사용하여 골드가 음수가 되지 않도록 보호하는 방어적 프로그래밍이 잘 적용되었습니다. 기존earnGold메서드와 일관성 있는 네이밍과 구조를 유지하고 있습니다.
109-109: 메서드 시그니처 포맷팅이 개선되었습니다.파라미터 간 공백이 일관되게 적용되어 코드 가독성이 향상되었습니다.
src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/WildBeastsEscape.java (5)
30-33: 지역변수 추출로 가독성 개선 승인
player변수 추출과speed,evasion변수명 명시로 코드 가독성이 향상되었습니다.
36-39: 스토리텔링 개선으로 사용자 경험 향상로그 메시지가 더 상세하고 몰입감 있게 개선되어 게임의 재미와 몰입도가 크게 향상되었습니다.
Also applies to: 45-49
52-55: 실패 시나리오 스토리텔링 개선 승인도망 실패 상황도 유머러스하고 생생하게 표현하여 부정적인 결과도 재미있게 받아들일 수 있도록 개선되었습니다.
30-31: 플레이어 이름을 위한 지역 변수 추가가 좋습니다.코드 가독성이 향상되고 문자열 포맷팅에서 일관성을 유지할 수 있게 되었습니다.
36-56: 인카운터 내러티브 개선으로 사용자 경험이 향상되었습니다.기존의 단순한 메시지에서 더욱 생생하고 몰입감 있는 스토리텔링으로 개선되었습니다. 성공과 실패 시나리오 모두 플레이어의 선택과 결과를 더 극적으로 표현하고 있어 게임의 재미를 높입니다.
src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/StatSpeed.java (3)
37-38: 스피드 증가 시나리오 스토리텔링 개선 승인현대적이고 친근한 표현('개쩌는데?')과 고대 군사 실험이라는 흥미로운 설정으로 사용자 경험이 크게 향상되었습니다.
41-43: 스피드 감소 시나리오 스토리텔링 개선 승인실패 상황을 유머러스하게 표현('망했네', '체험학습')하여 부정적인 결과도 재미있게 받아들일 수 있도록 개선되었습니다.
37-44: 인카운터 내러티브의 일관된 개선입니다.다른 인카운터 전략과 마찬가지로 더욱 상세하고 몰입감 있는 스토리텔링으로 개선되었습니다. 성공과 실패 시나리오 모두 유머러스하면서도 몰입감 있는 설명으로 플레이어 경험을 향상시킵니다.
src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java (4)
13-13: 토큰 버킷 시스템 의존성 추가 승인토큰 버킷 시스템 도입을 위한 의존성 추가가 적절하게 이루어졌습니다.
Also applies to: 21-21, 35-35
48-48: 아직@Transactional애노테이션이 적용된 위치를 찾지 못했습니다. 클래스 또는 메서드 레벨에 트랜잭션 경계가 제대로 설정되어 있는지 추가로 확인해 주세요.#!/bin/bash # CharacterStatusDomainService에 @Transactional import나 선언이 있는지 확인 rg "import .+Transactional" src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java rg -n "@Transactional" src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java
13-13: 토큰 버킷 시스템 통합을 위한 의존성 추가가 적절합니다.새로운
GameCharacterMatchTokenBucket엔티티와MatchTokenBucketRepository의존성이 올바르게 추가되었습니다.Also applies to: 21-21, 35-35
48-48: 캐릭터 생성 시 토큰 버킷 초기화가 적절하게 배치되었습니다.캐릭터와 인벤토리 생성 후 토큰 버킷을 생성하는 순서가 논리적이며, 캐릭터 생성 라이프사이클에 토큰 버킷 관리가 잘 통합되었습니다.
src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java (2)
32-34: 토큰 버킷 시스템 예외 코드 추가 승인토큰 버킷 시스템에 필요한 예외 코드들이 체계적으로 추가되었습니다. 특히 '6시간 이후 리필'이라는 구체적인 정보로 사용자 경험이 향상되었습니다.
32-34: 토큰 버킷 시스템을 위한 새로운 예외 코드들이 잘 정의되었습니다.새로 추가된 예외 코드들은 기존 패턴과 일관성을 유지하며, 명확하고 도움이 되는 오류 메시지를 제공합니다. 특히 토큰 소진 시 6시간 후 리필된다는 정보를 포함하여 사용자에게 명확한 가이드를 제공합니다. HTTP 상태 코드도 적절하게 설정되었습니다.
src/main/java/org/ezcode/codetest/domain/game/strategy/encounter/encounterstrategyimpl/WildBeastsAttack.java (6)
30-40: 스토리텔링 개선이 잘 구현되었습니다.인카운터의 몰입감을 높이는 상세하고 유머러스한 로그 메시지들이 추가되어 사용자 경험이 크게 향상될 것으로 보입니다. 특히 메타적 요소(
취준생의 무심한 마우스 클릭)를 포함한 위트 있는 표현이 인상적입니다.
34-34: 승리 확률 계산 로직 개선이 적절합니다.기존의 공격력만 고려하던 방식에서 공격력과 정확도의 평균을 사용하도록 변경한 것은 게임 밸런스 측면에서 더 합리적입니다.
Math.min을 통해 100%를 초과하지 않도록 제한한 것도 좋습니다.
46-57: 승리/패배 시나리오의 상세한 묘사가 우수합니다.각 결과에 대한 생생하고 구체적인 묘사가 게임의 몰입도를 크게 높일 것으로 예상됩니다. 특히 패배 시나리오의 유머러스한 표현(
사료 광고를 믿지 않겠다고 다짐)이 게임의 톤을 잘 살렸습니다.
30-34: 승리 확률 계산 로직 개선이 우수합니다.공격력만 사용하던 기존 방식에서 공격력과 정확도의 평균을 사용하는 방식으로 변경하여 더욱 균형잡힌 게임플레이를 제공합니다.
36-40: 몰입감 있는 내러티브 추가가 훌륭합니다.게임 경험을 향상시키는 유머러스하고 상세한 로그 메시지들이 추가되어 플레이어의 몰입도를 높입니다.
46-49: 승리/패배 결과 내러티브가 잘 구성되었습니다.각 결과에 대한 생생한 묘사와 스탯 변경에 대한 설명이 게임 경험을 풍부하게 만듭니다.
Also applies to: 53-57
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketJpaRepository.java (3)
13-14: 비관적 쓰기 락 사용이 적절합니다.토큰 버킷에서 토큰을 소비하는 작업에서 동시성 이슈를 방지하기 위해
PESSIMISTIC_WRITE락을 사용한 것은 올바른 접근입니다. 이를 통해 동시에 여러 요청이 들어와도 토큰이 정확히 관리될 수 있습니다.
13-14: 비관적 잠금(Pessimistic Write Lock) 사용이 적절합니다.토큰 소비 시 경쟁 상태(race condition)를 방지하기 위해 비관적 쓰기 잠금을 사용한 것은 토큰 버킷 시스템에서 매우 중요한 설계입니다.
11-16: JPA Repository 인터페이스 설계가 우수합니다.Spring Data JPA 관례를 잘 따르고 있으며, 필요한 기능만 간결하게 정의되어 있습니다.
src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/MatchingEncounterResponse.java (6)
13-14: JWT 토큰 기반 ID 시스템으로의 전환이 보안상 우수합니다.원시 Long ID 대신 JWT 토큰을 사용하는 것은 클라이언트가 임의의 ID로 API를 남용하는 것을 방지하는 효과적인 보안 조치입니다. 스키마 설명도 적절히 업데이트되었습니다.
22-26: 인카운터 선택지 텍스트 추가가 적절합니다.클라이언트에서 선택지 텍스트를 직접 표시할 수 있도록
choice1Text와choice2Text필드를 추가한 것은 UI/UX 개선에 도움이 될 것입니다.
32-41: Factory 메서드 업데이트가 잘 구현되었습니다.
encounterIdToken파라미터를 추가하고 새로운 choice 텍스트 필드들을 매핑하는 로직이 올바르게 구현되었습니다.
13-14: JWT 토큰 기반 ID 사용으로 보안이 강화되었습니다.원시 ID 대신 JWT 토큰을 사용하여 클라이언트가 직접 ID를 조작하는 것을 방지할 수 있습니다.
22-26: 선택지 텍스트 필드 추가가 UX 개선에 도움됩니다.인카운터의 선택지를 명시적으로 표시하여 사용자 경험을 향상시킵니다.
32-42: 팩토리 메서드 업데이트가 일관성 있게 구현되었습니다.JWT 토큰 매개변수와 새로운 선택지 텍스트 필드를 올바르게 처리하고 있습니다.
src/main/java/org/ezcode/codetest/common/security/util/JwtUtil.java (5)
43-43: 메서드 이름 변경이 명확성을 향상시켰습니다.
createToken에서createAccessToken으로 변경하여 액세스 토큰과 게임 토큰을 명확히 구분한 것은 좋은 리팩터링입니다.
64-78: 게임 토큰 생성 메서드가 잘 구현되었습니다.게임 이벤트를 위한 단순하고 안전한 토큰 생성 로직입니다. 추가 클레임 없이 eventId만 subject로 사용하는 것이 적절합니다. null 체크도 적절히 구현되었습니다.
26-26: 게임 토큰의 짧은 만료 시간(60초)이 보안상 적절합니다.게임 이벤트의 일시적 특성을 고려한 적절한 만료 시간 설정입니다.
43-43: 메서드명 변경으로 의도가 명확해졌습니다.
createToken에서createAccessToken으로 변경하여 액세스 토큰과 게임 토큰을 명확히 구분합니다.
64-78: 게임 토큰 생성 로직이 적절하게 구현되었습니다.최소한의 클레임만 포함하고 짧은 만료 시간을 설정하여 보안성과 성능을 모두 고려한 설계입니다.
src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacterMatchTokenBucket.java (1)
52-84: 동시성 처리 확인 필요토큰 소비 로직이 동시에 여러 요청에서 호출될 수 있습니다. Repository 레벨에서 pessimistic locking을 사용하고 있는지 확인이 필요합니다.
#!/bin/bash # Description: MatchTokenBucketRepository 구현체에서 pessimistic locking 사용 여부 확인 # repository 구현체에서 PESSIMISTIC_WRITE 사용 확인 rg -A 10 "MatchTokenBucketRepository" --type java rg -A 10 "PESSIMISTIC_WRITE|LockModeType" --type javasrc/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java (2)
203-211: JWT 토큰 기반 배틀 API로 적절히 변경됨Path variable 대신 JWT 토큰을 포함한 request body를 받도록 변경된 것이 보안상 좋은 개선입니다.
252-260: 인카운터 선택 API의 보안 개선JWT 토큰을 사용하여 인카운터 ID 노출을 방지한 것이 좋은 보안 개선입니다.
src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java (3)
183-206: JWT 토큰 기반 매칭 시스템 구현 우수랜덤 매칭 결과를 JWT 토큰으로 감싸서 반환하는 방식이 PK 노출을 방지하는 좋은 보안 개선입니다.
141-145: JWT 토큰 검증 강화 필요JWT 토큰에서 claims를 추출하기 전에 토큰의 유효성과 만료 시간을 검증해야 합니다. PR 설명에서 1분 만료 시간을 언급했는데, 이에 대한 검증이 필요합니다.
#!/bin/bash # Description: JwtUtil의 토큰 검증 로직 확인 # JwtUtil 클래스에서 토큰 검증 메서드 확인 ast-grep --pattern 'class JwtUtil { $$$ }' # extractClaims 메서드 구현 확인 rg -A 10 "extractClaims" --type java
163-180: 사용되지 않는 메서드 제거 필요
randomBattle메서드는 더 이상 컨트롤러에서 호출되지 않는 것으로 보입니다. 사용하지 않는 코드는 제거하는 것이 좋겠습니다.#!/bin/bash # Description: randomBattle 메서드 사용 여부 확인 # randomBattle 메서드 호출 검색 rg "randomBattle" --type javasrc/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketRepositoryImpl.java (2)
11-27: 깔끔한 Repository 구현체입니다.도메인 레포지토리 인터페이스와 JPA 구현체를 적절히 분리하여 클린 아키텍처를 유지하고 있습니다.
17-25: 위임 패턴을 올바르게 적용했습니다.JPA Repository에 대한 위임을 통해 도메인과 인프라스트럭처 계층을 적절히 분리했습니다.
작업 내용
해결해야 할 문제
참고 사항
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit
신규 기능
기능 개선
버그 수정
기타