docs(game): game_likes UNIQUE 제약 dev DB 적용 완료 반영
중복 0 점검 후 ALTER TABLE ADD CONSTRAINT uq_game_likes_game_user UNIQUE(game_id,user_key) 를 dev DB(bibimbap-db/schema dev)에 적용, pg_constraint 검증. B3 체크리스트 [~]→[x]. 별도 prod DB 는 배포 시 동일 마이그레이션 적용 필요. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K3FeMrbtxfTScjrwUukyHD
This commit is contained in:
parent
ee9487e118
commit
4c16d16dd9
|
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
## 잔여 / 미수행 (needs_user_verification)
|
## 잔여 / 미수행 (needs_user_verification)
|
||||||
|
|
||||||
- UNIQUE 마이그레이션(`db/migrations/20260629-game-likes-unique.sql`) 운영 적용 미수행 — 중복 점검 후 적용 게이트 대기. (로컬 dev DB 볼륨은 기존 init 이라 `schema.sql` 의 UNIQUE 변경도 미반영 — 앱레벨 멱등 토글로 기본 동작엔 무관.)
|
- ~~UNIQUE 마이그레이션 운영 적용 미수행~~ → **dev DB 적용 완료 (2026-06-29, `bibimbap-db`/schema `dev`)**: 중복 점검 0건 확인 후 `ALTER TABLE game_likes ADD CONSTRAINT uq_game_likes_game_user UNIQUE (game_id, user_key)`. `pg_constraint` 검증 완료. (별도 prod DB 가 있으면 배포 시 동일 마이그레이션 적용 필요 — `db/migrations/20260629-game-likes-unique.sql`.)
|
||||||
- 상세 초기 `aria-pressed` 상태(AC-7) 정밀 수동 확인은 선택(좋아요 반영 핵심 동작은 스모크로 확인됨).
|
- 상세 초기 `aria-pressed` 상태(AC-7) 정밀 수동 확인은 선택(좋아요 반영 핵심 동작은 스모크로 확인됨).
|
||||||
- L2 dev DB contract: PostgreSQL dev 기동 후 mapper SQL 실DB 동작 확인.
|
- L2 dev DB contract: PostgreSQL dev 기동 후 mapper SQL 실DB 동작 확인.
|
||||||
- 기존 `like_count` 컬럼값과 `game_likes` row 수 초기 불일치는 보존(±1 상대 증감, 절대 재계산은 비목표). 선택적 정합 보정 쿼리는 설계 문서 롤아웃 §3 참조.
|
- 기존 `like_count` 컬럼값과 `game_likes` row 수 초기 불일치는 보존(±1 상대 증감, 절대 재계산은 비목표). 선택적 정합 보정 쿼리는 설계 문서 롤아웃 §3 참조.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| B1 | P1 | login/signup CSRF 검증 추가 | MED, 완료 |
|
| B1 | P1 | login/signup CSRF 검증 추가 | MED, 완료 |
|
||||||
| B2 | P2 | 프로토타입 dead code 제거 | LOW-MED |
|
| B2 | P2 | 프로토타입 dead code 제거 | LOW-MED |
|
||||||
| B3 | P2 | 좋아요/댓글 서버 영속화 연결 | MED, 기능 무결성. 댓글 완료(W3-2) + 좋아요 완료(20260629-151216, 실환경 스모크 PASS 20260629-171042, UNIQUE 마이그레이션 운영 적용 대기) |
|
| B3 | P2 | 좋아요/댓글 서버 영속화 연결 | MED, 기능 무결성. 댓글 완료(W3-2) + 좋아요 완료(20260629-151216, 실환경 스모크 PASS + UNIQUE 제약 dev DB 적용 20260629-171042) |
|
||||||
| B4 | P2 | 의존성/세션/운영 하드닝 | MED |
|
| B4 | P2 | 의존성/세션/운영 하드닝 | MED |
|
||||||
|
|
||||||
## B1. login/signup CSRF 검증 추가 (MED)
|
## B1. login/signup CSRF 검증 추가 (MED)
|
||||||
|
|
@ -103,7 +103,7 @@
|
||||||
|
|
||||||
- [x] `POST /game/{id}/like` 또는 `/api/games/{id}/like` 엔드포인트를 설계한다. → **`POST /game/{id}/like` 토글(@Transactional). 게이트 CSRF(403)→로그인(401)→존재(404).**
|
- [x] `POST /game/{id}/like` 또는 `/api/games/{id}/like` 엔드포인트를 설계한다. → **`POST /game/{id}/like` 토글(@Transactional). 게이트 CSRF(403)→로그인(401)→존재(404).**
|
||||||
- [x] 좋아요 추가/취소는 CSRF 검증을 적용한다. → **`CsrfTokens.isValid(request)` 선행(403). 회귀 테스트 AC-4 PASS.**
|
- [x] 좋아요 추가/취소는 CSRF 검증을 적용한다. → **`CsrfTokens.isValid(request)` 선행(403). 회귀 테스트 AC-4 PASS.**
|
||||||
- [~] `game_likes` 중복 방지 키를 DB 또는 트랜잭션에서 보장한다. → **애플리케이션 레벨 select-then-act + 단일 트랜잭션으로 1차 방어. DB UNIQUE(game_id,user_key) 제약은 `db/schema.sql` 반영 + `db/migrations/20260629-game-likes-unique.sql` 신규, 운영 DB 미적용(중복 점검 후 적용 게이트 — [maintenance/post-deploy-verification-checklist.md](../maintenance/post-deploy-verification-checklist.md)).**
|
- [x] `game_likes` 중복 방지 키를 DB 또는 트랜잭션에서 보장한다. → **애플리케이션 레벨 select-then-act + 단일 트랜잭션 1차 방어 + DB UNIQUE(game_id,user_key) 제약 2차 방어. `db/schema.sql` 반영 + `db/migrations/20260629-game-likes-unique.sql`. dev DB 적용 완료(2026-06-29, 중복 0 점검 후 ALTER, `pg_constraint` 검증). 별도 prod DB 배포 시 동일 마이그레이션 적용.**
|
||||||
- [x] `games.like_count` 증감은 race condition 없이 처리한다. → **`incrementLikeCount`(`SET like_count = like_count + 1`)/`decrementLikeCount`(`GREATEST(like_count - 1, 0)`) DB 원자 UPDATE + row 변경과 동일 `@Transactional` 단위. 클라이언트 ±1 추정 제거(토글 직후 컬럼 재조회 응답).**
|
- [x] `games.like_count` 증감은 race condition 없이 처리한다. → **`incrementLikeCount`(`SET like_count = like_count + 1`)/`decrementLikeCount`(`GREATEST(like_count - 1, 0)`) DB 원자 UPDATE + row 변경과 동일 `@Transactional` 단위. 클라이언트 ±1 추정 제거(토글 직후 컬럼 재조회 응답).**
|
||||||
- [x] `GET /game/{id}/comments` 또는 상세 모델 주입 방식을 결정한다. → **초기 모델 주입 가능 + 별도 GET C1(`GET /game/{id}/comments`) fetch 방식 채택.** GameCommentController C1 구현 완료(20260618-104034).
|
- [x] `GET /game/{id}/comments` 또는 상세 모델 주입 방식을 결정한다. → **초기 모델 주입 가능 + 별도 GET C1(`GET /game/{id}/comments`) fetch 방식 채택.** GameCommentController C1 구현 완료(20260618-104034).
|
||||||
- [x] `POST /game/{id}/comments`는 CSRF, 길이 제한, 작성자 정책을 적용한다. → **C2 `POST /game/{id}/comments`: CsrfTokens.isValid(403), content 200자(400), 로그인(401) 적용.** L1 12건 PASS(20260618-104034).
|
- [x] `POST /game/{id}/comments`는 CSRF, 길이 제한, 작성자 정책을 적용한다. → **C2 `POST /game/{id}/comments`: CsrfTokens.isValid(403), content 200자(400), 로그인(401) 적용.** L1 12건 PASS(20260618-104034).
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue