bibimbap/docs/analysis/2026-06-16-project-analysis.md

26 KiB

2026-06-16 프로젝트 전면 분석

범위

  • 목적: 현재 프로젝트의 아키텍처, 보안, 품질, 도메인 상태를 읽기 전용으로 분석하고 후속 보안 개선 항목을 정리한다.
  • 변경 원칙: 이 분석 세션은 문서와 프로젝트 지침만 추가/수정한다. src/pom.xml은 수정하지 않는다.
  • 조사 방식: 파일 목록, 컨트롤러, 매퍼, JSP, 설정 파일을 rg와 라인 번호 기준으로 확인했다.

요약

  • 보안 기초는 비교적 견고하다. MyBatis 매퍼는 동적 ${} 조립 없이 #{} 바인딩을 쓰고, 비밀번호는 PBKDF2-SHA256 210,000회 반복으로 저장한다.
  • 주요 보안 갭은 POST /login, POST /signup에 CSRF 검증이 없는 점이다. 다른 주요 상태 변경 API는 CsrfTokens.isValid를 적용하고 있다.
  • 파일 업로드와 WebGL asset 제공 경로는 normalize/startsWith 검사를 반복 적용하고, zip-slip 및 XSS 방어도 일관된 편이다.
  • 구조적 부채는 서비스 레이어 부재, fat controller, 프로토타입 잔재(abstracts, header.jspf, GameCatalog), 실질 테스트 부족이다.
  • 좋아요/댓글은 DB 매퍼와 삭제 연계는 있으나, 상세 화면은 localStorage만 사용해 서버 영속화가 미완성이다.

1. 아키텍처 분석

A1. 현재 구조는 Controller + Mapper 중심이다

  • Spring MVC JSP 뷰 구조는 spring.mvc.view.prefix와 suffix 설정에 고정되어 있다. 근거: src/main/resources/application.properties:5, src/main/resources/application.properties:6
  • 홈/로그인/회원가입/프로필 라우팅은 WebMvcController가 담당한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/WebMvcController.java:57, src/main/java/com/pandoli365/bibimbap/controller/WebMvcController.java:64, src/main/java/com/pandoli365/bibimbap/controller/WebMvcController.java:75, src/main/java/com/pandoli365/bibimbap/controller/WebMvcController.java:88
  • 회원가입, 로그인, 프로필 변경은 UserController가 요청 검증, DB 접근, 세션 저장, 응답 생성을 함께 수행한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:65, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:118, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:173, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:209, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:494
  • 게임 등록/수정/삭제도 컨트롤러가 검증, 권한 확인, 매퍼 호출을 직접 수행한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:41, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:158, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:222
  • 모집글 등록도 동일 패턴이다. 근거: src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:49, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:73, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:116

영향: 단기 구현 속도는 빠르지만, 보안 검증과 도메인 규칙이 컨트롤러마다 흩어진다. CSRF 누락처럼 특정 엔드포인트만 빠지는 회귀가 발생하기 쉽다.

