리뷰 및 평가 기능 (Review & Rating) - fitpassTeam/fitpass GitHub Wiki

리뷰 및 평가 기능 (Review & Rating)

개요

FitPass의 리뷰 및 평가 시스템은 완료된 예약에 대해 헬스장과 트레이너를 5점 척도로 평가하고 리뷰를 남길 수 있는 기능입니다. 예약 완료 후에만 작성 가능하며 헬스장과 트레이너를 같이 평점을 매길 수 있습니다.

평가 체계

평가 대상 평점 범위 평가 기준 제약 조건
헬스장 (Gym) 1~5점 시설, 청결도, 장비 상태 예약 완료 후 작성 가능
트레이너 (Trainer) 1~5점 전문성, 친절함, 지도력 예약 완료 후 작성 가능

리뷰 상태 및 권한

상태 설명 가능한 작업
작성 가능 예약 완료 + 리뷰 미작성 리뷰 생성 가능
작성 완료 리뷰 작성됨 수정, 삭제 (본인만) 가능
조회 전용 타인이 작성한 리뷰 조회만 가능

권한 관리 프로세스

예약 완료 → 리뷰 작성 권한 획득 → 1회 작성 (중복 방지) → 본인만 수정/삭제 가능

리뷰 작성 관리

리뷰 작성 필수 정보

  • 리뷰 내용 (텍스트) 헬스장 평점 (1-5점) 트레이너 평점 (1-5점)

리뷰 작성 프로세스

  1. 예약 완료 상태 확인
  2. 예약 소유자 권한 검증
  3. 중복 리뷰 작성 방지 체크
  4. 평점 유효성 검증 (1-5점)
  5. 리뷰 데이터 저장

리뷰 수정

수정 가능한 정보

  • 리뷰 내용
  • 헬스장 평점
  • 트레이너 평점

수정 제한사항

  • 본인이 작성한 리뷰만 수정 가능
  • 평점은 1-5점 범위 내에서만 수정
  • 예약 정보는 수정 불가

평점 집계 시스템

헬스장 평점 계산

  • 평균 평점 : 해당 헬스장의 모든 리뷰 평점 평균
  • 리뷰 수 : 총 리뷰 개수
  • 실시간 업데이트 : 새 리뷰 작성/수정 시 자동 재계산

트레이너 평점 계산

  • 개별 트레이너별 평점 관리
  • 예약 기반 평가: 실제 PT 세션 완료 후 평가
  • 헬스장 별 트레이너 평점 분리 관리

평점 조회 기능

  • 헬스장 별 평균 평점 및 리뷰 수 조회
  • 트레이너 별 평점 및 리뷰 목록 조회
  • 사용자 별 작성한 리뷰 히스토리 조회

API 명세

리뷰 관리

Method Endpoint 설명 권한
POST /reservations/{reservationId}/reviews 리뷰 생성 USER+
PUT /reservations/{reservationId}/reviews/{reviewId} 리뷰 수정 USER+ (본인만)
DELETE /reservations/{reservationId}/reviews/{reviewId} 리뷰 삭제 USER+ (본인만)

리뷰 조회

Method Endpoint 설명 권한
GET /reviews/{reviewId} 리뷰 단건 조회 Public
GET /reviews/my 내가 작성한 리뷰 목록 USER+
GET /reviews/gyms/{gymId} 헬스장 리뷰 목록 Public
GET /reviews/trainers/{trainerId} 트레이너 리뷰 목록 Public

요청/응답 예시

리뷰 생성 요청

{
  "content": "정말 좋은 시설이고 트레이너님도 친절하셨어요!",
  "gymRating": 5,
  "trainerRating": 4
}

리뷰 생성 응답

{
  "statusCode": 201,
  "message": "리뷰가 성공적으로 생성되었습니다.",
  "data": {
    "id": 1,
    "content": "정말 좋은 시설이고 트레이너님도 친절하셨어요!",
    "gymRating": 5,
    "trainerRating": 4,
    "reservationId": 123,
    "userId": 456,
    "createdAt": "2024-06-26T14:30:00"
  }
}

