리뷰 및 평가 기능 (Review & Rating) - fitpassTeam/fitpass GitHub Wiki
리뷰 및 평가 기능 (Review & Rating)
개요
FitPass의 리뷰 및 평가 시스템은 완료된 예약에 대해 헬스장과 트레이너를 5점 척도로 평가하고 리뷰를 남길 수 있는 기능입니다. 예약 완료 후에만 작성 가능하며 헬스장과 트레이너를 같이 평점을 매길 수 있습니다.
평가 체계
평가 대상 |
평점 범위 |
평가 기준 |
제약 조건 |
헬스장 (Gym) |
1~5점 |
시설, 청결도, 장비 상태 |
예약 완료 후 작성 가능 |
트레이너 (Trainer) |
1~5점 |
전문성, 친절함, 지도력 |
예약 완료 후 작성 가능 |
리뷰 상태 및 권한
상태 |
설명 |
가능한 작업 |
작성 가능 |
예약 완료 + 리뷰 미작성 |
리뷰 생성 가능 |
작성 완료 |
리뷰 작성됨 |
수정, 삭제 (본인만) 가능 |
조회 전용 |
타인이 작성한 리뷰 |
조회만 가능 |
권한 관리 프로세스
예약 완료 → 리뷰 작성 권한 획득 → 1회 작성 (중복 방지) → 본인만 수정/삭제 가능
리뷰 작성 관리
리뷰 작성 필수 정보
- 리뷰 내용 (텍스트)
헬스장 평점 (1-5점)
트레이너 평점 (1-5점)
리뷰 작성 프로세스
- 예약 완료 상태 확인
- 예약 소유자 권한 검증
- 중복 리뷰 작성 방지 체크
- 평점 유효성 검증 (1-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 레벨에서 처리
캐시 전략
- 평점 캐싱: 자주 조회되는 헬스장 평점 정보 캐시
- 무효화 전략: 리뷰 변경 시 관련 캐시 삭제
- 조회 캐시: 인기 헬스장/트레이너 리뷰 목록 캐시