123 lines
5.9 KiB
Markdown
123 lines
5.9 KiB
Markdown
---
|
|
kind: change
|
|
title: "W3-2 댓글/리뷰 분리 구현"
|
|
session_id: 20260618-104034
|
|
created_at: 2026-06-18
|
|
status: implemented
|
|
related_security_checklist: "../security/security-remediation-checklist.md"
|
|
related_work_log: "../work-log/2026-06-17-w3-feature-skeletons.md"
|
|
related_design: "../../.atp/work-session/20260618-104034/design.md"
|
|
---
|
|
|
|
# W3-2 댓글/리뷰 분리 구현 변경 이력
|
|
|
|
상위 골자: [W3 사이트 플랫폼 기능 골자 카탈로그](../work-log/2026-06-17-w3-feature-skeletons.md) §W3-2.
|
|
|
|
## 개요
|
|
|
|
기존 `game_comments`(닉네임 자유입력, localStorage 전용)를 서버 영속화 + 로그인 연동으로 전환하고,
|
|
별점 5점 + 서술 평가 형태의 `game_reviews` 도메인을 신설했다.
|
|
|
|
## 변경된 런타임 동작
|
|
|
|
### 1. 댓글 서버 영속화 전환
|
|
|
|
- **이전**: 댓글이 `localStorage`에만 저장. `game_comments` 매퍼·테이블은 고아 상태.
|
|
- **이후**: 댓글이 서버 DB `game_comments`에 영속. 새로고침·브라우저 변경 후에도 유지.
|
|
- 기존 localStorage 댓글은 마이그레이션하지 않음(보안 [hold] 정합 — QG-2 결정).
|
|
- `game_comments.user_id` bigint NULL FK 추가(비파괴, 레거시 nickname 레코드 보존).
|
|
- content 200자 앱레벨 검증 신규 적용(이전: 길이 제한 없음).
|
|
|
|
### 2. game_reviews 도메인 신설
|
|
|
|
- 신규 테이블 `game_reviews`: 게임당 1회 제한(partial UNIQUE WHERE is_delete IS NOT TRUE), rating smallint CHECK(1~5), body text.
|
|
- "수정됨" 상태: in-row(updated_at > created_at). 별도 이력 테이블 없음(열람 권한 확정 시 후속).
|
|
- 삭제: soft-delete(is_delete, deleted_at).
|
|
|
|
### 3. 권한 모델
|
|
|
|
- 댓글/리뷰 수정·삭제: 작성자 본인(`sessionUserId == 리소스.userId`) OR 운영자(`ROLE_ADMIN="ADMIN"`).
|
|
- 운영자 role 부여 경로는 W1 RBAC 연결 시 활성(현재 휴면 — 부여자 없음).
|
|
- 로그인 없는 쓰기 시도: 401.
|
|
- CSRF 토큰 없는 상태 변경: 403.
|
|
|
|
### 4. 게임 삭제 cascade 확장
|
|
|
|
- `GameController.deleteGame`에 `softDeleteGameReviews` 추가.
|
|
- 게임 삭제 시 관련 리뷰도 soft-delete.
|
|
|
|
## 신규/변경 파일
|
|
|
|
### 신규 파일 (백엔드)
|
|
|
|
| 파일 | 설명 |
|
|
|---|---|
|
|
| `src/.../data/GameReviewData.java` | 리뷰 도메인 POJO |
|
|
| `src/.../mapper/GameReviewsMapper.java` | 리뷰 MyBatis 매퍼 |
|
|
| `src/.../controller/api/GameCommentController.java` | 댓글 CRUD API (C1~C4) |
|
|
| `src/.../controller/api/GameReviewController.java` | 리뷰 CRUD API (R1~R5) |
|
|
| `docs/game-reviews-ddl.sql` | 권위 DDL (멱등 ALTER, 기존 DB 적용용) |
|
|
| `src/test/.../GameCommentControllerTest.java` | 댓글 컨트롤러 단위 테스트 12건 |
|
|
| `src/test/.../GameReviewControllerTest.java` | 리뷰 컨트롤러 단위 테스트 13건 |
|
|
|
|
### 변경 파일
|
|
|
|
| 파일 | 변경 내용 |
|
|
|---|---|
|
|
| `src/.../data/GameCommentData.java` | userId 필드 추가 |
|
|
| `src/.../mapper/GameCommentsMapper.java` | user_id 기반 쿼리 확장 |
|
|
| `src/.../mapper/GamesMapper.java` | softDeleteGameReviews 추가 |
|
|
| `src/.../controller/api/GameController.java` | deleteGame cascade 확장, currentUserId/userRole 모델 노출 |
|
|
| `db/schema.sql` | game_reviews CREATE + game_comments user_id ALTER |
|
|
| `src/main/webapp/WEB-INF/views/game-detail.jsp` | 댓글 localStorage→서버 fetch 교체, 리뷰 UI 신규(별점 위젯·수정됨 마커·게임당1회·로그인 게이트) |
|
|
| `src/test/.../BibimbapApplicationTests.java` | GameCommentsMapper/GameReviewsMapper @MockBean 2개 추가 |
|
|
|
|
## 신규 API 9개
|
|
|
|
### 댓글 (GameCommentController)
|
|
|
|
| ID | 메서드 | 경로 | 설명 |
|
|
|---|---|---|---|
|
|
| C1 | GET | `/game/{id}/comments` | 댓글 목록 조회 |
|
|
| C2 | POST | `/game/{id}/comments` | 댓글 작성 (CSRF·로그인·200자 검증) |
|
|
| C3 | PUT | `/game/{id}/comments/{commentId}` | 댓글 수정 (작성자/운영자) |
|
|
| C4 | DELETE | `/game/{id}/comments/{commentId}` | 댓글 삭제 (작성자/운영자) |
|
|
|
|
### 리뷰 (GameReviewController)
|
|
|
|
| ID | 메서드 | 경로 | 설명 |
|
|
|---|---|---|---|
|
|
| R1 | GET | `/game/{id}/reviews` | 리뷰 목록 조회 |
|
|
| R2 | GET | `/game/{id}/reviews/{reviewId}` | 리뷰 단건 조회 |
|
|
| R3 | POST | `/game/{id}/reviews` | 리뷰 작성 (게임당 1회, CSRF·로그인·rating 검증) |
|
|
| R4 | PUT | `/game/{id}/reviews/{reviewId}` | 리뷰 수정 (수정됨 마커, 작성자/운영자) |
|
|
| R5 | DELETE | `/game/{id}/reviews/{reviewId}` | 리뷰 삭제 (soft-delete, 작성자/운영자) |
|
|
|
|
모든 상태 변경 API 공통 시퀀스: `@Transactional → CsrfTokens.isValid (403) → sessionUserId (401) → 검증 (400) → mapper → JSON`.
|
|
|
|
## 범위 밖 (미변경)
|
|
|
|
- **좋아요**: 여전히 localStorage 전용. 보안 체크리스트 B3 좋아요 항목 별도 관리.
|
|
- **운영자 role 부여**: ROLE_ADMIN 상수 정의만. 실제 부여 경로는 W1 RBAC 연결 시.
|
|
- **W2-3 집계 계약**: game_reviews가 평점 공급원(rating 컬럼)까지만. AVG/COUNT 집계·뷰 미생성(W2-6 시상 후속).
|
|
- **리뷰 이력 열람**: in-row 수정됨 마커만. 이력 테이블은 열람 권한 확정 시 후속.
|
|
|
|
## 검증 결과 요약
|
|
|
|
| 레이어 | 결과 |
|
|
|---|---|
|
|
| L1 단위 테스트 (31건) | PASS (GameCommentControllerTest 12 + GameReviewControllerTest 13 + UserControllerCsrfTest 5 + BibimbapApplicationTests 1) |
|
|
| AGG-1 엔드포인트 수 | PASS (Comment 4, Review 5) |
|
|
| AGG-3 CSRF 게이트 | PASS (합산 6개) |
|
|
| AGG-2 DDL 3종 | PASS |
|
|
| L3 브라우저 스모크 | needs_user_verification |
|
|
| DDL 적용 | needs_user_verification (docs/game-reviews-ddl.sql 참조) |
|
|
|
|
## 이월 항목
|
|
|
|
1. W2-3 평점 집계 계약 (SELECT AVG/COUNT) — W2-6 시상 후속.
|
|
2. 운영자 role 부여 경로 — W1 RBAC/Interceptor 연결 시 활성.
|
|
3. 다축(육각형) 평점 — 현재 단일 rating, game_review_axes 분리 여지(주석).
|
|
4. 리뷰 이력 열람 권한 — 열람 정책 확정 시 별도 이력 테이블.
|
|
5. GameCatalog 정적 폴백 게임 대상 댓글/리뷰 — DB 실제 게임만 기능 동작(폴백은 404).
|