헬스장 리뷰 목록 조회 응답

{
  "statusCode": 200,
  "message": "헬스장 리뷰 목록을 성공적으로 조회했습니다.",
  "data": [
    {
      "id": 1,
      "content": "정말 좋은 시설이고 트레이너님도 친절하셨어요!",
      "gymRating": 5,
      "trainerRating": 4,
      "gymId": 10,
      "gymName": "FitZone 강남점",
      "trainerId": 20,
      "trainerName": "김철수",
      "userName": "이영희",
      "createdAt": "2024-06-26T14:30:00",
      "updatedAt": "2024-06-26T14:30:00"
    }
  ]
}

헬스장 평점 조회 응답

{
  "statusCode": 200,
  "message": "헬스장 평점을 성공적으로 조회했습니다.",
  "data": {
    "gymId": 10,
    "gymName": "FitZone 강남점",
    "averageGymRating": 4.2,
    "totalReviewCount": 15
  }
}

비즈니스 규칙

리뷰 작성 조건

  • 예약 완료 필수: ReservationStatus.COMPLETED 상태만 허용
  • 예약 소유자만: 본인의 예약에 대해서만 리뷰 작성 가능
  • 1회 제한: 동일 예약에 대해 1개의 리뷰만 작성 가능
  • 평점 범위: 헬스장/트레이너 평점 모두 1-5점 필수

리뷰 수정/삭제 제한

  • 본인만 가능: 리뷰 작성자만 수정/삭제 권한
  • 전체 수정: 내용, 헬스장 평점, 트레이너 평점 모두 수정 가능
  • 평점 검증: 수정 시에도 1-5점 범위 검증

평점 집계 규칙

  • 실시간 반영: 리뷰 생성/수정/삭제 시 평점 자동 재계산
  • 소수점 처리: 평균 평점은 소수점 둘째 자리까지 표시
  • 빈 데이터 처리: 리뷰가 없는 경우 평점 0.0, 리뷰 수 0개

데이터 무결성

  • 외래키 제약: 예약, 사용자 정보 연관 관계 보장
  • 논리적 검증: 예약 상태, 소유권, 중복 체크
  • 트랜잭션 처리: 데이터 일관성 보장

데이터 보안

입력 데이터 검증

  • 평점 범위: 1-5점 외 값 거부
  • 텍스트 길이: 리뷰 내용 최대 길이 제한
  • XSS 방지: HTML 태그 필터링
  • SQL 인젝션 방지: 파라미터 바인딩 사용

권한 검증

  • 예약 소유권: 본인의 예약에 대해서만 리뷰 작성
  • 리뷰 소유권: 본인이 작성한 리뷰만 수정/삭제
  • JWT 인증: 모든 CUD 작업에 사용자 인증 필수
  • 권한별 접근: USER 이상 권한 필요

데이터 일관성

  • 트랜잭션 격리: 동시 리뷰 작성 방지
  • 중복 방지: 예약별 리뷰 유일성 보장
  • 연관 데이터 검증: 예약, 헬스장, 트레이너 존재 확인
  • 상태 동기화: 예약 상태와 리뷰 작성 권한 동기화

성능 최적화

쿼리 최적화

  • JOIN 활용: 연관 엔티티 정보 한번에 조회
  • 인덱스 활용: 자주 조회되는 컬럼 인덱싱
  • 페이징 처리: 대량 리뷰 목록 조회 시 페이징 적용
  • 집계 쿼리: 평점 계산을 DB 레벨에서 처리

캐시 전략

  • 평점 캐싱: 자주 조회되는 헬스장 평점 정보 캐시
  • 무효화 전략: 리뷰 변경 시 관련 캐시 삭제
  • 조회 캐시: 인기 헬스장/트레이너 리뷰 목록 캐시