-
Notifications
You must be signed in to change notification settings - Fork 3
feature : 스킬 추가, 스킬 뽑기, 캐릭터 스킬 장착, 스텟창 확인 업데이트 #60
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게임 도메인에 스킬 관리 기능이 대대적으로 추가되었습니다. 기존 아이템 관련 도메인, DTO, 서비스, 컨트롤러 전반에 걸쳐 스킬 생성, 삭제, 장착, 뽑기(갬블링) 등 스킬 관련 로직이 통합되었습니다. 아이템의 grade 타입이 enum으로 변경되고, 무기/방어구/액세서리/스킬 관련 enum 및 엔티티 구조가 재정비되었습니다. 엔티티, 레포지토리, 서비스, 컨트롤러 계층에서 스킬과 관련된 신규 메서드와 API가 추가되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant GamePlayController
participant GamePlayUseCase
participant CharacterStatusDomainService
participant GameShopDomainService
participant SkillRepository
participant GameCharacterSkillRepository
User->>GamePlayController: POST /api/games/skills/gambling
GamePlayController->>GamePlayUseCase: gamblingForSkill(userId)
GamePlayUseCase->>GameShopDomainService: gamblingNewSkill(character)
GameShopDomainService->>SkillRepository: findAll()
GameShopDomainService->>GameCharacterSkillRepository: findByCharacterId(characterId)
alt 이미 보유한 스킬
GameShopDomainService-->>GamePlayUseCase: 기존 스킬 반환, 골드 환급
else 신규 스킬 획득
GameShopDomainService->>GameCharacterSkillRepository: save(GameCharacterSkill)
GameShopDomainService-->>GamePlayUseCase: 신규 스킬 반환
end
GamePlayUseCase->>GamePlayController: SkillGamblingResponse 반환
GamePlayController-->>User: SkillGamblingResponse 응답
sequenceDiagram
participant User
participant GamePlayController
participant GamePlayUseCase
participant CharacterStatusDomainService
participant SkillRepository
participant GameCharacterSkillRepository
User->>GamePlayController: PATCH /api/games/skills/equip
GamePlayController->>GamePlayUseCase: equipSkill(userId, skillName)
GamePlayUseCase->>CharacterStatusDomainService: equipNewSkill(character, skillName)
CharacterStatusDomainService->>SkillRepository: findByName(skillName)
CharacterStatusDomainService->>GameCharacterSkillRepository: findByCharacterId(characterId)
alt 장착 조건 체크
CharacterStatusDomainService-->>GamePlayUseCase: 예외 발생 or 성공
end
GamePlayUseCase->>GamePlayController: void
GamePlayController-->>User: 200 OK
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
""" 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (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: 12
🔭 Outside diff range comments (1)
src/main/java/org/ezcode/codetest/application/game/dto/response/CharacterStatusResponse.java (1)
30-38: 🛠️ Refactor suggestion정적 팩토리에서도 불변성 유지
위의 지적을 반영하려면
from메서드에서도 리스트를 불변으로 변환해야 합니다.- .items(items) - .skills(skills) + .items(Collections.unmodifiableList(items)) + .skills(Collections.unmodifiableList(skills))
🧹 Nitpick comments (34)
src/main/java/org/ezcode/codetest/application/game/dto/request/SkillDeleteRequest.java (1)
5-9: Swagger / SpringDoc 메타데이터 부재다른 DTO에서는
@Schema등으로 API 문서를 보강한 경우가 있었는데, 본 DTO에는 누락됐습니다.
컨트롤러 단에서 자동 문서화를 사용 중이라면 동일한 메타데이터를 추가해 주시면 일관성이 좋아집니다.src/main/java/org/ezcode/codetest/domain/game/model/enums/Grade.java (1)
8-13: 필드명grade→label등이 가독성에 더 적합
enum Grade { …; private final String grade; }는 의미가 중복되어 혼란을 줄 수 있습니다.
private final String label같이 의미를 분리하면 읽기-쉬워집니다.
또한 직렬화/역직렬화 시 한글 라벨을 그대로 노출할지 결정해야 합니다.
@JsonValue또는@JsonFormat(shape = ...)을 고려해 주세요.src/main/java/org/ezcode/codetest/domain/game/model/enums/SkillSlotType.java (1)
3-6: 상수 가독성 개선 제안상수를 한 줄에 나열하면 변경‧추가 시 diff 가 커지고, 가독성이 떨어집니다. 줄바꿈하여 정렬하면 유지보수가 수월합니다.
-public enum SkillSlotType { - EQUIPPED, BACKPACK +public enum SkillSlotType { + EQUIPPED, + BACKPACK }src/main/java/org/ezcode/codetest/presentation/chattingmanagement/chatting/controller/ChatRoomController.java (1)
22-25: 경로/api/chatrooms채택 – 레거시 호출 호환성 주의기존
/chatrooms경로를 소비하던 클라이언트/배치 스크립트가 있다면 4xx 응답으로 실패할 수 있으니 릴리스 노트에 반드시 포함해 주세요.src/main/java/org/ezcode/codetest/application/game/dto/request/SkillEquipRequest.java (1)
5-10: 필드 길이·형식 검증 추가 권장
@NotBlank만으로는 과도하게 긴 문자열이나 금지 문자가 포함된 입력을 막지 못합니다. 추후 DB / 로그 저장 시 문제를 예방하려면 최소/최대 길이나 허용 문자 집합을 제한하는@Size,@Pattern을 함께 적용하는 것을 권장드립니다.@NotBlank(message = "장착할 스킬 이름을 입력해주십시오.") + @Size(max = 50, message = "스킬 이름은 50자 이내여야 합니다.") String namesrc/main/java/org/ezcode/codetest/domain/game/model/enums/AccessoryType.java (1)
5-5: 열거형 네이밍 일관성(NIT)
GRAPHIC_CARD→ 일반적으로는GRAPHICS_CARD,USB와 같은 약어는 다른 상수들과 달리 복수·단수 혼재가 있습니다. 도메인 모델이 UI 문구로 직접 노출된다면 사용성을 위해 철자 및 복수형을 재검토해 보시는 것도 좋겠습니다.src/main/java/org/ezcode/codetest/application/game/dto/request/ItemDeleteRequest.java (1)
5-10: 입력 검증 강화 제안아이템 삭제는 파괴적 작업이므로, 공백 외에도 길이·형식 검증을 추가해 SQL 와일드카드, 특수문자 등에 의한 오동작을 방지하세요.
@NotBlank(message = "삭제하려는 아이템 이름을 입력해주세요.") + @Size(max = 50) + @Pattern(regexp = "^[A-Za-z0-9가-힣 _-]+$", message = "아이템 이름은 특수문자를 포함할 수 없습니다.") String namesrc/main/java/org/ezcode/codetest/domain/game/model/enums/SkillEffect.java (1)
5-5: 상수 정렬 및 스펠링 일관성가독성을 위해 알파벳 순으로 정렬하거나 효과 카테고리별로 그룹핑해 두면 유지보수가 용이합니다. 또한
DEFENCE(영국식) ↔ 기존 코드 내DEFENSE여부를 확인해 일관성을 맞추세요.src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemRepositoryImpl.java (1)
37-41: deleteByName 반환값 처리 제안현재
void deleteByName(String name)는 삭제 성공 여부를 상위 계층에 전달할 방법이 없습니다.
Spring Data MongoDB의deleteByName가 삭제 건수를long으로 반환하도록 정의되어 있다면, 그 값을 반환하거나 예외 처리로 명확히 전달하는 편이 이후 로직(예: 관리자 화면 피드백)에 유용합니다.- public void deleteByName(String name) { - itemRepository.deleteByName(name); + public long deleteByName(String name) { + return itemRepository.deleteByName(name); }src/main/java/org/ezcode/codetest/application/game/dto/response/SkillGamblingResponse.java (1)
10-13: 하드코딩된 메시지 상수화 권장축하 문구가 메서드 내부에 하드코딩되어 있어 i18n·재사용이 어렵습니다.
DTO 내부 혹은 별도의MessageConstants클래스로 분리하면 다국어 지원과 테스트가 용이해집니다.- return new SkillGamblingResponse(response, "축하합니다! 뽑기에 성공하셨습니다.(중복스킬은 자동으로 골드로 환전됩니다)"); + return new SkillGamblingResponse( + response, + MessageConstants.SKILL_GAMBLING_SUCCESS + );src/main/java/org/ezcode/codetest/domain/game/model/entity/Weapon.java (1)
26-27: Null 방어 필요
grade가 필수 값이라면 Lombok의@NonNull또는Objects.requireNonNull체크를 추가해 두세요.
엔티티 생성 시 null 전달로 인한 NPE를 조기에 방지할 수 있습니다.src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java (1)
16-20: 예외 메시지 오타
조회되지 없습니다.→조회되지 않습니다.가 자연스러운 표현입니다.
실제 사용자에게 노출되는 메시지라면 통일해 주세요.src/main/java/org/ezcode/codetest/application/game/dto/response/SkillResponse.java (1)
1-30: 직렬화 옵션 검토API 응답 DTO라면 불필요한 null 필드를 숨기기 위해
@JsonInclude(JsonInclude.Include.NON_NULL)추가를 고려하세요.+import com.fasterxml.jackson.annotation.JsonInclude; ... +@JsonInclude(JsonInclude.Include.NON_NULL) public record SkillResponse (src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillJpaRepository.java (1)
12-16: N+1 문제 예방
findByCharacterId메서드에도@EntityGraph(attributePaths = "skill")를 붙여 두면 일관적으로 N+1 문제를 방지할 수 있습니다.- List<GameCharacterSkill> findByCharacterId(Long characterId); + @EntityGraph(attributePaths = "skill") + List<GameCharacterSkill> findByCharacterId(Long characterId);src/main/java/org/ezcode/codetest/domain/game/model/entity/Skill.java (1)
20-23: 동일성 보장을 위한 equals/hashCode 구현 누락엔티티 간 비교나 컬렉션(Set, Map) 사용 시 식별자 기반의 동일성 보장이 없으면 예상치 못한 버그가 발생할 수 있습니다.
Lombok의@EqualsAndHashCode(onlyExplicitlyIncluded = true)등을 활용해id필드를 기준으로 구현해 두는 편이 안전합니다.@@ -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; @@ -@Getter -@Entity -@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Entity +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class Skill {src/main/java/org/ezcode/codetest/application/game/dto/request/DefenceSaveRequest.java (1)
58-60: 지역 변수 이름이 필드와 충돌
Grade grade = ...로 선언하여 클래스 필드명(grade)과 동일한 식별자를 재사용하고 있습니다.
컴파일에는 문제없지만 가독성이 떨어지므로 다른 이름(예:gradeEnum)을 권장합니다.- Grade grade = Grade.valueOf(getGrade().trim().toUpperCase()); + Grade gradeEnum = Grade.valueOf(getGrade().trim().toUpperCase());src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacterSkill.java (2)
61-64: 메서드명 카멜케이스 불일치자바 메서드는 소문자로 시작하는 카멜케이스가 일반적인 컨벤션입니다.
EquipSkill()→equipSkill()로 변경해 주세요.- public void EquipSkill() { + public void equipSkill() {
51-53:slotType컬럼 null 허용 여부 명시 필요
slotType은 비즈니스상 반드시 값이 존재해야 하는 필드로 보입니다.@Column(nullable = false)를 추가해 DB 레벨 제약을 명시하는 편이 안전합니다.- @Enumerated(EnumType.STRING) + @Column(nullable = false) + @Enumerated(EnumType.STRING) private SkillSlotType slotType;src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillRepositoryImpl.java (1)
12-17: 읽기 전용 트랜잭션 어노테이션 추가 검토레포지토리 구현체에서는 대부분의 메서드가 읽기 전용 작업(find 계열)입니다.
클래스 또는 각 메서드에@Transactional(readOnly = true)를 부여하면 JPA 1차 캐시/flush 비용을 줄일 수 있습니다.@Repository @RequiredArgsConstructor +@Transactional(readOnly = true) public class SkillRepositoryImpl implements SkillRepository {src/main/java/org/ezcode/codetest/domain/game/model/entity/CharacterRealStat.java (1)
28-38: 복사 생성자 동작은 문제 없으나Double필드의 불변성 주의각 필드를 얕은 복사만 수행하므로 현재로서는 안전하지만, 추후
Double→ 래퍼 객체가 아닌 Mutable 클래스로 변경될 경우 예기치 않은 공유 문제가 생길 수 있습니다. 필요 시 방어적 복사 또는Builder패턴 도입을 검토해 주세요.src/main/java/org/ezcode/codetest/application/game/dto/request/AccessorySaveRequest.java (1)
67-72: 지역 변수명 충돌(Naming Shadow) 정리 권장
Grade grade = ...로컬 변수명이 상위 필드명(getGrade())과 겹쳐 가독성이 떨어집니다.-Grade grade = Grade.valueOf(getGrade().trim().toUpperCase()); +Grade gradeEnum = Grade.valueOf(getGrade().trim().toUpperCase()); ... - .grade(grade) + .grade(gradeEnum)src/main/java/org/ezcode/codetest/domain/game/model/entity/Inventory.java (1)
53-59: 중복 조건식을 헬퍼로 추출하면 가독성이 더 좋아집니다.
addItem와cleanUpdateInventory모두 동일한instanceof + NOTHING 제외조건 로직을 반복합니다.
private 정적 메서드로 분리하면 이후 enum 값이 늘어나더라도 한 곳만 수정하면 됩니다.src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacter.java (1)
46-47:name컬럼에 제약 조건을 명시하는 것이 좋습니다닉네임은 null/blank 가 될 수 없으므로
@Column(nullable = false, length = …)정도를 붙여 두면 DB 스키마가 의도와 더 맞아집니다.src/main/java/org/ezcode/codetest/application/game/dto/request/WeaponSaveRequest.java (1)
21-25: 하드코딩된 정규식은 enum 변경 시 유지보수가 어렵습니다
WeaponType.values()를 이용한 커스텀@EnumPatternValidator 또는@Enum라이브러리를 쓰면 enum 추가/삭제 시 DTO 수정이 필요 없습니다.src/main/java/org/ezcode/codetest/application/game/dto/request/SkillSaveRequest.java (1)
14-18: 정규식 대신 공통 enum 검증기를 재사용하세요
WeaponSaveRequest와 동일한 이유로,SkillEffectenum 값이 바뀌면 DTO 정규식을 매번 손대야 합니다. 공통 Validator로 중복을 제거해 주세요.src/main/java/org/ezcode/codetest/application/game/dto/mapper/GameMapper.java (1)
40-44: MapStruct 다중 파라미터 매핑 시 Builder 생성 비용에 유의
CharacterStatusResponse매핑마다CharacterRealStat를 새로 인스턴스화합니다. 빈번히 호출된다면 캐싱 또는applyItemStatsToRealStat내부에서 불필요한 객체 생성을 최소화할 여지가 있습니다.src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillRepositoryImpl.java (1)
30-34: 메서드 이름 오타로 인한 가독성 저하
findByCharacterIdEAndEquipped의E는 오타로 보입니다. IDE 검색‧자동완성에 불리하며 유지보수성이 떨어집니다.
findEquippedSkillsByCharacterId등 의미가 명확한 이름으로 교체해 주세요.src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java (1)
92-98: 레포지토리 메서드 이름 일관성 검토
findByCharacterIdEAndEquipped호출부가 그대로 노출되어 있습니다.
앞서 리포지토리 구현에서도 지적한 오타이므로, 서비스 계층에서도 동일하게 수정하여 혼선을 방지하세요.src/main/java/org/ezcode/codetest/presentation/game/management/ItemManagementController.java (2)
33-39: DELETE 메서드에서 RequestBody 사용은 호환성이 떨어집니다많은 HTTP 클라이언트·캐시가
DELETE본문을 지원하지 않습니다.
리소스 식별자를 URI 경로로 노출하는 RESTful 방식이 일반적입니다.DELETE /api/games/items/{name}
@PathVariable로 변경을 고려해 주세요.
49-55: 스킬 삭제 엔드포인트도 동일한 개선 필요위 항목과 동일하게
DELETE /api/games/skills/{name}형태로 수정하면 일관성과 호환성이 향상됩니다.src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java (4)
43-48: 메서드 네이밍 규칙 불일치 (CharacterStatusOpen)Java 메서드 이름은 소문자로 시작하는 카멜 케이스가 컨벤션입니다.
characterStatusOpen으로 변경해 다른 메서드들과 일관성을 맞추는 것이 가독성에 좋습니다.
50-56: 201 Created 응답에 Location 헤더가 없습니다POST
/items/gambling에서 201 상태 코드를 사용했다면, 새로 생성된 리소스의 URI를Location헤더로 반환하는 것이 REST 관례입니다. URI를 제공하기 어렵다면 200 OK로 응답하는 편이 더 명확할 수 있습니다.
59-65:/skills/gambling도 동일하게 Location 헤더 혹은 상태 코드 재검토 필요위의 아이템 가챠 엔드포인트와 같은 이유로, 201 Created를 유지할 경우
Location헤더를 포함하거나, 리소스가 실제로 생성되지 않는다면 200 OK 사용을 고려해 주세요.
75-83: PATCH 엔드포인트의 반환 코드 200 OK → 204 No Content 권장
equipItem/equipSkill두 메서드는 바디가 없는 성공 응답이므로 204 No Content가 HTTP 의미론에 더 적합합니다. 상태 코드만 수정하면 클라이언트 처리도 단순화됩니다.Also applies to: 85-93
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (55)
src/main/java/org/ezcode/codetest/application/game/dto/mapper/GameMapper.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/AccessorySaveRequest.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/DefenceSaveRequest.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/ItemDeleteRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/ItemEquipRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/ItemSaveRequest.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/SkillDeleteRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/SkillEquipRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/SkillSaveRequest.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/request/WeaponSaveRequest.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/AccessoryResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/CharacterStatusResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/DefenceResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/SkillGamblingResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/SkillResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/dto/response/WeaponResponse.java(1 hunks)src/main/java/org/ezcode/codetest/application/game/management/GameAdminUseCase.java(2 hunks)src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java(5 hunks)src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Accessory.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/CharacterRealStat.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Defence.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacter.java(3 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacterSkill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Inventory.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Item.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Skill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/Weapon.java(2 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/Accessory.java(0 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/AccessoryType.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/Defence.java(0 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/DefenceType.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/Grade.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/Skill.java(0 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/SkillEffect.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/SkillSlotType.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/enums/Weapon.java(0 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/GameCharacterSkillRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/ItemRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/SkillRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java(5 hunks)src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/service/GameShopDomainService.java(2 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemMongoRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/chattingmanagement/chatting/controller/ChatController.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/chattingmanagement/chatting/controller/ChatRoomController.java(1 hunks)src/main/java/org/ezcode/codetest/presentation/game/management/ItemManagementController.java(2 hunks)src/main/java/org/ezcode/codetest/presentation/game/play/GamePlayController.java(4 hunks)src/main/resources/templates/chat-page.html(1 hunks)
💤 Files with no reviewable changes (4)
- src/main/java/org/ezcode/codetest/domain/game/model/enums/Accessory.java
- src/main/java/org/ezcode/codetest/domain/game/model/enums/Weapon.java
- src/main/java/org/ezcode/codetest/domain/game/model/enums/Defence.java
- src/main/java/org/ezcode/codetest/domain/game/model/enums/Skill.java
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacterSkill.java (2)
src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacter.java (1)
Getter(36-123)src/main/java/org/ezcode/codetest/domain/game/model/entity/Skill.java (1)
Getter(20-51)
src/main/java/org/ezcode/codetest/application/game/dto/request/WeaponSaveRequest.java (4)
src/main/java/org/ezcode/codetest/application/game/dto/request/AccessorySaveRequest.java (1)
JsonTypeName(16-81)src/main/java/org/ezcode/codetest/application/game/dto/request/DefenceSaveRequest.java (1)
JsonTypeName(16-71)src/main/java/org/ezcode/codetest/domain/game/model/entity/Item.java (1)
Getter(15-34)src/main/java/org/ezcode/codetest/domain/game/model/entity/Weapon.java (1)
Getter(12-42)
🔇 Additional comments (28)
src/main/resources/templates/chat-page.html (1)
347-354: 엔드포인트 prefix 변경 확인 요청
/room/...→/api/room/...로 수정하셨는데,
- 백엔드 컨트롤러 매핑이 실제로
/api/room/{roomId}/chat인지,- 프록시/컨텍스트 경로에서
/api가 또 중첩되지 않는지
한 번 더 점검해 주세요. 프론트와 백엔드 경로 불일치 시 404 가 즉시 발생합니다.src/main/java/org/ezcode/codetest/domain/game/model/enums/DefenceType.java (1)
5-5:SHIELD추가에 따른 도메인 영향 범위 점검
DefenceType에SHIELD가 추가되었습니다.
– 기존 DB 레코드와 매핑되는 enum ordinal 사용 여부
– 검증 로직(@Pattern, DTO), 서비스 switch-case 문
– 캐릭터 스탯 계산 로직
등에서 누락된 분기가 없는지 확인이 필요합니다.
문제가 없으면 👍, 아니라면 빠르게 보강해 주세요.src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemMongoRepository.java (1)
17-18: 파생 삭제 메서드 추가 👍
deleteByName파생 쿼리 추가는 도메인 서비스 요구사항을 충족하며 Spring-Data MongoDB 규약에도 부합합니다. 별도 우려 사항 없습니다.src/main/java/org/ezcode/codetest/domain/game/repository/ItemRepository.java (1)
15-16: 이름 기반 삭제 시 예외 처리 확인 요청도메인 레이어에서
deleteByName호출 시,
ㆍ해당 이름의 아이템이 없을 경우 구현체가 아무 것도 삭제하지 않는지, 예외를 던지는지 명확히 해둘 필요가 있습니다.
서비스 로직이 결과를 기반으로 후속 처리를 한다면 반환값(삭제 건수 등)을 돌려주는 형태도 고려해 주세요.src/main/java/org/ezcode/codetest/domain/game/model/entity/Item.java (2)
3-3: Grade enum import 확인
Gradeenum 타입으로 전환된 부분은 타입 안정성 측면에서 환영할 만합니다. 다만 기존 컬렉션에 문자열로 저장돼 있던grade값들과의 호환성을 반드시 확인해 주세요.
28-28: 기존 데이터 마이그레이션 검토 필요문자열 → enum 매핑이 실패하면 읽기 시
null또는 예외가 발생할 수 있습니다.
운영 DB에 이미 저장된 Grade 값이 enum 상수와 정확히 일치하는지(대소문자 포함) 점검 후 필요 시 마이그레이션 스크립트를 준비하세요.src/main/java/org/ezcode/codetest/application/game/dto/response/AccessoryResponse.java (1)
7-18: DTO 타입 변경 확인 완료
grade필드를 enum으로 변경한 부분이 일관성을 높여 줍니다. JSON 직렬화 시 문자열로 자동 변환되므로 별도 작업은 필요 없겠습니다.src/main/java/org/ezcode/codetest/application/game/dto/response/WeaponResponse.java (1)
3-19: Grade 타입 변경 👍 – 매핑 코드 일관성만 다시 확인해주세요
grade필드를 enum으로 교체한 결정은 타입 안정성에 도움이 됩니다. 다만, 모든 매핑 계층(Mapper, QueryDSL projection 등)에서String→Grade변경이 누락된 부분이 없는지 한번 더 빌드/테스트로 확인해 주세요.
특별히 수정할 코드는 없어 보입니다.src/main/java/org/ezcode/codetest/presentation/chattingmanagement/chatting/controller/ChatController.java (1)
16-18: 엔드포인트 prefix 변경에 따른 프론트·문서 동기화 필요
/api/room/{roomId}/chat로 prefix 가 바뀌었습니다.
Swagger 문서, 프론트 Fetch URL, Nginx 리버스 프록시 규칙 등 외부 의존 경로가 모두/api를 포함하도록 갱신됐는지 확인 바랍니다.src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterJpaRepository.java (1)
11-12:@EntityGraph경로 변경 – 런타임 검증 필요
"stats"만 eager 로딩하도록 수정한 것은 과도한 fetch 를 줄이는 긍정적 변경입니다.
하지만 과거"skillId"를 쓰던 로직이 Lazy Loading 환경에서 Session 이 닫힌 후 접근될 가능성이 있으니, 서비스 계층에서GameCharacterSkill조회 시점이 안전한지 통합 테스트로 확인해 주세요.src/main/java/org/ezcode/codetest/application/game/dto/response/DefenceResponse.java (1)
3-17: Grade enum 적용 확인 완료
DefenceResponse도 enum 으로 통일되어 DTO 간 일관성이 확보되었습니다. 추가 수정 사항은 없어 보입니다.src/main/java/org/ezcode/codetest/application/game/dto/request/SkillEquipRequest.java (1)
5-10: 레코드 자체는 문제 없음간결한 DTO 작성 방식을 잘 활용하셨습니다. 추가적인 우려 사항 없습니다.
src/main/java/org/ezcode/codetest/domain/game/model/enums/AccessoryType.java (1)
5-5:Details
✅ Verification successful
기존 열거형 사용처 잔존 여부 확인 필요
CHARM,PENDENT상수가 제거되었으므로, 레거시 코드가 여전히 해당 값을 참조한다면 런타임IllegalArgumentException이 발생할 수 있습니다. 리포지토리 전역에서 잔존 참조를 확인해 주세요.
🏁 Script executed:
#!/bin/bash # 제거된 상수 사용 여부 탐색 rg -n --fixed-strings -e 'CHARM' -e 'PENDENT' --glob '*.java' | headLength of output: 66
기존 검색에서 ‘CHARM’와 ‘PENDENT’가 Java 파일 내에서 발견되지 않았으나, 다른 타입의 파일이나 리소스에서도 참조 여부를 확인할 필요가 있습니다. 전역 검색을 수행해 주세요.
🏁 Script executed:
#!/bin/bash # 모든 파일에서 제거된 상수 사용 여부 탐색 rg -n --fixed-strings -e 'CHARM' -e 'PENDENT'Length of output: 43
CHARM 및 PENDENT 상수 참조 없음 확인
전체 파일에 대해 ‘CHARM’와 ‘PENDENT’을 검색한 결과, 참조가 전혀 발견되지 않았습니다. 런타임
IllegalArgumentException위험이 없으므로 현재 변경을 그대로 승인합니다.src/main/java/org/ezcode/codetest/application/game/dto/request/ItemSaveRequest.java (1)
26-30:⚠️ Potential issue정규식 anchoring 누락으로 잘못된 값이 통과합니다
현재 패턴은
LEGENDARY|...만으로 구성돼 있어XXXLEGENDARYYYY같은 문자열도 유효하다고 판단됩니다. 전체 일치를 강제하려면^/$앵커를 추가해야 합니다.- regexp = "LEGENDARY|UNIQUE|RARE|UNCOMMON|COMMON|TRASH", + regexp = "^(LEGENDARY|UNIQUE|RARE|UNCOMMON|COMMON|TRASH)$",Likely an incorrect or invalid review comment.
src/main/java/org/ezcode/codetest/domain/game/model/enums/SkillEffect.java (1)
5-5: 기능 추가 승인새로운 스킬 효과 열거형이 명확하게 정의되었습니다. 도메인 확장에 적절해 보이며 별도 문제는 발견되지 않았습니다.
src/main/java/org/ezcode/codetest/domain/game/model/entity/Defence.java (2)
3-3: Grade 열거형 도입 👍
Gradeenum을 import하여 문자열 대신 타입 안전성을 확보한 점이 좋습니다. DTO·매퍼·저장소 단 모두가 enum 타입을 사용하도록 일관성을 유지했는지 한 번 더 확인해 주세요.
24-32: 생성자 시그니처 변경 적용 여부 확인
grade파라미터 타입을Grade로 변경했으므로,
이 생성자를 호출하는 모든 곳(빌더 포함)이 문자열을 그대로 넘기고 있지 않은지 점검이 필요합니다.
특히 테스트 픽스처나 JSON ↔ 엔티티 매핑 구간에서 컴파일 오류가 숨어 있을 수 있습니다.src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemRepositoryImpl.java (1)
19-26: @OverRide 추가 👍컴파일 타임에 시그니처 불일치를 잡을 수 있어 유지보수성이 향상되었습니다.
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillJpaRepository.java (1)
8-13: ID 타입 일관성 재검증 필요
Skill엔티티의 PK가Long이 맞는지 확인해 주세요.
다른 아이템·스킬 도메인은String id를 사용 중이므로, 혼용될 경우 JPA 매핑 오류나 서비스 레이어 혼란이 발생할 수 있습니다.
필요 시 엔티티·DTO·서비스 전체에서 PK 타입을 통일하는 것을 권장합니다.src/main/java/org/ezcode/codetest/domain/game/model/entity/Accessory.java (1)
24-36: Grade enum 적용 일관성 확보 👍
Accessory에도Gradeenum을 적용하여 도메인 모델이 통일되었습니다.
다만 앞선Defence와 마찬가지로, 빌더·매퍼·테스트 코드에서 문자열을 넘기지 않는지 다시 한 번 확인 바랍니다.src/main/java/org/ezcode/codetest/domain/game/model/entity/Weapon.java (1)
3-3: Enum 도입 👍
Gradeenum을 사용하도록 수정되어 타입 안정성이 향상되었습니다.src/main/java/org/ezcode/codetest/domain/game/repository/SkillRepository.java (1)
8-21: 인터페이스 정의 이상 없음CRUD 범위가 명확히 정의되어 있으며, 메서드 시그니처도 직관적입니다.
추가 의견 없습니다.src/main/java/org/ezcode/codetest/domain/game/model/entity/CharacterRealStat.java (1)
47-63: 패턴 매칭 사용 시 JDK 17 이상 의존
instanceof Weapon weapon문법은 JDK 16+ 기능입니다.
프로젝트sourceCompatibility가 17 이상인지 다시 확인 바랍니다.src/main/java/org/ezcode/codetest/application/game/dto/request/AccessorySaveRequest.java (1)
20-25: 밸리데이션 패턴 추가 👍악세서리 타입 검증 로직이 명확해졌습니다. 성능 및 가독성 모두 만족합니다.
src/main/java/org/ezcode/codetest/domain/game/model/entity/Inventory.java (1)
71-85:item.getItemType()가 null 일 때 NPE 위험도메인 제약상 null 이 아닐 것이라 가정하셨다면 그대로 두어도 되지만, 방어적으로 null 체크를 추가하면 서비스 계층에서 잘못된 Item이 넘어와도 인벤토리 전체 초기화가 실패하지 않습니다.
src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacter.java (1)
105-114:equipItem반환형 변경 영향 확인 필요기존 호출부가 반환값(교체된 아이템 ID)을 사용하던 곳이 있다면 컴파일은 잡히겠지만 런타임 로직이 달라질 수 있습니다. 의도한 변경인지 한번 더 점검해주세요.
src/main/java/org/ezcode/codetest/application/game/play/GamePlayUseCase.java (1)
85-101: 신규 스킬 기능 추가 확인스킬 장착·뽑기 로직이 도메인 서비스에 위임돼 깔끔하게 통합되었습니다. 별다른 문제 없이 동작할 것으로 보입니다.
src/main/java/org/ezcode/codetest/application/game/management/GameAdminUseCase.java (1)
31-41: 어드민 기능 확장 확인아이템/스킬 삭제·생성 기능이 일관성 있게 추가되었습니다. 별다른 이슈 없습니다.
| @NotBlank(message = "삭제하려는 스킬의 이름이 필요합니다.") | ||
| String name | ||
| ) { |
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.
💡 Verification agent
🧩 Analysis chain
스킬 식별 방식 재검토 필요
name 필드 하나만으로 삭제를 수행하면
- 동일 이름 스킬이 중복 존재할 경우 모호성이 발생하고
- 한글·영문 혼용 ‑ 대소문자 차이 등으로 의도치 않은 레코드가 삭제될 위험이 있습니다.
가능하면 DB PK(예: skillId) 또는 고유 키를 추가해 주세요.
추가로, 이름 길이 제한이 없으므로 @Size(max = …) 나 커스텀 밸리데이터로 길이를 제한해 두는 편이 안전합니다.
🏁 Script executed:
#!/bin/bash
# Locate and display the SkillDeleteRequest DTO to verify its fields
find src -name SkillDeleteRequest.java -exec sed -n '1,200p' {} \;Length of output: 277
스킬 삭제 요청 DTO에 고유 식별자 및 입력 길이 제약 추가 필요
현재 SkillDeleteRequest가 오로지 name 필드만 사용하고 있어
- 동일한 이름의 스킬이 중복 존재할 경우 삭제 대상이 모호해질 수 있으며
- 한글·영문 혼용, 대소문자 차이로 의도치 않은 레코드가 삭제될 위험이 있습니다.
다음 사항을 반영해 주세요:
- DTO에 DB PK(예:
Long skillId또는UUID id) 혹은 애플리케이션 레벨 고유 키 추가 name필드에@Size(max = …)또는 커스텀 밸리데이터를 적용해 길이 제한- 삭제 로직(Service/Repository)에서 식별자 기반 삭제로 변경
대상 파일 및 위치:
src/main/java/org/ezcode/codetest/application/game/dto/request/SkillDeleteRequest.java(record 선언부)
위 수정 후 재검토를 부탁드립니다.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/game/dto/request/SkillDeleteRequest.java
around lines 7 to 9, the SkillDeleteRequest DTO currently uses only the name
field for deletion, which risks ambiguity and unintended deletions. Add a unique
identifier field such as Long skillId or UUID id to the DTO, apply a length
constraint annotation like @Size(max = ...) to the name field, and update the
deletion logic in the service and repository layers to use this identifier for
deletion instead of the name.
| @NotBlank(message = "장착할 아이템 이름을 입력해주십시오.") | ||
| String itemName | ||
| String name |
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.
💡 Verification agent
🧩 Analysis chain
필드명 변경으로 인한 API 호환성 주의
itemName → name 으로 변경되어 기존 클라이언트가 바로 깨질 수 있습니다.
버전 관리(URI 버저닝, Header 버저닝 등) 없이 필드명을 변경할 경우
하위 호환 불가가 되므로, 마이그레이션 기간을 두거나 별도 DTO 를 두는 방안을 검토해 주세요.
다른 코드나 테스트에서 기존 itemName 필드를 참조하는지 확인하기 위해 아래 스크립트를 실행해주세요.
🏁 Script executed:
#!/bin/bash
# 1) 과거 필드명(itemName) 참조 검색
rg "itemName" -n
# 2) 해당 DTO가 사용되는 위치 확인
rg "ItemEquipRequest" -nLength of output: 1150
API 호환성 경고: DTO 필드명 변경에 따른 클라이언트 영향
ItemEquipRequest 의 필드명을
// 변경 전
String itemName
// 변경 후
String name으로 바꾸면, 기존에 itemName 키로 요청을 보내던 클라이언트가 모두 실패합니다.
조치 방안 예시:
- DTO 필드에
@JsonAlias("itemName")또는@JsonProperty("name")+@JsonAlias("itemName")추가 - 또는 URI/헤더 버저닝을 도입하여 v1 클라이언트에는 이전 스펙을, v2 클라이언트에는 새 스펙을 반환
- 마이그레이션 기간 동안 두 필드를 모두 지원하는 별도 DTO 유지
위치
- src/main/java/org/ezcode/codetest/application/game/dto/request/ItemEquipRequest.java (7~8줄)
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/game/dto/request/ItemEquipRequest.java
around lines 7 to 8, the field name was changed from itemName to name, which
breaks backward compatibility for existing clients. To fix this, add the
annotation @JsonAlias("itemName") to the new name field so that JSON
deserialization accepts both "name" and the old "itemName" keys, preserving API
compatibility without requiring immediate client changes.
| @Pattern( | ||
| regexp = "LEGENDARY|UNIQUE|RARE|UNCOMMON|COMMON|TRASH", | ||
| flags = Pattern.Flag.CASE_INSENSITIVE, | ||
| message = "아이템 등급은 LEGENDARY, UNIQUE, RARE, UNCOMMON, COMMON, TRASH 중 하나여야 합니다." | ||
| ) |
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
Enum 값 중복 정의 유지보수 부담
Grade enum이 이미 존재하므로, 문자열 패턴을 하드코딩하면 enum 변경 시 DTO를 수동 수정해야 합니다. @EnumValidator 같은 커스텀 어노테이션이나 @ValueOfEnum(Grade.class)를 활용하면 중복을 제거할 수 있습니다.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/game/dto/request/ItemSaveRequest.java
around lines 26 to 30, the item grade validation uses a hardcoded regex pattern
that duplicates the Grade enum values, causing maintenance issues. Replace the
@Pattern annotation with a custom enum validator annotation such as
@EnumValidator or @ValueOfEnum(Grade.class) to directly validate against the
Grade enum values, eliminating duplication and ensuring consistency.
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.
나중에 시간남으면 만들어ㅏ볼게
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 네, 이해합니다! 현재 기능 구현이 우선이시니까 나중에 리팩토링 할 때 고려해보시면 됩니다. 👍
| List<ItemResponse> items, | ||
|
|
||
| List<Skill> skills | ||
| List<SkillResponse> skills | ||
| ) { |
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
List 노출 시 불변 래핑 권장
items, skills 리스트는 그대로 노출되면 외부에서 수정될 수 있습니다.
Collections.unmodifiableList(...) 로 감싸 불변 리스트로 전달하는 편이 안전합니다.
- List<ItemResponse> items,
+ List<ItemResponse> items,
...
- List<SkillResponse> skills
+ List<SkillResponse> skillsCommittable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/game/dto/response/CharacterStatusResponse.java
around lines 25 to 28, the items and skills lists are exposed directly, allowing
external modification. To fix this, wrap these lists with
Collections.unmodifiableList(...) before returning or assigning them to ensure
they are immutable and cannot be altered from outside the class.
src/main/java/org/ezcode/codetest/domain/game/repository/GameCharacterSkillRepository.java
Outdated
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java
Show resolved
Hide resolved
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java
Show resolved
Hide resolved
| public List<String> unEquipAllItems() { | ||
|
|
||
| weaponId = WeaponType.NOTHING.name(); | ||
| defenceId = DefenceType.NOTHING.name(); | ||
| accessoryId = AccessoryType.NOTHING.name(); | ||
| return List.of(weaponId, defenceId, accessoryId); | ||
| } |
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.
착용 해제 시 이전 아이템 ID가 사라집니다
메서드가 장비 ID를 NOTHING 으로 바꾼 뒤 그 새로운 ID들을 리턴하고 있어, 호출 측에서 “기존 장착 아이템을 인벤토리에 되돌린다” 같은 후속 처리를 할 수 없습니다.
public List<String> unEquipAllItems() {
- weaponId = WeaponType.NOTHING.name();
- defenceId = DefenceType.NOTHING.name();
- accessoryId = AccessoryType.NOTHING.name();
- return List.of(weaponId, defenceId, accessoryId);
+ String prevWeapon = weaponId;
+ String prevDefence = defenceId;
+ String prevAccessory= accessoryId;
+
+ weaponId = WeaponType.NOTHING.name();
+ defenceId = DefenceType.NOTHING.name();
+ accessoryId= AccessoryType.NOTHING.name();
+
+ return List.of(prevWeapon, prevDefence, prevAccessory);
}📝 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.
| public List<String> unEquipAllItems() { | |
| weaponId = WeaponType.NOTHING.name(); | |
| defenceId = DefenceType.NOTHING.name(); | |
| accessoryId = AccessoryType.NOTHING.name(); | |
| return List.of(weaponId, defenceId, accessoryId); | |
| } | |
| public List<String> unEquipAllItems() { | |
| String prevWeapon = weaponId; | |
| String prevDefence = defenceId; | |
| String prevAccessory= accessoryId; | |
| weaponId = WeaponType.NOTHING.name(); | |
| defenceId = DefenceType.NOTHING.name(); | |
| accessoryId= AccessoryType.NOTHING.name(); | |
| return List.of(prevWeapon, prevDefence, prevAccessory); | |
| } |
🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacter.java
lines 116 to 122, the unEquipAllItems method overwrites the weaponId, defenceId,
and accessoryId with "NOTHING" before returning them, causing loss of the
original equipped item IDs. To fix this, first store the current IDs in local
variables, then set the fields to "NOTHING", and finally return the stored
original IDs so the caller can handle the unequipped items properly.
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.
안사라짐 걱정 ㄴㄴ
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 알겠습니다! 현재 구현이 의도한 동작이라면 문제없습니다. 🙂
src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java
Show resolved
Hide resolved
| if (allIds.size() != inventoryItems.size()) { | ||
| inventory.cleanUpdateInventory(inventoryItems); | ||
| } | ||
|
|
||
| return inventoryItems; |
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.
인벤토리 정합성 수정 후 목록 재조회 필요
inventory.cleanUpdateInventory() 로 DB 상태를 수정한 뒤에도 inventoryItems 리스트를 그대로 반환하고 있습니다.
정합성 수정으로 제거된 아이템이 리스트에 남아 있을 수 있어 클라이언트와 데이터가 불일치합니다.
- if (allIds.size() != inventoryItems.size()) {
- inventory.cleanUpdateInventory(inventoryItems);
- }
-
- return inventoryItems;
+ if (allIds.size() != inventoryItems.size()) {
+ inventory.cleanUpdateInventory(inventoryItems);
+ inventoryItems = itemRepository.findByIdIn(allIds); // 재조회
+ }
+ return inventoryItems;📝 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.
| if (allIds.size() != inventoryItems.size()) { | |
| inventory.cleanUpdateInventory(inventoryItems); | |
| } | |
| return inventoryItems; | |
| if (allIds.size() != inventoryItems.size()) { | |
| inventory.cleanUpdateInventory(inventoryItems); | |
| inventoryItems = itemRepository.findByIdIn(allIds); // 재조회 | |
| } | |
| return inventoryItems; |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java
around lines 67 to 71, after calling inventory.cleanUpdateInventory() to fix
inventory consistency, the code still returns the original inventoryItems list
which may contain removed items. To fix this, re-query or refresh the
inventoryItems list from the database after the cleanUpdateInventory call to
ensure the returned list reflects the updated, consistent state.
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
♻️ Duplicate comments (2)
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java (2)
31-38: 삭제 결과 미검증 – 이전 리뷰와 동일한 논의
itemRepository.deleteByName(name)호출 후 실제로 삭제가 이루어졌는지 확인하지 않습니다. 삭제 건수가 0이면ITEM_NOT_FOUND예외를 던져 도메인 무결성을 보장하세요. (지난 커밋에서 이미 지적된 내용입니다.)
54-61: 스킬 삭제 결과 미검증 – 이전 리뷰와 동일한 논의
skillRepository.deleteByName(name)호출 후 삭제 건수를 확인하지 않아 무존재 스킬도 “삭제 성공”처럼 보일 수 있습니다. 삭제 수 0일 때SKILL_NOT_FOUND예외를 던지도록 개선이 필요합니다.
🧹 Nitpick comments (2)
src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemMongoRepository.java (1)
17-18:deleteByName의 반환값을long으로 바꾸어 삭제 성공 여부를 확인하세요Spring-Data MongoDB는
long deleteBy…()형태를 지원하여 삭제된 도큐먼트 수를 반환합니다.
현재void반환은 서비스 계층에서 “실제로 삭제되었는지”를 확인하기 어렵게 만듭니다. 반환값을 활용하면 도메인 무결성 검증(예: 삭제 대상 미존재 시 예외) 로직을 간결하게 구현할 수 있습니다.-long deleteByName(String name); +long deleteByName(String name);src/main/java/org/ezcode/codetest/domain/game/repository/ItemRepository.java (1)
13-18: 도메인 레이어에서도 삭제 결과를 반환하도록 일관성 맞추기 권장인프라 레이어의 개선(삭제 수 반환)과 맞추려면 도메인 인터페이스 역시
long deleteByName(String name)으로 선언하는 편이 자연스럽습니다. 서비스 계층에서 결과값 기반 로직을 구현할 수 있어 테스트와 예외 처리가 쉬워집니다.-void deleteByName(String name); +long deleteByName(String name);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacterSkill.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/GameCharacterSkillRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/ItemRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/repository/SkillRepository.java(1 hunks)src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java(5 hunks)src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemMongoRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillRepositoryImpl.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillJpaRepository.java(1 hunks)src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillRepositoryImpl.java(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- src/main/java/org/ezcode/codetest/domain/game/repository/GameCharacterSkillRepository.java
- src/main/java/org/ezcode/codetest/domain/game/model/entity/GameCharacterSkill.java
- src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemRepositoryImpl.java
- src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java
- src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/GameCharacterSkillRepositoryImpl.java
- src/main/java/org/ezcode/codetest/domain/game/repository/SkillRepository.java
- src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillRepositoryImpl.java
- src/main/java/org/ezcode/codetest/domain/game/exception/GameExceptionCode.java
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java (3)
src/main/java/org/ezcode/codetest/domain/game/service/CharacterStatusDomainService.java (1)
Service(26-168)src/main/java/org/ezcode/codetest/application/game/management/GameAdminUseCase.java (1)
Service(13-42)src/main/java/org/ezcode/codetest/domain/game/service/GameShopDomainService.java (1)
Service(22-145)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build
🔇 Additional comments (2)
src/main/java/org/ezcode/codetest/infrastructure/mongodb/repository/ItemMongoRepository.java (1)
21-21:existsByName메서드 명세 문제 없음 – LGTM
조회 전용 메서드는 관용적으로 잘 추가되었습니다.src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillJpaRepository.java (1)
10-10:findByName사용 전 이름 컬럼의 유니크 제약 확인 필요
Optional<Skill> findByName(String name)은 이름이 유일하다는 전제를 암묵적으로 내포합니다.
동일 이름의 스킬이 중복 저장되지 않도록 DB 스키마(@Column(unique = true)) 혹은 서비스 레이어에서의 검증을 반드시 확보해 주세요.
| public Skill createSkill(Skill skill) { | ||
|
|
||
| boolean exists = skillRepository.existsByName(skill.getName()); | ||
|
|
||
| if(exists) throw new GameException(GameExceptionCode.SKILL_ALREADY_EXISTS); | ||
|
|
||
| return skillRepository.save(skill); | ||
| } |
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
createSkill 메서드도 아이템과 동일한 경쟁 조건 이슈
위 아이템 로직과 동일하게 existsByName → save 사이에 경쟁 조건이 존재합니다. 동일 전략(트랜잭션 + 중복키 예외 매핑 혹은 선행 exists 제거)을 적용해 주세요.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java
around lines 45 to 52, the createSkill method has a race condition between the
existsByName check and the save operation. To fix this, apply the same strategy
used in the item logic: either wrap the method in a transaction and handle
duplicate key exceptions to map them to GameException, or remove the pre-check
and rely solely on catching the unique constraint violation during save. This
will prevent concurrent insertions of duplicate skills.
| public Item createItem(Item item) { | ||
|
|
||
| boolean exists = itemRepository.existsByName(item.getName()); | ||
|
|
||
| if(exists) throw new GameException(GameExceptionCode.ITEM_ALREADY_EXISTS); | ||
|
|
||
| return itemRepository.save(item); | ||
| } |
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
중복 체크 후 저장 → 경쟁 조건 가능성, 트랜잭션 어노테이션 검토
existsByName 과 save 사이에 다른 트랜잭션에서 동일 이름 아이템을 삽입하면 유니크 인덱스 충돌 예외가 발생할 수 있습니다. 두 가지 개선안을 제안합니다.
- 서비스 클래스(or 메서드)에
@Transactional부여 후save시 발생하는DuplicateKeyException을 잡아ITEM_ALREADY_EXISTS로 매핑. - 또는 데이터베이스 예외만 활용하고 사전
existsByName호출을 제거(쿼리 1회 절감).
둘 중 하나를 택해 경쟁 조건을 제거하세요.
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java
around lines 22 to 29, the current code checks for item existence before saving,
which can cause race conditions leading to unique constraint violations. To fix
this, either add a @Transactional annotation to the service or method and catch
DuplicateKeyException during save to throw a GameException with
ITEM_ALREADY_EXISTS, or remove the existsByName check entirely and rely on
handling the database unique constraint exception to reduce queries and avoid
race conditions.
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 맞습니다, 현재 코드는 아이템이 존재하면 예외를 던집니다.
제가 지적한 문제는 **경쟁 조건(race condition)**입니다:
- Thread A:
existsByName("아이템1")→false반환 - Thread B:
existsByName("아이템1")→false반환 - Thread A:
save(아이템1)→ 성공 - Thread B:
save(아이템1)→ 데이터베이스 유니크 제약 위반 예외 발생
Thread B는 ITEM_ALREADY_EXISTS 대신 데이터베이스 제약 위반 예외를 받게 됩니다.
현재 동시성 이슈가 없다면 그대로 두어도 되지만, 향후 동시 접근 시 예상치 못한 예외가 발생할 수 있습니다.
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.
이거 어차피 아이템은 어드민이 가끔씩 패치할때 넣는거라 동시성문제가 생길일이없음
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 이해했습니다! 어드민이 패치할 때만 가끔씩 아이템을 추가하는 용도라면 동시성 문제가 발생할 가능성이 거의 없겠네요. 현재 코드 구조가 사용 사례에 적합합니다.
✏️ Learnings added
Learnt from: chat26666
PR: ezcode-my/backend#60
File: src/main/java/org/ezcode/codetest/domain/game/service/GameManagementDomainService.java:22-29
Timestamp: 2025-06-14T11:55:53.267Z
Learning: 아이템 생성 기능은 어드민이 패치할 때만 가끔씩 사용하는 기능으로, 동시성 문제가 발생할 가능성이 낮다.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
|
|
||
| Optional<Skill> findByName(String name); | ||
|
|
||
| void deleteByName(String name); |
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
deleteByName 트랜잭션/변경 메서드 어노테이션 누락
파생(delete) 쿼리는 데이터 변경을 수행하므로 @Transactional 및 @Modifying 어노테이션을 명시적으로 추가해 두는 편이 안전합니다.
현재 상태로도 동작은 하지만, 읽기 전용 트랜잭션으로 래핑될 위험을 제거하고 의도를 분명히 할 수 있습니다.
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.transaction.annotation.Transactional;
...
+ @Transactional
+ @Modifying
void deleteByName(String name);📝 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.
| void deleteByName(String name); | |
| import org.springframework.data.jpa.repository.Modifying; | |
| import org.springframework.transaction.annotation.Transactional; | |
| @Transactional | |
| @Modifying | |
| void deleteByName(String name); |
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/game/SkillJpaRepository.java
at line 12, the deleteByName method lacks the @Transactional and @Modifying
annotations. Add both annotations above the method declaration to explicitly
mark it as a modifying query and ensure it runs within a transactional context,
preventing it from being wrapped in a read-only transaction and clarifying its
intent.
작업 내용
변경 사항
현재까지 업데이트 된 기능들입니다.
해결해야 할 문제
코드 리뷰 전 확인 체크리스트
type :)Summary by CodeRabbit