-
Notifications
You must be signed in to change notification settings - Fork 3
feat : 방어 전투 로그 조회할 수 있는 기능 추가, 성능 개선 #90
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
|
Caution Review failedThe pull request is closed. Walkthrough방어전(Defence) 전투 기록을 조회하는 기능이 새롭게 추가되었습니다. 이를 위해 백엔드에 방어전 기록 API 엔드포인트가 신설되고, 관련 DTO, 도메인 서비스, 캐시, 리포지토리 계층이 확장되었습니다. 프론트엔드에서는 "DEFENCE LOG" 버튼과 방어전 기록 조회/표시 기능이 배틀 패널에 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자(클라이언트)
participant Front as 프론트엔드(game-page.html)
participant Controller as GamePlayController
participant UseCase as GamePlayUseCase
participant Domain as GameEncounterDomainService
participant Repo as BattleHistoryRepository
User->>Front: "DEFENCE LOG" 버튼 클릭
Front->>Controller: GET /api/games/characters/battles (인증)
Controller->>UseCase: getPlayerDefenceHistory(userId)
UseCase->>Domain: getCharacterBattleHistory(player)
Domain->>Repo: findCreatedInLast24Hours(playerId)
Repo-->>Domain: 최근 24시간 방어전 기록 반환
Domain-->>UseCase: BattleHistory 리스트 반환
UseCase-->>Controller: DefenceBattleHistoryResponse 리스트 반환
Controller-->>Front: HTTP 200 + 방어전 기록 리스트
Front-->>User: 방어전 기록 UI 표시
Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (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: 2
🧹 Nitpick comments (9)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/BattleHistoryRepositoryImpl.java (1)
63-63: 캐시 무효화 전략을 고려하세요.현재 캐시 키로
playerId만 사용하고 있어서 새로운 전투 기록이 생성되어도 캐시가 자동 갱신되지 않습니다. 캐시 만료 시간을 짧게 설정하거나@CacheEvict를 통한 캐시 무효화 전략을 추가로 고려해보세요.src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java (1)
221-221: API 경로를 더 명확하게 구분하세요.현재 같은 경로(
/api/games/characters/battles)에 POST(전투 실행)와 GET(방어 기록 조회) 엔드포인트가 있습니다. HTTP 메서드로 구분되지만, RESTful 설계 관점에서 더 명확한 경로를 사용하는 것을 권장합니다.- @GetMapping("/characters/battles") + @GetMapping("/characters/battles/defence-history")또는
- @GetMapping("/characters/battles") + @GetMapping("/characters/defence-battles")src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java (1)
208-208: 읽기 전용 트랜잭션을 사용하여 성능을 최적화하세요.현재 메서드는 데이터 조회만 수행하므로 읽기 전용 트랜잭션을 사용하면 성능상 이점을 얻을 수 있습니다.
- @Transactional + @Transactional(readOnly = true)src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/DefenceBattleHistoryResponse.java (2)
18-18: 필드명 네이밍 컨벤션 수정이 필요합니다.
PlayerNickName은 camelCase 규칙에 따라playerNickName으로 수정해야 합니다.- String PlayerNickName, + String playerNickName,
33-33: 필드명 일관성 확인이 필요합니다.위에서 제안한 필드명 수정에 따라 이 부분도 함께 수정되어야 합니다.
- .PlayerNickName(history.getDefender().getName()) + .playerNickName(history.getDefender().getName())src/main/resources/templates/game-page.html (3)
389-458: 방어 로그 기능 구현이 포괄적이고 사용자 친화적입니다.API 호출, 에러 처리, 동적 HTML 생성, 이벤트 바인딩까지 모든 요소가 잘 구현되었습니다. 특히 다음 점들이 우수합니다:
- 적절한 에러 핸들링
- 뒤로 가기 기능 제공
- 토글 가능한 상세 로그 표시
- 승패에 따른 색상 구분
다만 JavaScript 코드가 길어져 별도 함수로 분리하는 것을 고려해보세요.
424-424: 필드명 불일치 수정이 필요합니다.DTO에서
PlayerNickName을playerNickName으로 수정한다면, 여기서도 일치시켜야 합니다.- • ${item.attackerNickName} vs ${item.PlayerNickName} + • ${item.attackerNickName} vs ${item.playerNickName}
396-399: 에러 처리 로직 개선을 제안합니다.현재는
data.success가 false일 때만 에러 처리를 하고 있는데, HTTP 상태 코드나 네트워크 오류도 함께 처리하면 더 견고한 코드가 될 것입니다.+ if (!res.ok) { + panel.innerHTML = `<p style="color:#f00;">Network error: ${res.status}</p>`; + return; + } const data = await res.json(); if (!data.success) { panel.innerHTML = `<p style="color:#f00;">Failed to load defence log.</p>`; return; }src/main/java/org/ezcode/codetest/infrastructure/cache/config/CaffeineCacheConfig.java (1)
52-53: 캐시 목록 업데이트가 정확합니다.새로 추가된 두 캐시가 캐시 매니저에 올바르게 등록되었습니다. 향후 캐시 성능 메트릭 모니터링을 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/DefenceBattleHistoryResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java(3 hunks)src/main/java/org/ezcode/codetest/domain/game/model/character/CharacterRealStat.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/BattleHistoryRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java(9 hunks)src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/LifeStealSkill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/util/StatUpdateUtil.java(0 hunks)src/main/java/org/ezcode/codetest/infrastructure/cache/config/CaffeineCacheConfig.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/event/config/CustomHandShakeHandler.java(0 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/GameCharacterRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/BattleHistoryJpaRepository.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/BattleHistoryRepositoryImpl.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/EncounterChoiceRepositoryImpl.java(2 hunks)src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java(2 hunks)src/main/resources/templates/game-page.html(2 hunks)
💤 Files with no reviewable changes (2)
- src/main/java/org/ezcode/codetest/infrastructure/event/config/CustomHandShakeHandler.java
- src/main/java/org/ezcode/codetest/domain/game/util/StatUpdateUtil.java
🧰 Additional context used
🧠 Learnings (1)
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/EncounterChoiceRepositoryImpl.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 (26)
src/main/java/org/ezcode/codetest/infrastructure/cache/config/CaffeineCacheConfig.java (5)
26-29: 새로운 histories 캐시 설정이 적절합니다.방어전 기록 조회 기능을 위한 캐시 설정이 올바르게 구성되었습니다. 1분 TTL은 전투 기록의 특성상 적절한 설정입니다.
46-49: choices 캐시 설정이 기존 패턴과 일관성을 유지합니다.10분 TTL은 다른 게임 데이터 캐시들과 동일한 설정으로 일관성이 있습니다.
52-53: 캐시 목록에 새로운 캐시들이 올바르게 추가되었습니다.historyCache와 choiceCache가 적절하게 캐시 관리자에 등록되었습니다.
26-29: 새로운 캐시 설정이 적절하게 추가되었습니다.방어 전투 기록 조회를 위한 "histories" 캐시가 1분 만료로 설정되어 실시간성과 성능의 균형을 잘 맞췄습니다.
46-49: 선택지 캐시 설정이 합리적입니다."choices" 캐시의 10분 만료 설정은 다른 게임 데이터 캐시들과 일관성을 유지하고 있습니다.
src/main/java/org/ezcode/codetest/domain/game/strategy/skill/skillstrategyimpl/LifeStealSkill.java (2)
42-42: 한국어 텍스트 개선이 자연스럽습니다."머리를 잃었습니다"에서 "정신을 잃었습니다"로 변경하고 조사 "(이)가"를 추가한 것이 더 자연스러운 한국어 표현입니다. 스턴 효과를 설명하는 데 적절한 표현입니다.
42-42: 한국어 표현이 더 자연스럽게 개선되었습니다."머리를 잃었습니다"에서 "정신을 잃었습니다"로 변경하여 스턴 상태를 더 적절하게 표현하고 있습니다.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/character/GameCharacterRepositoryImpl.java (2)
34-34: 엣지 케이스 처리가 개선되었습니다.캐릭터가 1명만 있을 때도 빈 Optional을 반환하도록 수정한 것이 논리적으로 올바릅니다. 단 하나의 캐릭터만 존재할 때 다른 랜덤 캐릭터를 찾으려는 시도는 불필요한 연산이므로 이 변경이 적절합니다.
34-34: 논리적 엣지 케이스 처리가 개선되었습니다.캐릭터가 1명만 존재할 때 불필요한 반복문 실행을 방지하여 성능을 개선하고 논리적 정확성을 향상시켰습니다.
src/main/java/org/ezcode/codetest/domain/game/repository/BattleHistoryRepository.java (2)
24-24: 새로운 리포지토리 메서드가 적절하게 추가되었습니다.
findCreatedInLast24Hours메서드명이 명확하고 기존 리포지토리 패턴과 일관성을 유지합니다. 방어전 기록 조회 기능을 위한 적절한 인터페이스 설계입니다.
24-24: 방어 전투 기록 조회를 위한 메서드가 적절하게 추가되었습니다.메서드명이 기능을 명확히 표현하며, 24시간 범위 제한으로 성능과 실용성의 균형을 잘 맞췄습니다.
src/main/java/org/ezcode/codetest/domain/game/model/character/CharacterRealStat.java (4)
89-89: 게임 밸런스 변경 사항을 검증해주세요.정확도(accuracy) 스탯 증가율을
rate / 10에서rate / 5로 2배 증가시킨 변경이 게임 밸런스에 미치는 영향을 확인해야 합니다. DATA_STRUCTURE, SPEED, OPTIMIZATION 스탯의 정확도 기여도가 크게 향상되어 전투 시스템에 상당한 영향을 줄 수 있습니다.이 변경이 의도된 밸런스 조정인지, 그리고 다른 스탯들과의 균형이 적절한지 테스트 또는 시뮬레이션을 통해 검증하는 것을 권장합니다.
Also applies to: 94-94, 104-104
89-89: DATA_STRUCTURE 스탯의 정확도 증가율이 개선되었습니다.정확도 증가율을 rate/10에서 rate/5로 조정하여 해당 스탯의 효용성을 높였습니다.
92-94: SPEED 스탯의 증가율 밸런스가 조정되었습니다.속도와 정확도 증가율을 모두 향상시켜 SPEED 스탯의 가치를 높였습니다. 게임 밸런스에 미치는 영향을 테스트해보시기 바랍니다.
104-104: OPTIMIZATION 스탯의 정확도 증가율이 강화되었습니다.다른 스탯들과 일관성 있게 정확도 증가율을 개선하여 스탯 시스템의 균형을 맞췄습니다.
src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java (1)
213-227: API 구현이 잘 설계되었습니다.인증 처리, OpenAPI 문서화, 응답 메시지 처리가 모두 적절하게 구현되어 있습니다. 기존 패턴과 일관성을 유지하고 있어 좋습니다.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/BattleHistoryJpaRepository.java (1)
18-20: EntityGraph를 활용한 효율적인 쿼리 설계입니다.
@EntityGraph를 사용하여 연관 엔티티(attacker,defender)를 즉시 로딩하도록 설정한 것은 N+1 쿼리 문제를 방지하는 좋은 방법입니다. 메서드명도 Spring Data JPA 컨벤션을 잘 따르고 있습니다.src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java (1)
209-216: 깔끔하고 일관성 있는 구현입니다.도메인 서비스를 통해 데이터를 조회하고 DTO로 변환하는 방식이 기존 패턴과 일관성을 유지하고 있습니다. 코드 가독성도 좋습니다.
src/main/java/org/ezcode/codetest/domain/game/service/GameEncounterDomainService.java (6)
43-43: 코드 포맷팅 개선이 잘 되었습니다.불필요한 공백 제거로 가독성이 향상되었습니다.
68-68: 캐스팅 스타일 일관성 개선이 좋습니다.
(WeaponType)item.getItemType()형태로 일관되게 수정되어 코드 스타일이 통일되었습니다.Also applies to: 74-74
109-109: 전투 로그 메시지 개선이 훌륭합니다.정적 문자열에서 캐릭터 이름을 포함한 동적 메시지로 변경되어 로그의 유용성이 크게 향상되었습니다. 사용자 경험 개선에 도움이 될 것입니다.
Also applies to: 113-115, 133-133, 137-139
112-112: 골드 전송 로직 추가가 적절합니다.플레이어가 골드를 잃을 때 상대방이 해당 골드를 얻도록 하여 전투의 경제적 균형을 맞춘 것이 좋습니다.
Also applies to: 136-136
147-147: 무승부 메시지 정리가 적절합니다.감탄사 제거로 더 중립적이고 전문적인 메시지가 되었습니다.
242-245: 새로운 메서드 구현이 적절합니다.24시간 내 전투 기록을 조회하는 기능이 잘 구현되었고, 캐시 적용도 고려된 것으로 보입니다. 메서드명과 기능이 명확하게 일치합니다.
src/main/java/org/ezcode/codetest/application/game/dto/response/encounter/DefenceBattleHistoryResponse.java (1)
30-38: 팩토리 메서드 구현이 정확합니다.도메인 모델에서 DTO로의 변환 로직이 올바르게 구현되었고,
isAttackerWin을 반전시켜isDefenderWin으로 매핑하는 것이 방어자 관점에서 적절합니다.src/main/resources/templates/game-page.html (1)
383-384: DEFENCE LOG 버튼 추가가 잘 구현되었습니다.기존 BATTLE MATCHING 버튼과 일관된 스타일로 새로운 기능 버튼이 추가되어 UI 일관성이 유지되었습니다.
| } | ||
|
|
||
| @Override | ||
| @Cacheable(value = "choices", key = "#encounterId + '-' + #playerDecision") |
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.
🛠️ Refactor suggestion
캐시 키 생성 방식을 개선하세요.
현재 문자열 연결 방식("#encounterId + '-' + #playerDecision")은 잠재적인 키 충돌을 일으킬 수 있습니다. SpEL의 컬렉션 구문을 사용하여 더 안전한 키를 생성하는 것을 권장합니다.
- @Cacheable(value = "choices", key = "#encounterId + '-' + #playerDecision")
+ @Cacheable(value = "choices", key = "{#encounterId, #playerDecision}")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Cacheable(value = "choices", key = "#encounterId + '-' + #playerDecision") | |
| @Cacheable(value = "choices", key = "{#encounterId, #playerDecision}") |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/EncounterChoiceRepositoryImpl.java
at line 38, the cache key is currently generated by concatenating strings, which
can cause key collisions. Replace the string concatenation with a SpEL
collection syntax like "key = {#encounterId, #playerDecision}" to create a
safer, composite cache key.
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.
@Cacheable(value = "choices", key = "#encounterId + '-' + #playerDecision")
- @Cacheable(value = "choices", key = "{#encounterId, #playerDecision}") 이거 두개 차이가 뭔데 ?
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.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
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.
@coderabbitai 둘차이가 머냐고
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.
@chat26666 두 방식의 주요 차이점을 설명드리겠습니다:
1. 문자열 연결 방식 (현재)
@Cacheable(value = "choices", key = "#encounterId + '-' + #playerDecision")encounterId와playerDecision을 문자열로 변환해서-로 연결- 예시:
encounterId=123, playerDecision=true→ 캐시키:"123-true"
2. SpEL 컬렉션 구문 (권장)
@Cacheable(value = "choices", key = "{#encounterId, #playerDecision}")- 두 값을 배열 형태로 묶어서 구조화된 복합 키 생성
- 예시:
encounterId=123, playerDecision=true→ 캐시키:[123, true]
주요 차이점
1. 키 충돌 위험성
- 문자열 연결: 잠재적 충돌 가능
encounterId=12, playerDecision=true→"12-true"encounterId=1, playerDecision="2-true"→"1-2-true"(만약 boolean이 아닌 다른 타입이라면)
- 컬렉션 구문: 충돌 위험 없음 (각 요소가 독립적으로 처리됨)
2. 타입 안전성
- 문자열 연결: 모든 값이 문자열로 변환됨
- 컬렉션 구문: 각 요소의 원본 타입 유지
3. 성능
- 문자열 연결: 문자열 생성/연결 오버헤드
- 컬렉션 구문: 더 효율적인 해시 계산
컬렉션 구문 {#encounterId, #playerDecision}이 더 안전하고 권장되는 방식입니다! 🐰
/| /|
( :v: )
|(_)|
🧠 Learnings used
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.
| return battleHistoryRepository.findByDefenderIdAndCreatedAtAfterOrderByCreatedAtDesc(playerId, | ||
| LocalDateTime.now().minusDays(1)); |
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.
🛠️ Refactor suggestion
시간대 처리를 명시적으로 관리하세요.
LocalDateTime.now()는 시스템 시간대에 의존하므로 다국가 서비스에서 예상치 못한 결과를 초래할 수 있습니다. UTC 기준으로 시간을 처리하거나 애플리케이션의 표준 시간대를 명시적으로 사용하는 것을 권장합니다.
- return battleHistoryRepository.findByDefenderIdAndCreatedAtAfterOrderByCreatedAtDesc(playerId,
- LocalDateTime.now().minusDays(1));
+ return battleHistoryRepository.findByDefenderIdAndCreatedAtAfterOrderByCreatedAtDesc(playerId,
+ LocalDateTime.now(ZoneOffset.UTC).minusDays(1));추가로 java.time.ZoneOffset import가 필요합니다.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/mysql/encounter/BattleHistoryRepositoryImpl.java
around lines 66 to 67, replace LocalDateTime.now() with
LocalDateTime.now(ZoneOffset.UTC) to explicitly use UTC timezone instead of the
system default. This ensures consistent time handling across different regions.
Also, add the necessary import for java.time.ZoneOffset at the top of the file.
thezz9
left a comment
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.
LOL 👍
작업 내용
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit
신규 기능
버그 수정
성능 개선
UI/UX
기타