장단콩 보드게임 & 미니어처 게임 클럽

참석자 상호 평점 시스템 설계

개요

게임 일정(poststype: "event")에 참석한 사람들이 일정 종료 후 서로를 평가하는 기능. 평가 점수는 누적되어 개인 평균 점수로 반영된다.

흐름 요약

  1. 사용자가 일정에 참석 신청 → attendees 배열에 등록 (기존 기능)
  2. 일정 당일 자정이 지나면, 일정 상세 페이지에 “평가하기” 섹션이 열림
  3. 참석자는 자신을 제외한 다른 참석자 각각에 대해 3개 항목(매너/실력/재만남 의향)을 5점 척도로 평가하거나 “불참”으로 표시
  4. 제출한 평가는 수정 불가 (1회 제출로 고정)
  5. 점수는 stats/global에 누적되어 개인 평균으로 계산되고, 상시 공개된다 (아래 “참가 신청자 hover 열람” 참고)

출석 확정 (사전 준비 단계)

데이터 모델

posts/{postId} (기존 문서에 필드 추가)

confirmedAttendees?: string[]   // uid 배열. 없으면 attendees로 fallback

ratings/{postId}_{raterUid}_{targetUid} (신규 컬렉션)

{
  postId: string,
  raterUid: string,
  targetUid: string,
  noShow: boolean,        // true면 아래 점수 필드 없음
  manner?: 1-5,
  skill?: 1-5,
  again?: 1-5,
  createdAt: serverTimestamp
}

문서 ID를 postId_raterUid_targetUid로 고정 → 동일 대상 중복 제출이 구조적으로 불가능하며, 이것으로 “수정 불가” 요건도 충족한다 (재제출 시도는 이미 문서가 존재하므로 거부).

stats/global (기존 문서에 필드 추가)

members.{uid}.ratingSum.manner: number
members.{uid}.ratingSum.skill: number
members.{uid}.ratingSum.again: number
members.{uid}.ratingCount: number   // noShow 평가는 카운트에서 제외

기존 attendCount/postCount와 동일한 increment() 누적 패턴을 따른다. 평균은 조회 시 sum / count로 계산하며 별도 저장하지 않는다.

화면 (post.js, 일정 상세 페이지)

출석 확정 섹션 (작성자 전용)

평가 섹션 (참석자 전용, 자정 이후 노출)

점수 열람 (마이페이지)

참가 신청자 hover 열람 (신규)

시간 판정

자정 경과 여부는 클라이언트의 new Date()eventDate 비교로 판단한다. Firestore 보안 규칙에서 서버 시간 기준 재검증은 하지 않는다 — 내부 친목 모임 앱으로 악의적 조작 유인이 낮고, 기존 코드도 마감 인원 체크 등을 트랜잭션+클라이언트 조합으로만 처리해온 것과 일관된다.

범위 밖 (Out of scope)