A2. 정적 리소스 제공은 프로필과 게임 asset이 분리되어 있다

  • 프로필 이미지는 UploadResourceConfig에서 /profile/**로 노출한다. 근거: src/main/java/com/pandoli365/bibimbap/config/UploadResourceConfig.java:19, src/main/java/com/pandoli365/bibimbap/config/UploadResourceConfig.java:22
  • WebGL 게임 asset은 별도 컨트롤러가 /game/{gameUuid}/**를 직접 처리한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:31, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:43, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:50
  • WebGL 응답에는 X-Content-Type-Options와 CSP가 설정된다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:59, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:60, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:65

영향: 업로드 asset을 일반 정적 리소스와 분리한 점은 좋다. 단, 사용자가 만든 WebGL을 같은 사이트 origin에서 iframe으로 실행하므로 장기적으로 별도 asset origin 정책을 결정해야 한다.

A3. 프로토타입 잔재가 남아 있다

  • GameController는 DB에 게임이 없으면 GameCatalog로 fallback한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:103, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:111, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:116
  • GameCatalog는 빈 배열만 가진다. 근거: src/main/java/com/pandoli365/bibimbap/game/GameCatalog.java:8, src/main/java/com/pandoli365/bibimbap/game/GameCatalog.java:12, src/main/java/com/pandoli365/bibimbap/game/GameCatalog.java:18
  • header.jspf는 Spring Security taglib와 ${_csrf}를 전제로 하지만, 실제 화면은 /WEB-INF/views/header.jsp를 include한다. 근거: src/main/webapp/WEB-INF/jsp/fragments/header.jspf:1, src/main/webapp/WEB-INF/jsp/fragments/header.jspf:2, src/main/webapp/WEB-INF/jsp/fragments/header.jspf:14, src/main/webapp/WEB-INF/views/login.jsp:203, src/main/webapp/WEB-INF/views/signup.jsp:201
  • abstracts.Service는 현재 컨트롤러 흐름과 별개인 수동 인증/요청 검증 추상화다. 근거: src/main/java/com/pandoli365/bibimbap/abstracts/Service.java:5, src/main/java/com/pandoli365/bibimbap/abstracts/Service.java:7, src/main/java/com/pandoli365/bibimbap/abstracts/Service.java:11, src/main/java/com/pandoli365/bibimbap/abstracts/Service.java:12

영향: 죽은 코드가 보안 로직처럼 보이는 상태로 남아 있으면 새 구현자가 잘못 재사용할 수 있다. 삭제 전 참조 검색과 동작 확인이 필요하다.

2. 보안 분석

S1. SQL injection 표면은 현재 스캔 범위에서 발견되지 않았다

  • src/main/java/com/pandoli365/bibimbap/mapper와 controller 패키지에서 MyBatis 동적 치환 ${} 사용은 발견되지 않았다.
  • 검색 쿼리도 ILIKE CONCAT('%', #{query}, '%')로 바인딩한다. 근거: src/main/java/com/pandoli365/bibimbap/mapper/GamesMapper.java:85, src/main/java/com/pandoli365/bibimbap/mapper/GamesMapper.java:86, src/main/java/com/pandoli365/bibimbap/mapper/GamesMapper.java:87
  • 주요 insert/update/select는 #{} 바인딩을 사용한다. 근거: src/main/java/com/pandoli365/bibimbap/mapper/UsersMapper.java:25, src/main/java/com/pandoli365/bibimbap/mapper/UsersMapper.java:39, src/main/java/com/pandoli365/bibimbap/mapper/UserAuthIdentitiesMapper.java:47, src/main/java/com/pandoli365/bibimbap/mapper/UserAuthIdentitiesMapper.java:67, src/main/java/com/pandoli365/bibimbap/mapper/GamesMapper.java:128, src/main/java/com/pandoli365/bibimbap/mapper/RecruitPostsMapper.java:91

판정: 현재 코드 스캔 기준 SQLi 직접 표면은 0이다. 동적 정렬/테이블명 기능을 추가할 때도 ${}를 금지하는 규칙을 유지해야 한다.

S2. 비밀번호 저장 방식은 강한 편이다

  • 최소 비밀번호 길이와 PBKDF2 파라미터가 상수로 정의되어 있다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:45, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:46, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:47, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:48
  • 신규 비밀번호는 salt 생성 후 pbkdf2_sha256$iterations$salt$hash 형식으로 저장된다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:542, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:543, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:546
  • 검증은 저장된 iteration/salt를 읽고 MessageDigest.isEqual로 비교한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:551, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:558, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:561, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:562
  • 알고리즘은 PBKDF2WithHmacSHA256이다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:568, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:571

판정: 현재 구현은 기본 수준 이상이다. 향후에는 로그인 실패 제한, 비밀번호 재해시 정책, 계정 잠금 정책을 별도 개선으로 다루면 된다.

S3. CSRF 방어는 전반적으로 있으나 login/signup에 구멍이 있다

  • CSRF 토큰은 세션에 저장되고 32바이트 난수로 생성된다. 근거: src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:20, src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:28, src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:31
  • 검증은 X-CSRF-Token 헤더 또는 _csrf 파라미터를 허용한다. 근거: src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:35, src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:44, src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:46, src/main/java/com/pandoli365/bibimbap/security/CsrfTokens.java:48
  • JSP 공통 초기화는 meta token과 JS header helper를 제공한다. 근거: src/main/webapp/WEB-INF/views/theme-init.jsp:5, src/main/webapp/WEB-INF/views/theme-init.jsp:7, src/main/webapp/WEB-INF/views/theme-init.jsp:19, src/main/webapp/WEB-INF/views/theme-init.jsp:27
  • 로그아웃, 프로필 변경, 게임 업로드, 게임 등록/수정/삭제, 모집글 등록은 CSRF 검증을 한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:164, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:179, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:215, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:59, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:106, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:170, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:53, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:171, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:227, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:65
  • POST /signup은 컨트롤러 진입 후 CSRF 검증 없이 입력 검증과 DB 조회를 시작한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:65, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:75, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:87
  • POST /login도 CSRF 검증 없이 인증 로직과 세션 갱신으로 이어진다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:118, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:126, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:151, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:152
  • 로그인/회원가입 fetch 요청은 현재 CSRF header helper를 쓰지 않는다. 근거: src/main/webapp/WEB-INF/views/login.jsp:277, src/main/webapp/WEB-INF/views/login.jsp:279, src/main/webapp/WEB-INF/views/login.jsp:284, src/main/webapp/WEB-INF/views/signup.jsp:291, src/main/webapp/WEB-INF/views/signup.jsp:293, src/main/webapp/WEB-INF/views/signup.jsp:297

판정: MED. 공격자가 피해자의 브라우저에서 원치 않는 로그인 상태 전환 또는 회원가입 요청을 유도할 수 있다. 기존 CSRF 헬퍼가 있어 수정 범위는 작다.

S4. 업로드와 파일 경로 방어는 일관되어 있다

  • 게임 파일 업로드는 CSRF와 로그인 세션을 먼저 확인한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:59, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:62
  • WebGL zip 업로드는 zip 여부, 로그인, target path boundary를 확인한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:106, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:113, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:121, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:127, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:128
  • zip entry 개수와 압축 해제 총량 제한이 있다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:40, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:41, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:261, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:297
  • zip-slip 방어는 targetDir.resolve(entry.getName()).normalize()startsWith(targetDir)로 수행된다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:266, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:267, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:268
  • 썸네일/프로필 이미지는 크기와 확장자/Content-Type 검사를 한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:181, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:186, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:228, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:233
  • 프로필 저장 경로도 root boundary를 검사한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:246, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:248, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:254, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:256
  • 게임 asset 조회도 URI decode 후 normalize/startsWith를 수행한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:91, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:92, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:101, src/main/java/com/pandoli365/bibimbap/controller/api/GameAssetController.java:102

판정: 현재 방어는 좋다. 다만 운영 설정에서 multipart 상한이 1GB로 높아 실제 서버 메모리/디스크 정책과 맞는지 재검토해야 한다. 근거: src/main/resources/application.properties:15, src/main/resources/application.properties:16, src/main/resources/application.properties:17, src/main/resources/application.properties:18

S5. XSS 방어는 서버 렌더와 클라이언트 렌더 모두 대체로 안전하다

  • 게임 상세 주요 출력값은 HtmlUtils.htmlEscape로 이스케이프한다. 근거: src/main/webapp/WEB-INF/views/game-detail.jsp:6, src/main/webapp/WEB-INF/views/game-detail.jsp:7, src/main/webapp/WEB-INF/views/game-detail.jsp:10, src/main/webapp/WEB-INF/views/game-detail.jsp:21
  • 홈 검색어와 게임 카드 출력도 escape를 적용한다. 근거: src/main/webapp/WEB-INF/views/index.jsp:21, src/main/webapp/WEB-INF/views/index.jsp:466, src/main/webapp/WEB-INF/views/index.jsp:506, src/main/webapp/WEB-INF/views/index.jsp:507, src/main/webapp/WEB-INF/views/index.jsp:514
  • 댓글 localStorage 렌더링은 textContent를 사용한다. 근거: src/main/webapp/WEB-INF/views/game-detail.jsp:951, src/main/webapp/WEB-INF/views/game-detail.jsp:958, src/main/webapp/WEB-INF/views/game-detail.jsp:969
  • 프로필 아바타 URL은 출력 전에 escape한다. 근거: src/main/webapp/WEB-INF/views/header.jsp:8, src/main/webapp/WEB-INF/views/header.jsp:11, src/main/webapp/WEB-INF/views/header.jsp:219
  • 외부 Git URL은 http:// 또는 https://만 허용한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:282, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:287, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:288

판정: 현재 XSS 방어는 일관된 편이다. 서버 댓글 영속화를 붙일 때도 JSP 직접 출력 대신 escape/textContent 원칙을 유지해야 한다.

S6. 세션 보안은 기본은 있으나 쿠키 하드닝 설정이 없다

  • 로그인 성공 시 request.changeSessionId()로 세션 고정 공격을 줄인다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:151, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:152
  • 로그인 유지 옵션은 세션 만료 시간을 조정한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:49, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:50, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:317, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:318
  • application.properties에는 session cookie HttpOnly, Secure, SameSite 설정이 없다. 근거: src/main/resources/application.properties:1, src/main/resources/application.properties:27

판정: B4에서 운영 프로필 기준 쿠키 하드닝을 추가한다.

S7. 의존성/로깅 운영 리스크가 있다

  • Spring Boot 버전이 SNAPSHOT이다. 근거: pom.xml:29
  • snapshot repository와 pluginRepository가 활성화되어 있다. 근거: pom.xml:200, pom.xml:202, pom.xml:210, pom.xml:212
  • MyBatis TRACE 로그가 켜져 있다. 근거: src/main/resources/application.properties:25, src/main/resources/application.properties:26, src/main/resources/application.properties:27

판정: 배포 안정성과 보안 재현성을 위해 release 버전 고정, CVE 스캔, 운영 로깅 레벨 분리가 필요하다.

3. 품질 분석

Q1. 테스트가 실질 보안/도메인 동작을 검증하지 않는다

  • 기본 테스트는 context load뿐이다. 근거: src/test/java/com/pandoli365/bibimbap/BibimbapApplicationTests.java:6, src/test/java/com/pandoli365/bibimbap/BibimbapApplicationTests.java:9, src/test/java/com/pandoli365/bibimbap/BibimbapApplicationTests.java:10
  • DB 업데이트 쿼리 생성 테스트는 surefire에서 제외되어 일반 테스트로 돌지 않는다. 근거: pom.xml:127, pom.xml:130, pom.xml:131
  • CSRF, 로그인, 업로드 zip-slip, XSS 렌더링 회귀 테스트가 없다. 근거: 현재 src/test/java/com/pandoli365/bibimbap/BibimbapApplicationTests.java:9 외 애플리케이션 동작 테스트가 확인되지 않는다.

영향: 보안 개선 PR마다 최소 MockMvc 테스트를 붙여 회귀를 잡아야 한다.

Q2. 컨트롤러에 중복 helper가 많다

  • 세션 사용자 ID 추출이 여러 컨트롤러에 반복된다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:325, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:222, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:291, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:155
  • trim helper도 반복된다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:317, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:173

영향: 정책 변경 시 수정 누락 위험이 높다. 서비스/유틸 레이어 도입은 보안 변경 뒤 별도 PR로 다루는 편이 안전하다.

Q3. 설정 상한과 실제 검증 상한이 어긋난다

  • Spring multipart 상한은 1GB다. 근거: src/main/resources/application.properties:15, src/main/resources/application.properties:16
  • WebGL zip 압축 해제 총량 제한은 512MB다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:40, src/main/java/com/pandoli365/bibimbap/controller/api/GameUploadController.java:297

영향: 애플리케이션 레벨에서 거절하기 전 서버가 큰 요청을 받아야 한다. 운영 인프라 제한과 함께 조정해야 한다.

4. 도메인 분석

D1. 회원가입 문서는 다중 provider를 설명하지만 구현은 email provider 중심이다

  • 문서는 guest, google, email, kakao, naver, github, apple를 설명한다. 근거: docs/user-signup-schema.md:32
  • 현재 컨트롤러는 PROVIDER_EMAIL 상수로 email provider를 사용한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:42, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:87, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:100
  • 회원가입 JSP에는 provider hidden input이 있지만 컨트롤러는 해당 파라미터를 받지 않는다. 근거: src/main/webapp/WEB-INF/views/signup.jsp:216, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:67, src/main/java/com/pandoli365/bibimbap/controller/api/UserController.java:72

영향: 문서와 구현 간 목표 차이가 있다. 소셜/게스트 가입을 실제 기능으로 만들지, 문서를 email-only로 조정할지 결정해야 한다.

D2. 게임 등록/수정/삭제는 서버 영속화되어 있다

  • 게임 생성은 gamesMapper.addGame으로 저장한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:80, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:90, src/main/java/com/pandoli365/bibimbap/mapper/GamesMapper.java:117
  • 게임 수정은 작성자 확인 후 gamesMapper.updateGame을 호출한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:179, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:183, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:212
  • 게임 삭제는 댓글 soft delete와 좋아요 삭제를 함께 수행한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:243, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:244, src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java:245

영향: 게임 CRUD는 서버 중심으로 동작한다. 좋아요/댓글만 연결되지 않은 상태다.

D3. 좋아요/댓글은 DB 모델은 있으나 상세 화면은 localStorage 전용이다

  • 좋아요 매퍼는 존재한다. 근거: src/main/java/com/pandoli365/bibimbap/mapper/GameLikesMapper.java:10, src/main/java/com/pandoli365/bibimbap/mapper/GameLikesMapper.java:24, src/main/java/com/pandoli365/bibimbap/mapper/GameLikesMapper.java:36
  • 댓글 매퍼는 존재한다. 근거: src/main/java/com/pandoli365/bibimbap/mapper/GameCommentsMapper.java:10, src/main/java/com/pandoli365/bibimbap/mapper/GameCommentsMapper.java:27, src/main/java/com/pandoli365/bibimbap/mapper/GameCommentsMapper.java:41
  • 상세 화면 좋아요는 localStorage map만 갱신한다. 근거: src/main/webapp/WEB-INF/views/game-detail.jsp:811, src/main/webapp/WEB-INF/views/game-detail.jsp:812, src/main/webapp/WEB-INF/views/game-detail.jsp:817, src/main/webapp/WEB-INF/views/game-detail.jsp:830, src/main/webapp/WEB-INF/views/game-detail.jsp:904, src/main/webapp/WEB-INF/views/game-detail.jsp:906
  • 상세 화면 댓글도 localStorage에 저장하고 DOM으로 렌더링한다. 근거: src/main/webapp/WEB-INF/views/game-detail.jsp:813, src/main/webapp/WEB-INF/views/game-detail.jsp:913, src/main/webapp/WEB-INF/views/game-detail.jsp:928, src/main/webapp/WEB-INF/views/game-detail.jsp:994, src/main/webapp/WEB-INF/views/game-detail.jsp:1002

영향: 사용자는 브라우저를 바꾸면 좋아요/댓글을 잃는다. 서버 연결 시 익명 허용 여부, 남용 방지, 삭제 권한, CSRF 정책을 먼저 확정해야 한다.

D4. 모집글은 서버 영속화되어 있다

  • 목록, 작성, 상세 라우트가 존재한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:35, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:49, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:145
  • 작성 시 enum-like set과 길이 검증을 수행한다. 근거: src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:25, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:26, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:27, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:80, src/main/java/com/pandoli365/bibimbap/controller/RecruitController.java:112
  • 매퍼는 visible/not-deleted 조건으로 조회한다. 근거: src/main/java/com/pandoli365/bibimbap/mapper/RecruitPostsMapper.java:67, src/main/java/com/pandoli365/bibimbap/mapper/RecruitPostsMapper.java:68, src/main/java/com/pandoli365/bibimbap/mapper/RecruitPostsMapper.java:74

영향: 모집글 쪽은 최소 CRUD 흐름이 게임 CRUD와 비슷한 수준으로 정리되어 있다.

후속 작업 후보