Skip to content

Conversation

@chat26666
Copy link
Collaborator

@chat26666 chat26666 commented Jun 21, 2025


작업 내용

image

  • 기존에 랜덤 인카운터나 적 플레이어 매칭시 raw pk가 클라이언트한테 반환되는 이슈가 있어서 pk 를 가지고 서버에 직접 api 를 던지면 무한으로 같은 인카운터를 선택하거나 같은 플레이어랑 무한으로 싸울 수 있는 문제점이 있었습니다. 현재는 pk 를 jwt 감싸서 반환하기 때문에(만료시간 1분) 해당 문제점이 해결되었습니다. 추가적으로 토큰 버킷이라는 엔티티를 추가하여 하루에 무한으로 배틀이나 랜덤 인카운터를 실행할 수 없게끔 조치하였습니다.

해결해야 할 문제

  • 지속적으로 성능개선 진행할 예정입니다.

참고 사항

  • 기타 공유하고 싶은 정보나 참고한 문서(링크 등)가 있다면 작성해주세요.

코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • 신규 기능

    • 전투 및 인카운터 매칭에 JWT 기반 토큰 시스템 도입으로 보안성이 강화되었습니다.
    • 전투 및 인카운터 매칭 토큰 버킷 기능이 추가되어 일정 시간마다 토큰이 리필됩니다.
    • 인카운터 선택지 텍스트가 추가되어 더욱 다양한 선택지가 제공됩니다.
  • 기능 개선

    • 전투 및 인카운터 관련 API가 경로 변수에서 요청 본문 방식으로 변경되어 사용성이 향상되었습니다.
    • 전투 및 인카운터 결과 응답에 선택지 및 토큰 정보가 포함되어 안내가 명확해졌습니다.
    • 골드 차감 및 보상 로직이 명확히 구분되어 결과가 직관적으로 표시됩니다.
    • 전투 및 인카운터 내 로그 메시지와 내러티브가 보다 풍부하고 자연스럽게 개선되었습니다.
  • 버그 수정

    • 일부 메시지 및 로그의 오타, 문장 구조가 자연스럽게 개선되었습니다.
  • 기타

    • 토큰 소진 및 버킷 미존재에 대한 에러 코드가 추가되어 예외 상황 안내가 강화되었습니다.

@chat26666 chat26666 self-assigned this Jun 21, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 21, 2025

"""

Walkthrough

이 변경사항은 게임 내 배틀 및 인카운터 매칭 시스템에 JWT 기반 토큰 버킷을 도입하고, 관련 API 및 도메인 로직을 대대적으로 리팩터링합니다. 주요 엔티티와 DTO, 서비스, 컨트롤러, 저장소 계층이 토큰 기반 인증 및 매칭으로 전환되었으며, 골드 손실 로직과 로그 메시지 등도 일부 개선되었습니다.

Changes

파일/경로 요약 변경 요약
.../BattleRequest.java 배틀 요청용 DTO(BattleRequest) 신설, JWT 토큰 필드 추가
.../EncounterChoiceRequest.java 인카운터 선택 요청에 encounterToken 필드 추가
.../RandomEncounterSaveRequest.java, .../RandomEncounter.java, .../EncounterResponse.java, .../MatchingEncounterResponse.java 인카운터 선택지(choice1Text, choice2Text) 필드 추가 및 관련 생성자/메서드 수정
.../MatchingBattleResponse.java enemyId(Long) → enemyIdToken(String)으로 변경, JWT 토큰 사용
.../GamePlayUseCase.java, .../GamePlayController.java 배틀 및 인카운터 관련 메서드/엔드포인트가 토큰 기반으로 리팩터링, 파라미터 및 반환값 변경
.../JwtUtil.java, .../AuthService.java, .../CustomSuccessHandler.java createToken → createAccessToken으로 메서드명 변경, createGameToken 신설(만료 60초), 토큰 생성 방식 분리
.../GameExceptionCode.java 토큰 소진 및 버킷 미존재 관련 예외코드 3종 추가
.../GameCharacter.java loseGold(long gold) 메서드 신설, 골드 감소 방식 명확화
.../GameCharacterMatchTokenBucket.java, .../MatchTokenBucketRepository.java, .../MatchTokenBucketJpaRepository.java, .../MatchTokenBucketRepositoryImpl.java 토큰 버킷 엔티티/저장소 신설, JPA 및 도메인 저장소 구현
.../CharacterStatusDomainService.java 캐릭터 생성 시 토큰 버킷도 생성/저장하도록 변경
.../GameEncounterDomainService.java 적 캐릭터/인카운터 매칭 시 토큰 소모 및 버킷 체크 추가, 골드 보상/패널티 로직 분기
.../encounterstrategyimpl/*.java 골드 감소 시 earnGold(-x) → loseGold(x)로 변경, 일부 로그 메시지 개선 및 내러티브 강화
.../EncounterLog.java 로그 메시지 구분자 개행 → 공백으로 변경
.../skillstrategyimpl/.java, .../skilldecorator/.java 일부 전투/스킬 로그 메시지 텍스트 개선

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: 결과 응답
Loading

Possibly related PRs

  • feat: 전투 시스템 추가 #67: 배틀 시스템의 초기 구현 및 배틀 히스토리 응답, 랜덤 인카운터 CRUD가 포함되어 있으며, 본 PR은 해당 시스템을 JWT 기반 토큰 매칭 방식으로 리팩터링함.

Suggested labels

enhancement

Suggested reviewers

  • minjee2758
  • NCookies
  • Kimminu7
  • pokerbearkr
  • thezz9

Poem

🐇

매칭 토큰 한 움큼, 골드도 쏙 빠져,
JWT 품은 전장 위, 토끼는 깡총 뛰네!
버킷 채워 다시 한 번, 모험은 계속된다,
로그도 한층 멋져져, 내러티브가 살아나네.

오늘도 깡총, 코드도 깡총!
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef35865 and 50364d5.

📒 Files selected for processing (2)
  • src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacterMatchTokenBucket.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketRepositoryImpl.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketRepositoryImpl.java
  • src/main/java/org/ezcode/codetest/domain/game/model/character/GameCharacterMatchTokenBucket.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@chat26666 chat26666 added the enhancement New feature or request label Jun 21, 2025
Copy link

@coderabbitai coderabbitai bot left a 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: 토큰 소비 순서 및 빈 리스트 처리 필요

  1. 토큰이 먼저 소비되어 실패 시에도 돌아오지 않습니다.
  2. 인카운터 목록이 비어있을 경우 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

📥 Commits

Reviewing files that changed from the base of the PR and between 58d8a20 and ef35865.

📒 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: 인카운터 선택지 텍스트 필드 추가

choice1Textchoice2Text 필드 추가로 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: 인카운터 선택지 텍스트 필드 추가 승인

새로운 choice1Textchoice2Text 필드가 적절한 검증과 문서화와 함께 올바르게 추가되었습니다. 사용자 인터페이스에서 명확한 선택지 제공이 가능해집니다.


44-45: 빌더 패턴 업데이트 확인

toRandomEncounter() 메서드에서 새로운 필드들이 올바르게 매핑되었습니다.

src/main/java/org/ezcode/codetest/domain/game/model/encounter/RandomEncounter.java (2)

37-41: 엔티티 필드 추가 승인

새로운 choice1Textchoice2Text 필드가 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 java
src/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: 인카운터 선택지 텍스트 추가가 적절합니다.

클라이언트에서 선택지 텍스트를 직접 표시할 수 있도록 choice1Textchoice2Text 필드를 추가한 것은 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 java
src/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 java
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/MatchTokenBucketRepositoryImpl.java (2)

11-27: 깔끔한 Repository 구현체입니다.

도메인 레포지토리 인터페이스와 JPA 구현체를 적절히 분리하여 클린 아키텍처를 유지하고 있습니다.


17-25: 위임 패턴을 올바르게 적용했습니다.

JPA Repository에 대한 위임을 통해 도메인과 인프라스트럭처 계층을 적절히 분리했습니다.

@pokerbearkr pokerbearkr merged commit db550fc into dev Jun 21, 2025
2 checks passed
@pokerbearkr pokerbearkr deleted the feature/game branch June 21, 2025 15:02
@coderabbitai coderabbitai bot mentioned this pull request Jun 21, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants