Skip to content

소셜 토너먼트 위시 자동 편입 분기 + '위시에도 담기' 수동 버튼 #919

Description

@sevineleven

상위 Epic

  • 지금 원칙은 "토너먼트에 담기는 순간 자동 위시 편입"이고, 그 밑엔 **"토너먼트 = 항상 나 자신을 위한 결정"**이라는 전제가 깔려 있다.
  • 실제로는 그 전제가 깨지는 케이스가 있다 — 선물용(타인을 위한 결정)과 소셜(타인이 담은 것). 이때 자동 편입하면 "내가 사고 싶은 것"이 아닌 아이템이 내 위시에 섞인다.
  • 판단 기준을 **"누가 담았나"가 아니라 "누구를 위한 것인가"**로 재정의한다.

무엇을 — 최종 정책

아이템 출신(링크/이미지) × 토너먼트 종류(개인/소셜)로 편입 규칙을 나눈다.

개인(SOLO) 토너먼트 소셜(SOCIAL) 토너먼트
링크 아이템 START 시 자동편입 ROOT 에게 "위시에도 담기" 수동 버튼
이미지 아이템 제외 제외
  • 개인 + 링크 = 자동편입 — 혼자 하는 결정이고, 링크는 상품 정체성이 있어 "내 위시"로 추적할 가치가 있음.
  • 소셜 = 자동 OFF — 내가 담든 친구가 담든 "정말 나를 위한 건지"를 시스템이 판단 불가. 대신 주인이 "이건 진짜 갖고 싶다" 싶은 것만 수동으로 담게.
  • 이미지 = 항상 제외 — 링크(상품 정체성)가 없어 위시로 옮겨도 가격 추적·새로고침이 안 되는 반쪽 위시가 된다.

설계

편입 시점 — START 정산 (담는 순간 아님)

생성 직후엔 모든 토너먼트가 SOLO 라(아무도 참여 안 함), 담는 순간엔 개인/소셜을 알 수 없다. 그래서 자동편입을 담을 때가 아니라 START 시점에 정산한다 — 그때 SOLO/SOCIAL 이 확정되므로 선물 후보가 위시에 잘못 섞이는 일이 없다. (부작용: START 안 한 개인 토너먼트의 링크는 편입 안 됨 — 커밋 안 한 것이라 수용.)

자동편입 — 서버, START · SOLO

  • startAsOwner 에서 토너먼트가 SOLO(참가자 = owner 1명)면, owner 의 링크 아이템(sourceUrl 있음) 전부를 owner 위시로 생성.
  • SOCIAL 이거나 이미지 아이템이면 안 함.
  • 외부 호출 없는 순수 영속화지만, 위시 생성은 별도 빈에 위임해 짧은 트랜잭션으로 묶는다(WishPersistenceService 패턴).

수동 "위시에도 담기" — 신규 API, SOCIAL

  • 새 엔드포인트: POST /tournaments/{id}/items/{tournamentItemId}/wish (필요 시 다건).
  • 권한: ROOT owner 만 (아니면 403). 대상은 모든 참가자의 링크 아이템 — 주인이 친구가 올린 것 중 갖고 싶은 것도 자기 위시로.
  • ROOT 위시로 생성. 이미지 아이템(sourceUrl 없음)은 거부.

엣지 케이스

  • 중복(이미 위시에 있음): 멱등 — 조용히 skip, 에러 안 냄. 버튼은 "담김" 상태로.
  • 이미지 아이템(sourceUrl 없음): 자동·수동·API 모두 제외/거부.
  • CLONE 토너먼트: 항상 SOCIAL → 자동편입 없음. 버튼은 ROOT 화면에서만.
  • 위시 snapshot: 출전 고정본이 아니라 아이템의 현재 active snapshot으로 위시 생성 (이후 가격추적이 최신 기준으로 이어지게).

클라

  • 소셜 + ROOT 뷰: 각 링크 아이템(sourceUrl 있음)에 "위시에도 담기" 버튼, 이미 위시면 "담김" 표시.
  • 개인: 버튼 없음 (START 시 자동).

테스트

  • 단위: 링크/이미지 판정, SOLO/SOCIAL 판정, 멱등(중복 skip).
  • 통합: START·SOLO 자동편입, START·SOCIAL 미편입, 수동 API 계약(성공 / 비-ROOT 403 / 이미지 거부 / 멱등).

코드 현황 (조사 완료)

이미지가 전제한 "토너먼트 담기 → 위시 자동 편입"은 서버·웹·앱 어디에도 실제로 없다. 현재는 위시와 토너먼트 후보 바구니가 완전히 분리된 두 컬렉션이다.

  • 서버: addItemsFromWish는 반대 방향(위시 → 토너먼트)이고 담으려면 이미 위시일 것을 요구(itemNotInWishlist). 링크/이미지 담기(TournamentItemService)는 위시를 만들지 않음.
  • 클라: 링크/이미지 담기 공용 다이얼로그(GetItemDialog)가 type prop 으로 배타 분기 — type="wish" → 위시에만, type="tournament" → 후보 바구니에만.

활용 가능한 기존 재료:

  • 링크/이미지 구분: 토너먼트 아이템 응답의 sourceUrl(이미지로 등록하면 undefined).
  • 개인/소셜 구분: TournamentPlayType(SOLO/SOCIAL) 파생값 — CLONE 이거나 참가자 2명 이상이면 SOCIAL. start()startAsOwner/startAsMember 로 갈려 SOLO 판정 훅 지점이 명확.

실작업 범위

  1. 서버 자동편입startAsOwner·SOLO 에서 owner 링크 아이템을 owner 위시로 (별도 빈 위임). 이미지 제외.
  2. 서버 수동 APIPOST .../items/{id}/wish, ROOT-only(403), 모든 참가자 링크 아이템 대상, 멱등, 이미지 거부. *Api/*ApiExamples/응답 문서화 포함.
  3. 클라 버튼 — 소셜 ROOT 뷰의 링크 아이템에 "위시에도 담기"(+"담김" 상태).
  4. 테스트 — 위 단위·통합.

Metadata

Metadata

Assignees

Labels

feat외부 가시적 새 기능

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions