167 lines
12 KiB
Markdown
167 lines
12 KiB
Markdown
---
|
|
phase: research
|
|
agent: research-advisor
|
|
agent_version: 2
|
|
generated_at: 2026-06-29T09:04:35Z
|
|
concerns: []
|
|
source_confidence: high
|
|
workers_spawned: 2
|
|
---
|
|
|
|
# 조사 결과 — B2 dead code 삭제 안전성 + B4 의존성 업그레이드 사실조사
|
|
|
|
## 주제
|
|
bibimbap (Java21/SpringBoot/JSP/MyBatis WAR) 의 두 작업트랙:
|
|
- B2: dead code(abstracts 패키지, GameCatalog, header.jspf) 삭제 안전성
|
|
- B4: Spring Boot 최신 stable 버전 + OWASP Dependency-Check maven plugin(오프라인) 도입을 위한 사실조사
|
|
|
|
전부 read-only. 설계·구현·코드수정 없음.
|
|
|
|
---
|
|
|
|
## 트랙 B2 — dead code 삭제 안전성 (코드 사실 / 조사포인트 1)
|
|
|
|
### 포인트 1-A: abstracts 패키지
|
|
- 경로: `src/main/java/com/pandoli365/bibimbap/abstracts/`
|
|
- 요약: 4개 파일 존재 — `ErrorResult.java`, `Request.java`, `Result.java`, `Service.java`.
|
|
- `ErrorResult` extends `Result` (status만 받는 생성자)
|
|
- `Request` abstract, `IsReceivedAllField()` 기본 true 반환
|
|
- `Result` abstract, status/message 필드
|
|
- `Service<Req extends Request, Res extends Result>` 제네릭 abstract, `ChackService()`/`StartService()`
|
|
- 외부 참조 확인:
|
|
- `rg "bibimbap\.abstracts|abstracts\."` → 4개 파일 자기 자신의 package 선언(라인1)만 hit. 패키지 밖 import/참조 **0건**.
|
|
- **(advisor 보강)** `rg "extends (Service|Request|Result)|new ErrorResult|StartService|ChackService|IsReceivedAllField"` → hit는 전부 abstracts 패키지 **내부**의 정의/상호참조(Service.java가 ErrorResult/Request를 쓰고, ErrorResult가 Result를 extends)뿐. abstracts **외부**에서 `extends Service`/`extends Request`/`extends Result` 하는 구체 클래스 **0건**.
|
|
- 관련 파일:라인:
|
|
- `abstracts/ErrorResult.java:3` — `public class ErrorResult extends Result`
|
|
- `abstracts/Service.java:5` — `public abstract class Service<Req extends Request, Res extends Result>`
|
|
- `abstracts/Service.java:13,15` — `(Res) new ErrorResult(401)` (패키지 내부 사용)
|
|
- 신뢰도: 확인됨 (rg 전수 + 직접 코드읽기 + advisor 상속 키워드 보강검증)
|
|
|
|
### 포인트 1-B: GameCatalog.java 참조
|
|
- 경로: `src/main/java/com/pandoli365/bibimbap/game/GameCatalog.java`
|
|
- 요약: `rg "GameCatalog"` 결과 참조 파일 2개뿐 — GameCatalog.java 자신 + GameController.java. 다른 컨트롤러·서비스 참조 **0건**.
|
|
- 관련 파일:라인:
|
|
- `controller/api/GameController.java:5` — `import com.pandoli365.bibimbap.game.GameCatalog;`
|
|
- `controller/api/GameController.java:150,155,157-162` — gameDetail() fallback 블록에서 사용
|
|
- 신뢰도: 확인됨
|
|
|
|
### 포인트 1-C: header.jspf include 여부
|
|
- 경로: `src/main/webapp/WEB-INF/jsp/fragments/header.jspf`
|
|
- 요약: `rg "header\.jspf|fragments/header"` → **0 hit**. `rg "include.*header"` → 0 hit (이 패턴으로는). header.jsp를 include하는 JSP는 총 **23개**이며 전부 `<jsp:include page="/WEB-INF/views/header.jsp"/>` 형태로 통일. `header.jspf`를 include하는 사례 **0건**.
|
|
- 관련 파일:라인: game-detail.jsp:1201, index.jsp:727, login.jsp:205 등 23개 전부 `/WEB-INF/views/header.jsp`
|
|
- 신뢰도: 확인됨
|
|
|
|
### 포인트 1-D: GameController.gameDetail() fallback 로직 (404 변경용 정확 라인)
|
|
- 경로: `src/main/java/com/pandoli365/bibimbap/controller/api/GameController.java`
|
|
- 요약: `gameDetail()` 메서드(137~173라인) 현재 흐름:
|
|
- **140~148**: `gamesMapper.getGame(id)` DB조회 → `game != null`이면 정상 뷰 반환
|
|
- **150**: `game == null` 진입. `if (id < Integer.MIN_VALUE || id > Integer.MAX_VALUE || !GameCatalog.isValidId((int) id))`
|
|
- **151**: 위 조건 true이면 `return "redirect:/";`
|
|
- **154~172**: `GameCatalog.isValidId()` true이면 `GameCatalog.toIndex(intId)`로 인덱스 구해 `NAMES/CREATORS/LIKE_COUNTS/CREATOR_NOTES/GIT_URLS` 배열값을 model 적재 후 `"game-detail"` 뷰 반환
|
|
- 현재 코드 사실: **DB에 없는 game ID에 대해 404를 반환하는 분기는 이 메서드에 존재하지 않는다.** GameCatalog.isValidId 통과 여부에 따라 (a) fallback 정적 뷰("game-detail") 또는 (b) 루트 redirect("redirect:/") 둘 중 하나로 귀결.
|
|
- "GameCatalog 제거 후 없는 게임 ID를 404로 바꾸려면 고쳐야 할 줄" (사실 식별, 설계 아님):
|
|
- 150~151의 GameCatalog.isValidId 분기 + 154~172의 GameCatalog 기반 fallback 블록 전체가 제거 대상. game==null인 경로(150 진입 이후 전부)를 404 응답으로 대체해야 함. 즉 라인 150~172가 변경 영역.
|
|
- 신뢰도: 확인됨
|
|
|
|
---
|
|
|
|
## 트랙 B4 — Spring Boot / OWASP DC 버전 + 설정 (조사포인트 2,3,4)
|
|
|
|
### 포인트 2: Spring Boot 3.5.x 최신 stable(GA) 버전
|
|
- 요약: 현재 pom의 `3.5.14-SNAPSHOT`은 미출시 스냅샷. 3.5.x 계열 최신 **GA = 3.5.16** (2026-06-25 출시).
|
|
- v3.5.14 GA 2026-04-23 / v3.5.15 GA 2026-06-10 / v3.5.16 GA 2026-06-25(최신)
|
|
- 3.5.x 위로 4.0.x/4.1.x 별개 계열 존재(이번 트랙 범위 밖)
|
|
- 출처:
|
|
- https://spring.io/blog/category/releases — "Spring Boot 3.5.16 available now" (2026-06-25)
|
|
- https://github.com/spring-projects/spring-boot/releases — v3.5.16/3.5.15/3.5.14 확인
|
|
- 신뢰도: 확인됨 (spring.io 1차 + GitHub releases)
|
|
|
|
### 포인트 3-A: OWASP dependency-check-maven 최신 버전
|
|
- 요약: **12.2.2** (최신 GA).
|
|
- 동명 disambiguation: 원 저장소 `jeremylong/DependencyCheck`는 2025-09-27 아카이브됨. 관리 이관처 `dependency-check/DependencyCheck`. **Maven groupId는 동일하게 `org.owasp` 유지** — central.sonatype.com에서 `org.owasp:dependency-check-maven:12.2.2` latest로 확인됨(다른 groupId 아님).
|
|
- 현재 pom.xml에 OWASP DC plugin 없음(검색 0건).
|
|
- 출처:
|
|
- https://central.sonatype.com/artifact/org.owasp/dependency-check-maven/versions — 12.2.2 latest
|
|
- https://github.com/dependency-check/DependencyCheck/releases — v12.2.2 GA
|
|
- https://github.com/jeremylong/DependencyCheck — 이관 안내(2025-09-27 아카이브)
|
|
- 신뢰도: 확인됨 (Maven Central 1차 + GitHub releases)
|
|
|
|
### 포인트 3-B: 오프라인/NVD 무의존 설정 방법
|
|
- 요약(공식 configuration 문서 발췌 기준 — 전수 옵션 목록 아님):
|
|
- `autoUpdate` (기본 true): **false** 설정 시 NVD 자동 업데이트 비활성화 — 오프라인 핵심
|
|
- `dataDirectory` (기본 `~/.m2/.../dependency-check-data/`): 사전 다운로드한 로컬 NVD 캐시 위치 지정
|
|
- `nvdApiKey` (선택): **없어도 동작 가능**. 단 키 없으면 API 요청 간격이 8000ms로 늘어남(온라인 업데이트 시에만 영향, autoUpdate=false면 무관)
|
|
- `nvdDatafeedUrl`: 내부 NVD 미러 서버 지정(에어갭 지원). 별도 인프라 필요 → 상세는 범위 밖
|
|
- `failBuildOnCVSS` (기본 11=사실상 비활성, 0-10 범위): 특정 CVSS 이상 시 빌드 실패
|
|
- `skipProvidedScope` (기본 false): true면 provided scope 의존성 분석 생략
|
|
- 명시적 `--offline` 플래그는 **없음**. 오프라인 패턴 = `autoUpdate=false` + 사전채워진 `dataDirectory`. 한번 온라인에서 데이터 받아두면 이후 오프라인 재사용 가능.
|
|
- pom plugin 설정 예시(오프라인 친화, advisor가 검토할 후보 스니펫):
|
|
```xml
|
|
<plugin>
|
|
<groupId>org.owasp</groupId>
|
|
<artifactId>dependency-check-maven</artifactId>
|
|
<version>12.2.2</version>
|
|
<configuration>
|
|
<autoUpdate>false</autoUpdate>
|
|
<dataDirectory>${user.home}/.m2/repository/org/owasp/dependency-check-data</dataDirectory>
|
|
<failBuildOnCVSS>7</failBuildOnCVSS>
|
|
<skipProvidedScope>true</skipProvidedScope>
|
|
</configuration>
|
|
</plugin>
|
|
```
|
|
- 출처: https://jeremylong.github.io/DependencyCheck/dependency-check-maven/configuration.html
|
|
- 신뢰도: 확인됨 (옵션 존재·역할). 단 `failBuildOnCVSS=7`/`skipProvidedScope=true`의 구체 값 선택은 advisor 설계 결정(조사 산출 아님). 옵션 목록은 "공식 문서 발췌"이지 "전수 열거"가 아님.
|
|
|
|
### 포인트 4: 현 설정파일 정확 라인 (코드 사실)
|
|
|
|
#### 4-A: pom.xml 구조 (`/Users/wemadeplay/workspace/stz/bibimbap/pom.xml`)
|
|
- `spring-boot.version` property: **라인 29**, 값 `3.5.14-SNAPSHOT`
|
|
- `<repositories>` 블록: **라인 210~219** — spring-snapshots 1개(`https://repo.spring.io/snapshot`, releases disabled)
|
|
- `<pluginRepositories>` 블록: **라인 220~229** — spring-snapshots 1개(동일 URL, releases disabled)
|
|
- `<build><pluginManagement><plugins>`: 라인 100~155 — 9개 플러그인(clean/compiler/deploy/failsafe/install/resources/surefire/war/spring-boot)
|
|
- `<build><plugins>` (실행): **라인 157~208** — spring-boot-maven-plugin(157~169) + maven-compiler-plugin(170~207) 2개만. **OWASP plugin 추가 위치 = 이 블록 내**.
|
|
- profiles 빌드: dev(256~266), live(293~302)에 각각 spring-boot-maven-plugin profile용 추가
|
|
- 신뢰도: 확인됨
|
|
|
|
#### 4-B: application.properties (`src/main/resources/application.properties`, 31라인)
|
|
- `spring.profiles.active`: **라인 1** — `@app.profile@` (Maven 필터링 치환)
|
|
- 세션 쿠키 설정(`server.servlet.session.cookie.*`): **0건 (없음)**
|
|
- `logging.level.org.apache.ibatis`: **라인 30** — `TRACE`
|
|
- multipart: **라인 15~17** — `spring.servlet.multipart.max-file-size=1GB`, `max-request-size=1GB`, `server.tomcat.max-http-form-post-size=1GB`
|
|
- (참고) 라인 21에 `spring.config.import`로 profile별 db.properties 로드
|
|
- 신뢰도: 확인됨
|
|
|
|
#### 4-C: profile별 properties 파일 존재 여부
|
|
- `application-dev.properties` / `application-live.properties` 형식 파일: **존재하지 않음**
|
|
- 대신 디렉토리 기반:
|
|
- `dev/db.properties` (존재, 8라인) + `dev/db.properties.example`
|
|
- `live/db.properties.example`만 존재 — **`live/db.properties`는 없음**
|
|
- `dev/db.properties` 내용: postgresql driver, url(localhost:5433/bibimbap?currentSchema=dev), username=bibimbap, password=change_me_local_dev, app.upload.game-storage-path, app.webgl.asset-origin(빈값), app.webgl.frame-ancestors=self
|
|
- 사실: B4가 "application-dev.properties/application-live.properties 신규/수정 대상"으로 가정한다면, **현재 그런 파일은 없고** profile 설정은 `dev/`·`live/` 디렉토리 + `spring.config.import` 패턴으로 관리됨. → 가정과 현행 구조 불일치(아래 미해결 참조)
|
|
- 신뢰도: 확인됨
|
|
|
|
---
|
|
|
|
## 종합 판단
|
|
|
|
### 삭제 안전성 판정 (B2)
|
|
| 대상 | 외부 참조 | 삭제 안전성 |
|
|
|---|---|---|
|
|
| `abstracts/` 패키지 4파일 | 패키지 외부 0건 (상속 구체클래스 0, import 0) | **삭제 안전** (컴파일·런타임 파손 없음) |
|
|
| `GameCatalog.java` | GameController.gameDetail()만 참조 | **GameController 동시수정 필요** — fallback 로직(라인 150~172) 제거/404대체 후라야 안전 |
|
|
| `header.jspf` | include 0건 | **삭제 안전** (어떤 JSP도 참조 안 함, 전부 /WEB-INF/views/header.jsp 사용) |
|
|
|
|
### 확정 버전값 (B4)
|
|
| 항목 | 확정값 | 신뢰도 |
|
|
|---|---|---|
|
|
| Spring Boot 3.5.x 최신 GA | **3.5.16** | 확인됨 |
|
|
| OWASP dependency-check-maven 최신 GA | **12.2.2** (groupId `org.owasp` 유지) | 확인됨 |
|
|
|
|
전 항목 1차 출처(spring.io / Maven Central / 프로젝트 코드 직접읽기)로 확인됨 → `source_confidence: high`. 차단 출처 fallback 없음.
|
|
|
|
## 미해결
|
|
- **B4 가정 vs 현행 구조 불일치**: 작업트랙 B4 설명이 "application-dev.properties / application-live.properties 신규/수정 대상"이라 가정하나, 현 프로젝트는 그런 파일이 없고 `dev/db.properties`·`live/db.properties`(+ `spring.config.import`) 패턴을 쓴다. 설정 추가를 어느 파일에 넣을지는 design-advisor가 현행 패턴 기준으로 재결정해야 함. (조사로 사실 확인 완료, 결정은 다운스트림)
|
|
- `live/db.properties` 부재 — live profile 활성 시 어디서 DB 설정을 받는지(배포 시 주입 등)는 이번 조사 범위 밖.
|
|
- GameCatalog.java의 배열 실제 값(NAMES/CREATORS 등 fallback이 제공하던 게임 목록)은 미조회 — 404 전환 시 사라지는 정적 게임 목록의 내용·개수가 필요하면 별도 조사.
|
|
- `nvdDatafeedUrl` 내부 미러 상세 구성은 별도 인프라 필요로 범위 밖.
|