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:116GameCatalog는 빈 배열만 가진다. 근거: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:18header.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:201abstracts.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:87POST /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 cookieHttpOnly,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에는
providerhidden 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 - 상세 화면 좋아요는
localStoragemap만 갱신한다. 근거: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와 비슷한 수준으로 정리되어 있다.
후속 작업 후보
- B1:
login/signupCSRF 검증 추가. 자세한 실행 항목은 보안 개선 체크리스트를 따른다. - B2: 프로토타입 dead code 제거. 자세한 실행 항목은 보안 개선 체크리스트를 따른다.
- B3: 좋아요/댓글 서버 영속화 연결. 자세한 실행 항목은 보안 개선 체크리스트를 따른다.
- B4: Spring Boot SNAPSHOT 고정, 세션 쿠키 하드닝, 의존성 CVE 스캔. 자세한 실행 항목은 보안 개선 체크리스트를 따른다.