Skip to content

[Feat]#62 퀘스티 기본 아이템 7종 지연 지급 · 상점 배경 카테고리 추가 - #63

Merged
Chhun-Lee merged 5 commits into
developfrom
feature/#62-default-items-background
Sep 14, 2026
Merged

Chhun-Lee merged 5 commits into
developfrom
feature/#62-default-items-background

Conversation

@Chhun-Lee

Copy link
Copy Markdown
Contributor

#️⃣ 연관된 이슈

#62

📝 작업 내용

프론트 확정 사항(꾸미기 아이템 7종은 기본 보유, 아이템 상점은 배경 5종만)에 맞춰 서버 마스터 데이터와 지급 경로를 정리했습니다. 기존엔 shop_items에 기본 아이템이 4종뿐이고 이름도 달랐으며, 배경 카테고리가 없고, is_default 아이템을 user_items에 넣어주는 코드가 없어 프론트가 장착·구매 상태를 서버에 저장할 수 없었습니다.

  • BACKGROUND 카테고리 추가: ItemCategory에 추가하고 equip_slot_limits에 BACKGROUND(동시 장착 1개) 시딩.
  • 마스터 시더를 코드 기준 upsert로 교체: ItemMasterDataSeeder가 코드로 조회해 없으면 INSERT, 정의가 다르면 UPDATE, 정의 목록에 없는 활성 아이템은 비활성화(RewardMasterDataSeeder.seedBadges와 같은 패턴). 기본 보유 7종(탐험가 모자 / 보라 선글라스 / 빨간 스카프 / 노란 우비 / 탐험 조끼 / 여행 가방 / 탐험 돋보기, 가격 0, is_default=true) + 배경 5종(포근한 카페 320 / 햇살 교실 320 / 포근한 방 280 / 바닷가 캠핑 360 / 별빛 관측소 280). 구 아이템(SUNGLASSES, BLUE_SCARF, 판매 모자 3종)은 비활성화되고 행은 남습니다.
  • 상점 목록에서 기본 아이템 제외: GET /api/shop/items는 is_active=true AND is_default=false만 반환 → 배경 5종만 노출.
  • 기본 아이템 지연 지급: 새 Bean DefaultItemGranter가 보유 목록(GET /api/users/me/items)·퀘스티(GET /api/users/me/questy)·장착(POST /api/users/me/items/{id}/equip) 진입 시 미보유 기본 아이템을 INSERT ... SELECT ... WHERE NOT EXISTS ... ON DUPLICATE KEY UPDATE로 멱등 지급. 가격 0이라 포인트 원장·활동 기록은 남기지 않습니다. 가입 훅(회원 도메인)은 건드리지 않았습니다.
  • 비활성 아이템 처리: 보유 목록·퀘스티·장착 대상·슬롯 계산에서 제외. 해제는 그대로 허용(멱등).

변경 사항

  • API 시그니처·경로 변경 없음. 응답 필드 변경 없음(ShopItemResponseDTO.isDefault는 상점 목록에서 항상 false).
  • 동작 변경: 상점 목록에서 기본 아이템이 빠짐. 보유 목록·퀘스티·장착 호출 시 기본 아이템이 자동 지급됨(해당 세 서비스 메서드는 INSERT가 들어가 readOnly 해제).
  • DB: DDL 변경 없음. category 컬럼(VARCHAR 20)에 BACKGROUND 값이 들어가고 equip_slot_limits에 행 1개가 시더로 추가됨. 기존 dev DB는 재부팅만으로 반영(시더가 upsert + 비활성화).
  • image_url은 전부 null 유지. 프론트가 상점 응답의 code로 자체 에셋을 매핑합니다.
  • 에러 코드 변경 없음. docs/error-codes.md 변경 없음.
  • Swagger: ShopItemController/UserItemController/QuestyController 설명에 기본 아이템 제외·지급 시점 명시.

스크린샷 (Swagger 등)

경로 추가·변경이 없어 SwaggerGroupCoverageTest 그대로 통과. 통합 테스트에서 GET /api/shop/items 결과가 배경 5종(COZY_CAFE, SUNNY_CLASSROOM, COZY_ROOM, BEACH_CAMPING, STARLIGHT_OBSERVATORY)만인 것을 확인했습니다.

💬 리뷰 요구사항

  • UserItemRepository.grantDefaultItems: INSERT ... SELECT에서 ON DUPLICATE KEY UPDATE id = id가 "Column 'id' in field list is ambiguous"로 실패해 user_items.id = user_items.id로 한정했습니다. 또 NOT EXISTS로 이미 보유한 행을 SELECT 단계에서 걸러, 전부 보유한 정상 상태에서 홈 조회마다 기존 행에 X-lock을 잡지 않게 했습니다(ON DUPLICATE KEY는 동시 첫 요청 경합의 안전망으로만 남김).
  • 지급을 별도 Bean(DefaultItemGranter)에 두되 트랜잭션은 호출부에 합류(REQUIRED)합니다. 지급과 이어지는 조회가 어긋날 이유가 없어 REQUIRES_NEW를 쓰지 않았습니다.
  • 기본 아이템은 여전히 POST /api/shop/items/{id}/purchase로 0원 "구매"가 가능합니다(이미 보유면 400). 프론트가 쓰지 않는 경로라 그대로 뒀는데, 막는 게 낫다고 보시면 findByIdAndIsActiveTrueAndIsDefaultFalse 한 줄로 닫을 수 있습니다.
  • ShopItem.deactivate()는 user_items.is_equipped를 건드리지 않습니다. 비활성 아이템을 나중에 정의에 되살리면 장착 상태로 다시 나타날 수 있어 주석으로 남겼습니다(현재는 dev 데이터뿐).

PR 전 필수 체크리스트

  • 관련 이슈를 연결했습니다.
  • 로컬에서 정상 동작을 확인했습니다.
  • 필요한 테스트를 수행했습니다.
  • Swagger/API 명세를 업데이트했습니다.
  • 불필요한 로그 또는 주석을 제거했습니다.
  • 민감 정보가 포함되지 않았는지 확인했습니다.

테스트 결과

  • 단위 테스트 — ItemMasterDataSeederTest(INSERT / no-op / UPDATE / 비활성화·재활성화), ShopItemServiceTest, UserItemServiceTest(지급이 조회보다 먼저 호출되는지 InOrder 검증)
  • 통합 테스트 — Testcontainers MySQL 8.4: 첫 조회 7개 지급 + 재조회 중복 없음 + 원장 행 없음, 장착 진입 시 지급, 상점 배경 5종만, 비활성 아이템 제외 + 행 보존, 시더 재실행 시 updated_at 불변. 구매 통합 테스트는 비활성화된 GOLDEN_CROWN 대신 COZY_CAFE(320P) 기준으로 변경
  • Swagger 테스트 — SwaggerGroupCoverageTest 통과
  • Postman 테스트
  • 직접 실행 확인 — item 도메인 26개 전부 통과. 전체 스위트는 로컬 DB_URL 없이 도는 contextLoads 1건만 실패(환경 문제, CI는 MySQL 서비스 컨테이너 사용)

🤖 Generated with Claude Code

https://claude.ai/code/session_01HtgegmjNs3gAc6qNCTekNa

Chhun-Lee and others added 5 commits September 14, 2026 15:01
기본 보유 7종·상점 배경 5종 정의, 목록 외 활성 아이템은 비활성화

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HtgegmjNs3gAc6qNCTekNa
INSERT ... SELECT의 ON DUPLICATE KEY UPDATE id가 모호하다는 실DB 오류를
user_items.id로 한정해 수정. 구매 통합 테스트는 비활성화된 GOLDEN_CROWN 대신
COZY_CAFE(320P) 기준으로 변경

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HtgegmjNs3gAc6qNCTekNa
정상 상태(전부 보유)에서 호출마다 ON DUPLICATE KEY가 기존 행에 X-lock을 잡던 문제를
SELECT 단계에서 미보유분만 고르도록 수정. 비활성 아이템이 보유 목록·장착에서 빠지는지,
시더 재실행 시 updated_at이 그대로인지 실DB 테스트 추가

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HtgegmjNs3gAc6qNCTekNa
@Chhun-Lee Chhun-Lee self-assigned this Sep 14, 2026
@Chhun-Lee Chhun-Lee added the 🐛 fix 버그 관련 라벨 label Sep 14, 2026
@Chhun-Lee
Chhun-Lee merged commit 53daa57 into develop Sep 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 fix 버그 관련 라벨

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant