451 lines
42 KiB
Markdown
451 lines
42 KiB
Markdown
---
|
||
title: branch / feature-static-analysis-quality-contract
|
||
source_type: branch-note
|
||
status: raw
|
||
branch: feature-static-analysis-quality-contract
|
||
parent_branch:
|
||
related_projects: [ca-skeleton, ca-tmpl]
|
||
governing_docs: [wiki/projects/ca-tmpl/devops-ci-supply-chain-dx]
|
||
tags: [branch, ca-skeleton, ci, static-analysis, build]
|
||
created: 2026-06-15
|
||
target_merge:
|
||
status_label: review
|
||
id: BR-CA-SKELETON-OPERATIONAL-CONTRACT-059
|
||
kind: project-work-item
|
||
project: ca-skeleton-operational-contract
|
||
work_item: WI-CA-SKELETON-OPERATIONAL-CONTRACT-059
|
||
inherits: [DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1, DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-TEST-001@1]
|
||
refines: []
|
||
overrides: []
|
||
depends_on: [WI-CA-SKELETON-OPERATIONAL-CONTRACT-028, WI-CA-SKELETON-OPERATIONAL-CONTRACT-029, WI-CA-SKELETON-OPERATIONAL-CONTRACT-018]
|
||
contract_packet: 1
|
||
contract_packet_sha256: 0c95c259df15379beb8e37dc590b41edb18028dd131f37b90fd59959d8d99163
|
||
---
|
||
|
||
# branch: feature-static-analysis-quality-contract
|
||
|
||
> Layer: `raw/branch-notes/` — 단일 브랜치의 **TODO·결정·진행 기록**. 머지/종료 후 verified 결과는 `/ingest`로 `wiki/projects/`에 추출. 원본은 raw에 영구 보관.
|
||
> `status_label`: `in-progress` | `review` | `merged` | `abandoned`
|
||
> **계층 표기**: "root branch" 라는 별도 개념은 없음. project 의 직접 자식 branch 는 `parent_branch:` 를 **비워두고** `related_projects` 만 채움. 다른 branch 의 자식이면 `parent_branch: <부모 branch 이름>` 명시 + `## Parent` 섹션의 부모 wikilink 필수.
|
||
|
||
<!-- section-id: branch-parent -->
|
||
## 부모 (필수)
|
||
|
||
> 이 branch 가 어느 작업 묶음에 속하는지. 모든 branch 는 예외 없이 upward link 보유.
|
||
|
||
**Project 의 직접 자식 branch** (`parent_branch:` 비어있음):
|
||
|
||
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl 운영 계약 canonical SSOT. 본 branch 는 §35-E 신규 branch 권고 **우선순위 #2** (`Implementation Coverage Checklist` C 영역 L2051: "Static analysis / code quality baseline — tool 선택 + 룰셋") 의 전개.
|
||
|
||
선택 (인접 sibling — 경계 확정용, 본 branch 가 *침범하지 않음*):
|
||
|
||
- [[raw/branch-notes/feature-ci-quality-gates-contract]] — gate *threshold* + blocking/warning 정책 + gate 순서 owner. 본 branch 는 그 `format / lint` gate row 의 `(toolchain)` 공석을 *채우는* producer.
|
||
- [[raw/branch-notes/feature-architecture-enforcement-rules]] — ArchUnit suite owner. formatter/style lint 과 SonarQube custom rule 은 그 branch 의 **명시적 out-of-scope** → 본 branch 가 받음.
|
||
- [[raw/branch-notes/feature-build-release-supply-chain-contract]] — dependency locking / SBOM / Cosign / CVE 차단 owner. 본 branch 의 tool JAR 버전은 그 locking 메커니즘에 *편승*만 함.
|
||
- [[raw/branch-notes/feature-dependency-vulnerability-management-contract]] — CVE/license/upgrade (현재 빈 template). 본 branch 와 SpotBugs 보안 룰 vs CVE 스캔 경계 주의.
|
||
|
||
<!-- GENERATED: branch-contract:start -->
|
||
<!-- section-id: branch-contract-packet -->
|
||
## 브랜치 계약 패킷
|
||
|
||
- **생성 시 프로젝트 개정**: `1`
|
||
- **패킷 스키마**: `contract_packet: 1`
|
||
- **완료 조건**: static analysis 도구·threshold·CI failure mapping과 fixture가 명시된다
|
||
|
||
<!-- section-id: inherited-project-decisions -->
|
||
### 상속한 프로젝트 결정
|
||
|
||
| Decision Ref | Project Summary | Branch Application | Source |
|
||
|---|---|---|---|
|
||
| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-BUILD-001@1` | build tool은 Gradle Groovy DSL이다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |
|
||
| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-STACK-TEST-001@1` | test framework는 JUnit 5다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |
|
||
|
||
<!-- section-id: branch-local-decisions -->
|
||
### 브랜치 지역 결정
|
||
|
||
> 기존 branch-local 결정은 아래 `## Decision Evidence Map / 결정-근거 매핑`의 D-row가 소유하며 이 packet에서 복제하지 않는다.
|
||
|
||
| Decision ID | Decision | Relation | Supporting Claims | Status |
|
||
|---|---|---|---|---|
|
||
|
||
<!-- section-id: declared-overrides -->
|
||
### 선언한 예외
|
||
|
||
| Override ID | Overrides | Reason | Approval | Status |
|
||
|---|---|---|---|---|
|
||
<!-- GENERATED: branch-contract:end -->
|
||
|
||
<!-- section-id: branch-goal -->
|
||
## 목표
|
||
|
||
ca-tmpl skeleton 의 **정적 분석 / 코드 품질 baseline** — *어떤 정적 분석 도구를 채택하고 어떤 룰셋을 적용할지* 를 결정한다. 부모 §35-E 우선순위 **#2** ("코드 작성 본격화 직전" 박는 architecture-blocking 결정).
|
||
|
||
- **무엇을 막는가**: (1) 도구·룰셋이 모듈마다 제각각이라 위치 판정 불가, (2) formatter 와 style linter 가 같은 규칙을 중복 강제해 CI 가 무한 reformat 루프에 빠짐, (3) 코드 수준 보안 anti-pattern(SQL injection·weak crypto 등)이 빌드에서 새어나감, (4) 빈 `(toolchain)` gate 로 인해 lint gate 가 실제로 아무 도구도 실행하지 않음.
|
||
- **ci-quality-gates 와의 분담**: 그 branch 는 *threshold* (어느 위반이 release-blocking 인가) + gate 순서 owner. 본 branch 는 *tool 선택 + 룰셋 + Gradle wiring*. 본 branch 가 ci-quality-gates 의 `format / lint` gate row 의 `(toolchain)` 공석(literal gate-list `feature-ci-quality-gates-contract.md:194`; 동 노트의 ownership 매트릭스 `:184` 는 이미 본 branch 를 owner 로 기재)을 채우는 producer.
|
||
- 이슈: (ca-tmpl repo — 미생성)
|
||
- PR: (미생성)
|
||
|
||
<!-- section-id: branch-scope -->
|
||
## 범위
|
||
|
||
### 포함 범위
|
||
|
||
- 정적 분석 **도구 선택** (formatter / style linter / bytecode bug finder / code-level security / compile-time checker / aggregate platform 채택 여부) — D1~D7
|
||
- 각 도구의 **룰셋 내용 + config 파일 위치** (`config/checkstyle/checkstyle.xml`, `config/spotbugs/exclude.xml` 등)
|
||
- **Gradle plugin wiring** (plugin id + 버전 + 모듈 전체 적용 메커니즘 + `./gradlew check` 집계) — D8/D9
|
||
- 도구별 위반의 **blocking vs warning 채널 라우팅** (정책 *값* 은 ci-quality-gates 소유 → consume)
|
||
- **suppression / baseline 규약** (정적 분석 도구 한정 — Trivy suppression 은 ci-quality-gates 소유)
|
||
|
||
### 제외 범위
|
||
|
||
> 의도적으로 제외 — sibling branch 소유 (CLAUDE.md §11 OUT_OF_BRANCH_SCOPE). 면접에서 "이건 본 branch 범위 밖" 답변 근거.
|
||
|
||
- **coverage threshold + gate 순서 + blocking/warning 정책 *값*** → [[raw/branch-notes/feature-ci-quality-gates-contract]]
|
||
- **ArchUnit 경계 룰 + SonarQube custom rule *구현*** → [[raw/branch-notes/feature-architecture-enforcement-rules]] (그 branch 의 명시적 OOS)
|
||
- **dependency CVE/license 스캔 + SBOM + Cosign + dependency-locking *메커니즘*** → [[raw/branch-notes/feature-build-release-supply-chain-contract]] / [[raw/branch-notes/feature-dependency-vulnerability-management-contract]]
|
||
- **JaCoCo coverage 도구** → coverage 영역(ci-quality-gates) — 본 branch 미결정
|
||
- **CI job 분리/실행 시점** → ci-quality-gates 에서 최종화 (`feature-architecture-enforcement-rules.md:54` 와 동일 위임 패턴)
|
||
|
||
## 근거 (필수, 최소 1개+)
|
||
|
||
> 이 branch의 구현·설계 결정의 **근거가 되는 외부 자료**. 공식 문서·대기업 기술 블로그·강의 등 raw 자료를 인용. 같은 자료가 여러 결정의 근거면 결정 표시와 함께 여러 번 등장 가능.
|
||
|
||
| Source | 정당화하는 결정 |
|
||
|---|---|
|
||
| [[raw/official-docs/errorprone-gradle-plugin-readme]] | D5 — `net.ltgt.errorprone` 채택, Java 21에서 JDK 16+ 자동 forking + JVM args 주입 근거 (C3, C4) |
|
||
| [[raw/official-docs/sonarqube-server-versus-cloud]] | D7 — SonarQube(Server든 Cloud든) 기본 미채택 근거. Server는 self-managed 서버 설치 필요, Cloud는 외부 SaaS — 둘 다 zero-external-service 원칙과 충돌. |
|
||
| [[raw/official-docs/checkstyle-google-style-reference]] | D2 — Checkstyle naming(TypeName/MethodName)/Javadoc(MissingJavadocType/MissingJavadocMethod)/formatting(Indentation/LineLength/Whitespace) 모듈 분류 + google_checks.xml 기준 config 확인 |
|
||
| [[raw/official-docs/spotless-gradle-plugin-readme]] | D1/D9 — Spotless Gradle plugin(`com.diffplug.spotless`) 채택 + `spotlessCheck`(CI 검증) vs `spotlessApply`(자동수정) task 분리 + `googleJavaFormat` step 사용 + Gradle 7.3 / JRE 17 최소 요건 확인 |
|
||
| [[raw/official-docs/spotbugs-gradle-plugin-docs]] | D3/D4/D9 — SpotBugs Gradle Plugin 채택, `spotbugsPlugins` 로 FindSecBugs 연동, `./gradlew check` 자동 집계 (C1~C5) |
|
||
| [[raw/official-docs/find-sec-bugs-official]] | D4 — FindSecBugs(SpotBugs 보안 플러그인) 채택. 144개 취약점 유형·826+ API 시그니처 탐지, OWASP Top 10/CWE 연계, Maven/IDE/CI 통합 공식 확인. |
|
||
| [[raw/official-docs/google-java-format-readme]] | D1 — google-java-format 공식 scope(formatting 전용, naming 등 미포함), Java 21 최소 버전 요건, zero-configurability 설계 결정, JDK 16+ --add-exports JVM flag 요건 원문 확인. |
|
||
|
||
근거 자료가 raw에 아직 없다면 먼저 `raw-source-template` 또는 `lecture-note-template` 으로 raw에 등록한 뒤 여기서 링크.
|
||
|
||
## TODO
|
||
|
||
각 항목 옆에 증거 등급 표기: `actually-implemented` | `locally-verified` | `prod-verified` | `documented-only` | `planned` | `needs-confirmation`
|
||
|
||
- [x] Spotless + google-java-format Gradle wiring (`subprojects {}` + `spotlessCheck`/`spotlessApply`) — 등급: `locally-verified` (8.6.0 + GJF 1.35.0, `spotlessApply` 로 654 파일 일괄 포맷, `spotlessCheck` green)
|
||
- [x] Checkstyle custom minimal ruleset (`config/checkstyle/checkstyle.xml` + suppressions) — 등급: `locally-verified` (13.5.0; naming/logical error-tier, formatting/import-order 모듈 제거, Javadoc warning-tier, `log`/`SELF` 관용구 보정)
|
||
- [x] SpotBugs + FindSecBugs wiring (`config/spotbugs/exclude.xml`) — 등급: `locally-verified` (6.5.6/core 4.10.2 + FSB 1.14.0; `reportLevel='high'`; commons-lang3 BOM 충돌 해소 후 분석 정상; CSRF false-positive exclude)
|
||
- [x] ErrorProne wiring (`net.ltgt.errorprone` + `error_prone_core`) — 등급: `locally-verified` (5.1.0 + core 2.49.0; main 무오류, test 4건 실수정 후 compileJava/compileTestJava green)
|
||
- [x] Gradle 9.0.0 + Java 21 에서 4개 도구 plugin 버전 호환 smoke 검증 (`./gradlew check`) — 등급: `locally-verified` (`./gradlew check` BUILD SUCCESSFUL, 10모듈 도구+테스트+Testcontainers; gate-bites 음성테스트 확인)
|
||
- [x] (선택) SonarQube opt-in 문서 (`docs/optional/sonarqube-integration.md`) — 등급: `documented-only` (작성 완료; 단 `/docs` 는 gitignore 라 로컬 전용 — 커밋 비포함)
|
||
- [ ] 머지 시 ci-quality-gates `format / lint` gate row `(toolchain)` → `feature-static-analysis-quality-contract` 충원 (역참조 전파) — 등급: `planned` (merge-time follow-up — 본 구현 범위 밖)
|
||
|
||
## 진행 중 메모
|
||
|
||
- ca-tmpl 은 정적 분석 도구가 **전무한 greenfield** (Explore 확인: spotless/checkstyle/spotbugs/errorprone/pmd/sonar/jacoco 0). 본 branch 는 신규 도입(마이그레이션 아님).
|
||
- 실제 stack: Java 21 / Gradle **9.0.0** / Spring Boot **3.5.15** (project §34 는 3.5.14 기재 — 경미한 drift, §Audit 참조). 모든 plugin 버전 선택이 Gradle 9.0.0 기준 → 호환은 §Claims To Verify 로 실측.
|
||
- 도구 선택 철학: §34 single-stack minimalism + §2 무외부의존 → **로컬·infra-free·비중복** 도구만. 중복 도구(PMD)·외부 서비스(Sonar)는 기본 배제.
|
||
|
||
## 결정 사항
|
||
|
||
> 추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 대안과 함께 기록. 상세 매핑은 ↓ Decision Evidence Map.
|
||
|
||
- 2026-06-15: **D1 formatter = Spotless 8.6.0 + google-java-format 1.35.0** / 이유: 결정론적 zero-config 포맷 + `spotlessApply` 자동수정 / 대안: palantir-java-format(Spotless API 호환 위험), Eclipse JDT(custom XML overhead), Checkstyle-only(자동수정 없음) / 근거: [[raw/official-docs/google-java-format-readme]], [[raw/official-docs/spotless-gradle-plugin-readme]]
|
||
- 2026-06-15: **D2 style linter = Checkstyle 13.5.0 (custom minimal ruleset)** / 이유: formatter 가 못 하는 naming·Javadoc·logical 강제, formatting 모듈은 formatter 와 중복이라 suppress / 대안: google_checks.xml 그대로(포맷 충돌 #6527), sun_checks.xml(obsolete) / 근거: [[raw/official-docs/checkstyle-google-style-reference]], [[raw/official-docs/google-java-format-readme]]
|
||
- 2026-06-15: **D3 bytecode bug finder = SpotBugs 6.5.6 (core 4.10.2)** / 이유: 바이트코드 데이터플로우 null/resource/equals 버그 탐지 / 대안: 미채택 시 ErrorProne 단독 / 근거: [[raw/official-docs/spotbugs-gradle-plugin-docs]]
|
||
- 2026-06-15: **D4 code-level security = FindSecBugs 1.14.0 (SpotBugs plugin)** / 이유: SQL injection·weak crypto 등 코드 수준 보안 anti-pattern 탐지(타 도구 미커버), CVE 스캔과 구분 / 대안: 전문 SAST 위임 / 근거: [[raw/official-docs/find-sec-bugs-official]]
|
||
- 2026-06-15: **D5 compile-time checker = ErrorProne (net.ltgt.errorprone 5.1.0 + core 2.49.0)** / 이유: 컴파일 타임 correctness/swapped-arg/MissingOverride 즉시 강제 / 대안: 빌드 속도 제약 시 생략 / 근거: [[raw/official-docs/errorprone-gradle-plugin-readme]]
|
||
- 2026-06-15: **D6 PMD 미채택** / 이유: SpotBugs+ErrorProne 과 중복 크고 domain-less skeleton 에서 복잡도/CPD 가치 낮음·보안 미커버 / 대안: 복잡도 계약 요구 시 재검토 / 근거: 비교 합성(외부 vendor "미사용" 권고 부재 — `UNSUPPORTED_DECISION`)
|
||
- 2026-06-15: **D7 SonarQube 미채택(기본 skip) + optional opt-in** / 이유: Server/Cloud 모두 외부 서비스 전제 → §2 무외부의존 위반; 로컬 plugin 으로 `./gradlew check` 완결 / 대안: 조직이 Sonar 서버 보유 시 opt-in profile / 근거: [[raw/official-docs/sonarqube-server-versus-cloud]]
|
||
- 2026-06-15: **D8 Gradle wiring = 기존 루트 `subprojects {}` 확장** / 이유: ca-tmpl 현행 build.gradle 이 이미 `subprojects {}` 사용 → 일관성 / 대안: build-logic convention plugin(모듈 급증 시) / 근거: ca-tmpl `src/build.gradle:15-52` ground truth (`UNSUPPORTED_IMPL_DECISION` — 메커니즘 선택은 임의 trade-off)
|
||
- 2026-06-15: **D9 `./gradlew check` 단일 집계 + blocking; ci-quality-gates `(toolchain)` 충원** / 이유: 각 plugin 이 check 에 자동 연결, lint gate 가 실제 도구 실행 / 대안: 별도 task 수동 호출 / 근거: [[raw/official-docs/spotless-gradle-plugin-readme]], [[raw/official-docs/spotbugs-gradle-plugin-docs]] + cross [[raw/branch-notes/feature-ci-quality-gates-contract]] D1/D4
|
||
|
||
## 결정-근거 매핑
|
||
|
||
> 각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시한다.
|
||
> `Decision ID` 는 이 branch-note 안에서 안정적으로 유지한다. 예: `D1`, `D2`.
|
||
> `Supporting Claims` 는 `raw/<category>/<slug>.md#C1` 형식으로 연결한다.
|
||
|
||
> `선택 조건` 열(R2): "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 분기 없으면 `N/A`.
|
||
|
||
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|
||
|---|---|---|---|---|---|
|
||
| D1 | formatter = Spotless 8.6.0 + google-java-format 1.35.0 | 결정론적 포맷 + 100-char 수용 가능 → 이 결정 / 120-char 팀 표준이면 palantir(단 Spotless API 호환 확인 필수) | `raw/official-docs/google-java-format-readme.md#GJF-README-C2`, `raw/official-docs/google-java-format-readme.md#GJF-README-C3`, `raw/official-docs/spotless-gradle-plugin-readme.md#SPOTLESS-GRADLE-C4`, `raw/official-docs/spotless-gradle-plugin-readme.md#SPOTLESS-GRADLE-C5` | `official-vendor-doc` | google-java-format 1.35.0 + Spotless 8.6.0 의 Gradle 9.0.0 무결 동작 미검증(docs는 Gradle 7.3+/JRE17+ 최소만) → Claims To Verify |
|
||
| D2 | style linter = Checkstyle 13.5.0 (custom minimal ruleset: naming+Javadoc+logical, formatting 모듈 suppress) | naming/Javadoc 강제가 skeleton 계약 범위 → 이 결정 / pure formatting 만이면 Checkstyle 생략(D1 단독) | `raw/official-docs/checkstyle-google-style-reference.md#C2`, `raw/official-docs/checkstyle-google-style-reference.md#C3`, `raw/official-docs/checkstyle-google-style-reference.md#C4`, `raw/official-docs/checkstyle-google-style-reference.md#C1`, `raw/official-docs/google-java-format-readme.md#GJF-README-C1` | `official-vendor-doc` | google_checks.xml 직접 사용 시 formatter 충돌(#6527); importOrder↔CustomImportOrder 동기화 누락 시 CI 무한 reformat 루프 |
|
||
| D3 | bytecode bug finder = SpotBugs 6.5.6 (toolVersion core 4.10.2) | 항상(baseline) | `raw/official-docs/spotbugs-gradle-plugin-docs.md#SPOTBUGS-GRADLE-C1`, `raw/official-docs/spotbugs-gradle-plugin-docs.md#SPOTBUGS-GRADLE-C3`, `raw/official-docs/spotbugs-gradle-plugin-docs.md#SPOTBUGS-GRADLE-C5` | `official-vendor-doc` | docs는 "Gradle v7.0+"만 명시(Gradle 9.0.0 직접 미언급) → plugin 6.5.6 의 Gradle 9 동작 실측 필요 |
|
||
| D4 | code-level security = FindSecBugs 1.14.0 (spotbugsPlugins) | 코드 수준 OWASP 보안을 CI 에서 잡을 때 → 이 결정 / 전문 SAST 완전 위임 시 생략 가능 | `raw/official-docs/find-sec-bugs-official.md#C1`, `raw/official-docs/find-sec-bugs-official.md#C2`, `raw/official-docs/find-sec-bugs-official.md#C5`, `raw/official-docs/spotbugs-gradle-plugin-docs.md#SPOTBUGS-GRADLE-C4` | `official-vendor-doc` | FSB docs는 Gradle 통합 직접 미명시(C4=Maven/IDE만) → spotbugsPlugins 경유 Gradle 적용 실측 필요; CVE 스캔(sibling)과 경계 유지 |
|
||
| D5 | compile-time checker = ErrorProne (net.ltgt.errorprone 5.1.0 + error_prone_core 2.49.0) | correctness/null 즉시 강제 필요 → 이 결정 / 빌드 속도 절대 제약이면 생략(SpotBugs 단독) | `raw/official-docs/errorprone-gradle-plugin-readme.md#C3`, `raw/official-docs/errorprone-gradle-plugin-readme.md#C4`, `raw/official-docs/errorprone-gradle-plugin-readme.md#C2`, `raw/official-docs/errorprone-gradle-plugin-readme.md#C1` | `official-vendor-doc` | README는 min Gradle 6.8 만 명시; plugin 5.1.0 + core 2.49.0 의 Gradle 9.0.0 fork compiler 정상 동작 실측 필요 |
|
||
| D6 | PMD 미채택 | SpotBugs+ErrorProne 기채택 + domain-less skeleton → 제외 / 복잡도·CPD 가 계약 요구되면 재검토 | (없음 — 비교 합성, vendor "미사용" 권고 부재) | `research-synthesis` — **UNSUPPORTED_DECISION** (외부 근거 없는 임의 trade-off: 중복성·skeleton 규모 판단) | PMD CPD/복잡도 메트릭이 나중에 필요해지면 재평가 |
|
||
| D7 | SonarQube 미채택(기본 skip) + optional opt-in 문서 | skeleton zero-external-service 원칙 고수 → skip / 조직이 Sonar 서버 보유 시 opt-in profile | `raw/official-docs/sonarqube-server-versus-cloud.md#C1`, `raw/official-docs/sonarqube-server-versus-cloud.md#C2` (+ project §2/§34 무외부의존 연결 논리) | `official-vendor-doc(배포모델) + project-ssot` | Sonar Gradle 9 + 9-module classpath drop 위험(opt-in 활성화 시); SonarJava 고유 dataflow 룰 일부 미커버 |
|
||
| D8 | Gradle wiring = 기존 루트 `subprojects {}` 블록 확장 (신규 build-logic convention plugin 미도입) | ca-tmpl 현행 build.gradle 이 이미 `subprojects {}` + `tasks.named('check')` 집계 사용 → 일관성 / 모듈 급증 시 convention plugin 재검토 | ca-tmpl ground truth `src/build.gradle:15-52` (`subprojects {}` apply 패턴 + `tasks.named('check')` 집계) | `ground-truth-code` — **UNSUPPORTED_IMPL_DECISION** (메커니즘 선택은 임의 trade-off; convention plugin 이 Gradle 9 에선 더 idiomatic) | 빌드 복잡도 증가 시 convention plugin 마이그레이션 부담 |
|
||
| D9 | `./gradlew check` 단일 집계 + blocking; ci-quality-gates `(toolchain)` 공석 충원 | 항상 | `raw/official-docs/spotless-gradle-plugin-readme.md#SPOTLESS-GRADLE-C3`, `raw/official-docs/spotbugs-gradle-plugin-docs.md#SPOTBUGS-GRADLE-C1` (+ cross [[raw/branch-notes/feature-ci-quality-gates-contract]] D1/D4) | `official-vendor-doc + cross-contract` | 최종 blocking/warning *정책 값* 은 ci-quality-gates 소유 → 본 branch 는 채널 라우팅만, 정책 변경 시 재평가 |
|
||
|
||
## 구현 가이드
|
||
|
||
> *결정 (Decisions)* 이 "*무엇* 을 할 것인가" 라면, 본 §는 "*어디에 어떻게* 구현될 것인가" 의 사전 명세 — *문서가 모호해서 구현자가 임의로 정해야 했던 결정* 카탈로그. 작성 목표는 다음 구현자가 *되묻지 않아도 코드를 작성할 수 있는 수준*.
|
||
>
|
||
> **본 §는 일률적 anchor list 를 강제하지 않는다.** branch 마다 구현 내용·범위가 다르므로 sub-section 은 *이 branch 의 결정과 근거에서 도출되는 것만* 작성. 어떤 branch 는 error mapping 표 + 정적 강제 카탈로그, 어떤 branch 는 migration 단계 + wiring, 어떤 branch 는 sequence + state machine. 형식 예시는 [[raw/branch-notes/feature-boundary-validation-mapping-contract]] 의 §구현 가이드 참조.
|
||
>
|
||
> **3-rule meta principle (필수 준수)**:
|
||
>
|
||
> 1. **R1. Reference 필수** — 각 sub-section / row / cell 은 본 branch 의 `Decision ID` (예: D1, D2) + 그 결정의 `Supporting Claim ID` (예: `RAW-SLUG-C1`) 를 reference. *근거 없는 결정 금지* — 모든 구현 detail 은 결정 + 근거의 *도출* 이어야 함.
|
||
> 2. **R2. UNSUPPORTED_IMPL_DECISION 명시** — 근거 raw 가 *원칙* 만 권고하고 *detail* (메커니즘 선택 / 클래스/rule 명명 / glob 패턴 / algorithm / factory API 모양 등) 은 권고하지 않는 cell 은 `UNSUPPORTED_IMPL_DECISION` 라벨 + 사용자 trade-off 근거 한 줄. 이게 *근거 있는 결정 vs 사용자 임의 trade-off* 의 경계.
|
||
> 3. **R3. OUT_OF_BRANCH_SCOPE 정제** — 본 branch 결정 범위 밖 cell 은 §구현 가이드에 *남기지 않음*. 별도 branch 또는 canonical SSOT 로 이관 (이관 history 는 별도 § "Audit & Findings" 등에 보존). 도메인 특화 detail (ca-tmpl skeleton 범위 밖) 도 동일하게 정제.
|
||
>
|
||
> **각 sub-section 의 권장 헤더 패턴**:
|
||
>
|
||
> ```markdown
|
||
> ### N. <sub-section 제목>
|
||
>
|
||
> > **Trace**: <In-scope row 들 + Decision ID + Supporting Claim ID 의 매핑 (한 줄/한 단락)>
|
||
> >
|
||
> > - **UNSUPPORTED_IMPL_DECISION**: <근거 없는 사용자 임의 결정 항목들 + 각각의 trade-off 근거 한 줄>
|
||
>
|
||
> <표 또는 명확한 구조 — 자유 텍스트 = 모호함 = 되묻기 원인>
|
||
> ```
|
||
|
||
### 1. Gradle plugin 적용 (루트 build.gradle + 기존 subprojects 블록)
|
||
|
||
> **Trace**: D1(`GJF-README-C2/C3`,`SPOTLESS-GRADLE-C4`) · D3(`SPOTBUGS-GRADLE-C3`) · D4(`SPOTBUGS-GRADLE-C4`) · D5(`errorprone-...#C3/C4/C5`) · D8(ca-tmpl `src/build.gradle:15-52`). project §34 `apply false` 패턴 상속.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: plugin 버전 핀(8.6.0 / 6.5.6 / 5.1.0) + `effort='max'` / `reportLevel='high'` 는 docs 가 원칙만 제시하고 skeleton-specific 값은 권고 없음 → 사용자 trade-off(엄격도↑ vs 빌드시간/false-positive↑). 기본값(`'default'`)도 기능상 유효.
|
||
|
||
```groovy
|
||
// 루트 build.gradle plugins 블록 (apply false — 기존 §34 패턴)
|
||
plugins {
|
||
id 'com.diffplug.spotless' version '8.6.0' apply false // D1
|
||
id 'com.github.spotbugs' version '6.5.6' apply false // D3
|
||
id 'net.ltgt.errorprone' version '5.1.0' apply false // D5
|
||
}
|
||
|
||
// 기존 subprojects {} (src/build.gradle:15-52)에 추가 — D8
|
||
subprojects {
|
||
apply plugin: 'com.diffplug.spotless'
|
||
apply plugin: 'checkstyle' // Gradle 내장 — plugins{} 선언 불요 (D2)
|
||
apply plugin: 'com.github.spotbugs'
|
||
apply plugin: 'net.ltgt.errorprone'
|
||
|
||
spotless { java { // D1
|
||
googleJavaFormat('1.35.0')
|
||
importOrder()
|
||
removeUnusedImports()
|
||
} }
|
||
|
||
checkstyle { // D2
|
||
toolVersion = '13.5.0' // ※ Gradle 기본 toolVersion 은 구버전 → 명시 필수
|
||
configFile = rootProject.file('config/checkstyle/checkstyle.xml')
|
||
configDirectory = rootProject.file('config/checkstyle')
|
||
ignoreFailures = false
|
||
maxWarnings = 0
|
||
}
|
||
|
||
spotbugs { // D3
|
||
toolVersion = '4.10.2'
|
||
excludeFilter = rootProject.file('config/spotbugs/exclude.xml')
|
||
// effort / reportLevel: UNSUPPORTED_IMPL_DECISION (위 참조)
|
||
}
|
||
|
||
dependencies {
|
||
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0' // D4
|
||
errorprone 'com.google.errorprone:error_prone_core:2.49.0' // D5
|
||
}
|
||
|
||
tasks.withType(JavaCompile).configureEach {
|
||
options.errorprone { disableWarningsInGeneratedCode = true } // D5 (errorprone-...#C5)
|
||
}
|
||
}
|
||
```
|
||
|
||
> **ErrorProne Java 21 JVM args 수동 설정 금지** (`errorprone-...#C4`): plugin 5.1.0 은 JDK 16+ 감지 시 forking compiler + 필요한 `--add-exports`/`--add-opens` 를 자동 주입한다. `org.gradle.jvmargs` 에 수동 추가 시 중복/충돌. 단 Gradle daemon 자체가 Java 21 toolchain 으로 컴파일하는지만 확인.
|
||
|
||
### 2. Config 파일 레이아웃
|
||
|
||
> **Trace**: D2(checkstyle config) · D3/D4(spotbugs exclude). 본 branch 의 결정 산출물 위치.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: `config/<tool>/` 경로는 Gradle Checkstyle 관행 차용 — SpotBugs docs 는 자동탐색 없음. 다른 경로도 기능 동등(사용자 trade-off: 관행 일관성 vs 자유).
|
||
|
||
```text
|
||
config/
|
||
checkstyle/
|
||
checkstyle.xml ← KEEP: naming + Javadoc + logical 모듈만 (CS-C2/C3)
|
||
checkstyle-suppressions.xml ← SUPPRESS: formatter 소유 모듈 (CS-C4) — §3 카탈로그
|
||
spotbugs/
|
||
exclude.xml ← SpotBugs + FindSecBugs false-positive exclude filter
|
||
```
|
||
|
||
### 3. Checkstyle ruleset 카탈로그 (KEEP vs SUPPRESS)
|
||
|
||
> **Trace**: D2 + `checkstyle-...#C2/C3/C4/C5` + `GJF-README-C1`(formatter scope 는 formatting 한정, naming 미강제 → Checkstyle 잔존 이유). formatter(D1)와 중복 모듈을 suppress 해야 무한 reformat 루프(§엣지) 방지.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: KEEP/SUPPRESS 각 모듈의 *세부 파라미터*(예: `LineLength` 100 vs `MissingJavadocMethod` 의 `scope`/test 예외)는 docs 가 모듈 존재만 확인하고 값은 미권고 → 사용자 trade-off. 아래는 권고 기본선.
|
||
|
||
| 분류 | 모듈(예) | 처리 | 근거 |
|
||
|---|---|---|---|
|
||
| naming | `TypeName`, `MethodName`, `ConstantName`, `ParameterName`, `LocalVariableName`, `LambdaParameterName` … | **KEEP** (blocking) | `CS-C2`, `CS-C5` |
|
||
| Javadoc | `MissingJavadocType`, `MissingJavadocMethod`, `NonEmptyAtclauseDescription` … | **KEEP** (main: blocking, test: warning) | `CS-C3` |
|
||
| logical/design | `NeedBraces`, `FallThrough`, `EmptyCatchBlock`, `OneStatementPerLine`, `MissingSwitchDefault` | **KEEP** | google_checks.xml(`CS-C1`) |
|
||
| formatting | `Indentation`, `LineLength`, `WhitespaceAround`, `LeftCurly`/`RightCurly`, `SeparatorWrap`, `OperatorWrap`, `EmptyLineSeparator` | **SUPPRESS** (formatter 소유) | `CS-C4` (#6527 충돌) |
|
||
| import order | `CustomImportOrder` | **SUPPRESS** (Spotless `importOrder()` 단독 소유) | D1 + `SPOTLESS-GRADLE-C1` (spotless{} 포매터 step 구성) |
|
||
|
||
### 4. 위반 → blocking
|
||
|
||
> **Trace**: D9 + cross [[raw/branch-notes/feature-ci-quality-gates-contract]] D1(contract violation=blocking)/D4(warning-only 경계). 본 branch 는 *라우팅*만; 최종 정책 *값* 은 ci-quality-gates 소유.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: 아래 채널 배정은 ci-quality-gates 정책의 *예상 적용* — 그 branch 가 최종 확정. test source set warning 시작 여부는 사용자 trade-off.
|
||
|
||
| 도구 task | 채널 | 비고 |
|
||
|---|---|---|
|
||
| `spotlessCheck` (포맷 diff) | **blocking** | CI 는 `spotlessApply` 절대 실행 금지(파일 mutate) — `spotlessCheck` 만 |
|
||
| `checkstyleMain` | **blocking** (`ignoreFailures=false`, `maxWarnings=0`) | naming/Javadoc 위반 = skeleton 계약 위반 |
|
||
| `checkstyleTest` | **warning** 시작 → 추후 승급 | 테스트 헬퍼 Javadoc 예외 |
|
||
| `compileJava` (ErrorProne) | **blocking** (컴파일 오류) | 별도 설정 불요 |
|
||
| `spotbugsMain` (+ FindSecBugs) | **blocking** (high priority) | `reportLevel`/severity 정책은 ci-quality-gates |
|
||
|
||
### 5. SonarQube opt-in (기본 미적용)
|
||
|
||
> **Trace**: D7 + `sonarqube-...#C1/C2`(Server/Cloud 모두 외부 서비스). 기본 build.gradle 에 Sonar plugin **미포함**.
|
||
>
|
||
> - **UNSUPPORTED_IMPL_DECISION**: opt-in 제공 *형식*(주석 build.gradle vs 별도 `docs/optional/`)은 docs 무관 사용자 선택. 아래는 권고.
|
||
|
||
```text
|
||
docs/optional/sonarqube-integration.md ← Sonar 서버 보유 팀용 opt-in 가이드 (plugin id org.sonarqube + host.url/token)
|
||
```
|
||
기본 `./gradlew check` 는 Sonar 분석을 포함하지 않으며 외부 연결 없이 완결된다(D7).
|
||
|
||
## 엣지·실패·의존
|
||
|
||
> R4(깊이 게이트) 캡처용. 정상 경로 외에 *구현 중 부딪힐* 실패/엣지/다른 계약 의존을 미리 열거. 없으면 "해당 없음" 명시(공란 금지).
|
||
|
||
- **실패·엣지 경로**:
|
||
- *formatter ↔ linter 충돌*: google_checks.xml 직접 사용 시 `Indentation`/`LineLength` 등 formatter 가 고친 코드를 Checkstyle 이 reject → CI 무한 reformat. **기대 동작**: custom ruleset 이 formatter 소유 모듈 suppress(D2 / `CS-C4` / §구현 가이드 §3).
|
||
- *import order 동기화*: Spotless `importOrder()` ↔ Checkstyle `CustomImportOrder` 불일치 → 영구 CI 루프. **기대 동작**: Checkstyle 에서 import-order 검사 제거(Spotless 단독 소유).
|
||
- *생성 코드 false positive*: MapStruct/Lombok 생성물에 ErrorProne 경고 → `disableWarningsInGeneratedCode=true`(`errorprone-...#C5`).
|
||
- *Gradle 9 + Java 21 plugin 호환*: 4개 plugin 버전이 Gradle 9.0.0 에서 미검증 → 빌드 실패 가능. **기대 동작**: smoke 검증 후 버전 핀(§Claims To Verify).
|
||
- *FSB false positive*: taint 분석 inter-procedural 한계 → `config/spotbugs/exclude.xml` 로 관리.
|
||
- **다른 계약 의존**:
|
||
- [[raw/branch-notes/feature-ci-quality-gates-contract]] D1(contract violation=blocking) + D4(warning-only 경계)에 의존 — 본 branch 는 도구 위반을 그 정책 채널로 *라우팅*만. 그 정책 변경 시 본 branch 의 blocking 매핑 재평가. **역방향**: 그 branch 의 ownership 매트릭스(`:184`/§Coverage `:287`)는 이미 `(toolchain)`→본 branch 로 매핑됨; literal gate-list row `:194` 만 `(toolchain)` token 잔존(cosmetic) — 본 branch 머지 시 정합.
|
||
- [[raw/branch-notes/feature-build-release-supply-chain-contract]] D8(Gradle dependency-locking)에 의존 — 도구 JAR 버전이 `gradle/locks/*.lockfile` 에 포함되어야 함(`./gradlew dependencies --write-locks`). 본 branch 는 *버전 값*만 정하고 locking *메커니즘*은 그 branch 소유.
|
||
- [[raw/branch-notes/feature-architecture-enforcement-rules]] — ArchUnit suite 는 그 branch 소유. 본 branch 는 ArchUnit rule 추가 안 함(OOS).
|
||
|
||
## 검증해야 할 주장
|
||
|
||
> 공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다.
|
||
> 구현 전/중/후에 실제로 검증해야 하는 주장을 분리한다.
|
||
|
||
| Claim | Why uncertain | How to verify | Status |
|
||
|---|---|---|---|
|
||
| Spotless 8.6.0 + google-java-format 1.35.0 이 Gradle 9.0.0 + Java 21 에서 무결 동작 | docs는 Gradle 7.3+/JRE17+ 최소만 명시, Gradle 9 직접 미검증 | `./gradlew spotlessCheck` 실행 후 오류 0 | `locally-verified` — `spotlessApply` 654파일 포맷 후 `spotlessCheck` green (2026-06-20) |
|
||
| SpotBugs plugin 6.5.6(core 4.10.2) + FindSecBugs 1.14.0 이 Gradle 9.0.0 에서 분석 성공 | docs는 "Gradle v7.0+"만 명시(`SPOTBUGS-GRADLE-C5`); FSB는 Gradle 통합 직접 미언급(`find-sec-bugs-...#C4`) | `./gradlew check` → spotbugsMain 리포트 생성 + FSB 룰 동작 확인 | `locally-verified` — 단 Boot BOM 이 commons-lang3 를 3.17.0 으로 강등 → SpotBugs 4.10.2 가 `org.apache.commons.lang3.Strings`(3.18.0+) 부재로 crash. `ext['commons-lang3.version']='3.20.0'` override 로 해소(`force` 는 dependency-management 가 덮어써 무효). FSB 동작 확인(SPRING_CSRF_PROTECTION_DISABLED 탐지). 상세: [[raw/errors/spotbugs-commons-lang3-bom-downgrade-noclassdef-2026-06-20]] |
|
||
| ErrorProne plugin 5.1.0 + core 2.49.0 이 Gradle 9.0.0 + Java 21 fork compiler 정상 | README는 min Gradle 6.8 만 명시; 5.1.0 의 Gradle 9 호환 실측 필요 | `./gradlew compileJava` 오류 없이 통과 + ErrorProne 룰 적용 확인 | `locally-verified` — main 무오류; test 4건(CheckReturnValue×3, DoubleBraceInitialization×1) 실수정 후 compileJava/compileTestJava green |
|
||
| custom checkstyle.xml + suppressions 가 formatter 와 충돌 없이 동작(무한 reformat 루프 없음) | google_checks.xml 직접 사용은 #6527 충돌 — custom suppress 완전성 미검증 | `./gradlew spotlessApply && ./gradlew checkstyleMain` 연속 실행 시 위반 0 | `locally-verified` — formatting/import-order 모듈 제거; `spotlessApply` 후 `checkstyleMain` error 0(naming/logical), Javadoc 만 warning |
|
||
| `./gradlew check` 가 4개 도구 task 를 모두 집계 + 위반 시 non-zero exit | 각 plugin 이 check 에 자동 연결되나 조합 동작 미검증 | 의도적 위반 fixture 주입 후 `./gradlew check` exit code ≠ 0 확인 | `locally-verified` — `:module:check` dry-run 에 4개 도구 task 집계 확인; 의도적 위반(나쁜 포맷 + `Bad_Method_Name`) 주입 시 spotlessCheck/checkstyleMain BUILD FAILED 확인 후 원복 |
|
||
| Sonar opt-in 구성이 Gradle 9.0.0 + 9-module 에서 classpath drop 없이 분석 | sonar-scanner-gradle 7.0 공지가 "complex multi-module → major drop" 경고 | opt-in 활성화 후 `./gradlew sonar` 이슈 수 비교 | `planned` — 기본 미적용(opt-in 문서만), 본 branch 미검증 |
|
||
|
||
|
||
## Audit & Findings
|
||
|
||
> ground-truth(ca-tmpl 실제 코드/registry) 대조에서 발견한 drift. 본 branch 결정 영역 밖 항목은 *정합 권고만* (자동 rewrite 금지). 비차단.
|
||
|
||
- **GREENFIELD**: ca-tmpl 에 정적 분석 도구 전무(Explore 확인: settings.gradle 9-module 어디에도 spotless/checkstyle/spotbugs/errorprone/pmd/sonar/jacoco 없음). 본 branch = 신규 도입(마이그레이션 아님).
|
||
- **STACK_DRIFT (비차단)**: project §34 Stack Matrix = Spring Boot **3.5.14**, 실제 `ca-tmpl/src/build.gradle:2` = **3.5.15**. 정적 분석 도구는 Boot 버전 비의존이라 본 결정 무영향. project §34 갱신 권고.
|
||
- **GRADLE_VERSION (검증 대상화)**: ca-tmpl `gradle/wrapper/gradle-wrapper.properties` = Gradle **9.0.0**. project §34 는 "Gradle Groovy DSL"만 명시(버전 무기재). 본 branch 의 모든 plugin 버전이 9.0.0 기준 → §Claims To Verify 로 실측.
|
||
- **MODULE_LIST_STALE (비차단)**: ca-tmpl 실제 모듈 9개(`settings.gradle`): app-bootstrap · domain-core · application-core · adapter-web · adapter-persistence · adapter-outbound · **adapter-identifier** · shared-contract · sample-portfolio. project §25 Blocking Defaults 의 package layout 목록은 `adapter-identifier` 미포함(부분 stale). 본 branch 의 `subprojects {}` 는 9개 전체에 적용되므로 영향 없음.
|
||
- **CI_TOOLCHAIN_VACANCY (대부분 이미 정합)**: ci-quality-gates 노트는 ownership 매트릭스(`:184`) + Sources(`:254`) + Coverage(`:287`) + Audit(`:297`)에서 이미 `(toolchain)`→`feature-static-analysis-quality-contract` 를 owner 로 기재함. **잔존**: literal gate-list row `feature-ci-quality-gates-contract.md:194` 의 `| format / lint | true | (toolchain) |` token 만 미정합(cosmetic). 본 branch 머지 시 그 row 정합 권고(역참조 비차단 전파). → §TODO 에 항목화.
|
||
|
||
### AS-BUILT 편차 (2026-06-20 구현 실측 — §구현 가이드 대비)
|
||
|
||
> spec §구현 가이드 의 사전 명세 대비, 실제 ca-tmpl(Gradle 9.0.0 / Java 21 / Boot 3.5.15 / 10모듈)에서 green 을 위해 조정한 항목. 사용자 승인된 전략(Javadoc warning-tier)과 환경 강제(commons-lang3) 구분.
|
||
|
||
- **plugin 버전**: spec 핀(8.6.0 / 6.5.6 / 5.1.0) 그대로 사용 — Gradle Plugin Portal 에서 resolve 확인. config 파일은 `rootProject = src/` 이므로 `src/config/` 에 배치(spec §2 의 `config/` = rootProject 상대).
|
||
- **SpotBugs (env 강제)**: `ext['commons-lang3.version']='3.20.0'` 추가 — spec 미기재. Boot BOM 이 도구 classpath 의 commons-lang3 를 3.17.0 으로 강등시켜 4.10.2 가 crash(§마주친 문제). 또 `reportLevel='high'` 적용(§1 이 제시한 strictness lever) — medium tier 78건 중 38건이 EI_EXPOSE_REP/REP2(DI 협력자 방어복사 노이즈)라 high-confidence 만 blocking. SPRING_CSRF_PROTECTION_DISABLED(stateless JWT API 의 의도된 설정) 3건은 `*SecurityConfig` 한정 exclude.xml suppress.
|
||
- **Checkstyle (사용자 승인 전략 + 관용구 보정)**: §4 는 checkstyleMain Javadoc 을 blocking 으로 규정하나, 기존 코드 327건(Method 293 + Type 34) 누락 → 사용자 결정으로 **Javadoc 규칙을 warning-tier**(severity=warning, `maxWarnings=∞`)로 도입(추후 blocking 승급). naming/logical 은 error-tier 유지. 관용구 false-positive 보정: `ConstantName` 에 `log`/`logger` 허용(Logger 는 Google §5.2.4 상 비-상수), 타입파라미터 패턴 `^[A-Z][A-Z0-9]*$` 로 F-bounded `SELF` 허용. `checkstyleTest`·`spotbugsTest` 는 `ignoreFailures=true`(§4 test-source warning trade-off).
|
||
- **코드 실수정(behavior-preserving)**: NeedBraces 13(중괄호 추가) + MissingSwitchDefault 1(`UpdateWorkLogUseCase` 방어 default) + ErrorProne test 4(`catchThrowableOfType`→`assertThatThrownBy` ×3, double-brace init→static factory ×1). spotlessApply 로 654 파일 일괄 포맷(google-java-format 2-space).
|
||
- **SonarQube 문서**: `docs/optional/sonarqube-integration.md` 작성. 단 ca-tmpl `/docs` 는 `.gitignore` → 로컬 전용(registries/snapshot 과 동일 관행), 커밋에는 비포함.
|
||
|
||
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
|
||
|
||
> `/coverage` 가 채우는 **생성물** — 손으로 유지하지 않는다. governing 문서(frontmatter `governing_docs`)가 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지의 결과. 기준: `rules/coverage-gate.md`.
|
||
> 상태: `covered-here`(이 브랜치 결정) / `delegated`(다른 owner 브랜치) / `missing`(아무도 안 맡음 → Blocking).
|
||
|
||
| 관심사 | 상태 | owner | 심각도 | 근거 |
|
||
|--------|------|-------|--------|------|
|
||
| <governing doc 의 관심사> | covered-here | — | — | D<n> |
|
||
| <관심사> | delegated | feature-<owner> | OK/Should-fix | §Audit 위임 링크 |
|
||
| <관심사> | missing | (없음) | 🔴 Blocking | governing doc §<x> 요구, 결정 없음 |
|
||
|
||
## 마주친 문제
|
||
|
||
> 짧은 메모만. 깊이 있는 트러블슈팅은 `raw/errors/` 로 분리하고 아래 Cluster에 연결.
|
||
|
||
- 2026-06-20 — **SpotBugs 4.10.2 분석 worker crash** (`NoClassDefFoundError: org.apache.commons.lang3.Strings`). Boot BOM 이 commons-lang3 를 모든 configuration(도구 `spotbugs` 포함)에서 3.17.0 으로 강등 → SpotBugs 가 요구하는 3.20.0 의 `Strings`(3.18.0+) 부재. `resolutionStrategy.force` 무효(dependency-management 가 우선), `ext['commons-lang3.version']='3.20.0'` 로 해소. 전말: [[raw/errors/spotbugs-commons-lang3-bom-downgrade-noclassdef-2026-06-20]].
|
||
- 2026-06-20 — spec 의 plugin 버전 핀은 Maven Central 구현-artifact 경로엔 404 였으나 **Gradle Plugin Portal 에는 전부 존재**(SpotBugs 6.5.6 / ErrorProne 5.1.0 marker 확인). `plugins{}` 는 portal 에서 resolve 하므로 spec 버전 그대로 사용.
|
||
|
||
## 묶음 (이 branch에서 파생된 자료)
|
||
|
||
<!-- GENERATED: sources:start -->
|
||
- [[raw/official-docs/checkstyle-google-style-reference]]
|
||
- [[raw/official-docs/errorprone-gradle-plugin-readme]]
|
||
- [[raw/official-docs/find-sec-bugs-official]]
|
||
- [[raw/official-docs/google-java-format-readme]]
|
||
- [[raw/official-docs/sonarqube-server-versus-cloud]]
|
||
- [[raw/official-docs/spotbugs-gradle-plugin-docs]]
|
||
- [[raw/official-docs/spotless-gradle-plugin-readme]]
|
||
<!-- GENERATED: sources:end -->
|
||
|
||
<!-- GENERATED: interviews:start -->
|
||
- [[raw/interviews/formatter-vs-style-linter-responsibility-split-2026-06-20]]
|
||
<!-- GENERATED: interviews:end -->
|
||
|
||
<!-- GENERATED: errors:start -->
|
||
- [[raw/errors/spotbugs-commons-lang3-bom-downgrade-noclassdef-2026-06-20]]
|
||
<!-- GENERATED: errors:end -->
|
||
|
||
<!-- GENERATED: blog-topics:start -->
|
||
- [[raw/blog-topics/gradle9-java21-static-analysis-baseline-2026-06-20]]
|
||
<!-- GENERATED: blog-topics:end -->
|
||
|
||
> 이 branch는 단일 노트가 아니라 **작업 묶음의 entry point**. 이 branch에서 파생된 모든 raw 노트를 카테고리별로 명시. 자식 노트가 forward link만 박아도 Obsidian backlink로 자동 발견되지만, 읽기 흐름과 분류를 위해 hub가 명시적으로 그룹화한다.
|
||
|
||
### Sub-branches (세부 작업)
|
||
|
||
- 해당 없음 (단일 branch — 세부 분해 없음).
|
||
|
||
### 근거 자료 (이 branch 결정 근거 — official-docs, 본 branch 가 hub)
|
||
|
||
- [[raw/official-docs/google-java-format-readme]] — D1 formatter scope
|
||
- [[raw/official-docs/spotless-gradle-plugin-readme]] — D1/D9 Spotless wiring
|
||
- [[raw/official-docs/checkstyle-google-style-reference]] — D2 ruleset 분류
|
||
- [[raw/official-docs/spotbugs-gradle-plugin-docs]] — D3/D4/D9 SpotBugs
|
||
- [[raw/official-docs/find-sec-bugs-official]] — D4 code-level security
|
||
- [[raw/official-docs/errorprone-gradle-plugin-readme]] — D5 ErrorProne
|
||
- [[raw/official-docs/sonarqube-server-versus-cloud]] — D7 Sonar skip 근거
|
||
|
||
### 오류 기록 (이 branch 작업 중 발생)
|
||
|
||
- [[raw/errors/spotbugs-commons-lang3-bom-downgrade-noclassdef-2026-06-20]] — Boot BOM 의 commons-lang3 강등으로 SpotBugs 분석 worker crash, `ext` property override 로 해소.
|
||
|
||
### 면접 준비 (이 작업에서 나올 수 있는 면접 질문)
|
||
|
||
- [[raw/interviews/formatter-vs-style-linter-responsibility-split-2026-06-20]] — 포매터와 스타일 린터의 책임 분리(중복 강제 시 무한 reformat 루프).
|
||
|
||
### 강의 (이 작업을 위해 학습한 강의)
|
||
|
||
- 해당 없음.
|
||
|
||
### job-posting tie-ins (이 작업에서 파생된 글감)
|
||
|
||
- [[raw/blog-topics/gradle9-java21-static-analysis-baseline-2026-06-20]] — Gradle 9 + Java 21 정적 분석 baseline 5종 도입의 함정(책임 중복 제거 / 기존 코드 마이그레이션 전략 / BOM↔도구 classpath 충돌 / reportLevel 보정).
|
||
|
||
## 관련 일일 노트
|
||
|
||
> 이 브랜치를 작업한 날짜들. 양방향 nav 유지.
|
||
|
||
- 해당 없음 (2026-06-15 daily 노트 미생성).
|
||
|
||
## 완료 후 정리
|
||
|
||
> 머지/종료 시점에 채움. `/ingest`가 이 섹션을 기준으로 wiki/projects/에 추출.
|
||
|
||
- PR 링크:
|
||
- 리뷰 메모:
|
||
- 머지 결과 / 배포 환경: (로컬/dev/staging/prod 어디까지 검증됐는지)
|
||
- **wiki 추출 대상** (verified만, `wiki/projects/`로만 추출):
|
||
- `actually-implemented` 항목:
|
||
- `locally-verified` 항목:
|
||
- `prod-verified` 항목:
|
||
- **추출하지 않을 항목** (planned / documented-only / abandoned):
|