42 KiB
title, source_type, status, branch, parent_branch, related_projects, governing_docs, tags, created, target_merge, status_label, id, kind, project, work_item, inherits, refines, overrides, depends_on, contract_packet, contract_packet_sha256
| title | source_type | status | branch | parent_branch | related_projects | governing_docs | tags | created | target_merge | status_label | id | kind | project | work_item | inherits | refines | overrides | depends_on | contract_packet | contract_packet_sha256 | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| branch / feature-static-analysis-quality-contract | branch-note | raw | feature-static-analysis-quality-contract |
|
|
|
2026-06-15 | review | BR-CA-SKELETON-OPERATIONAL-CONTRACT-059 | project-work-item | ca-skeleton-operational-contract | WI-CA-SKELETON-OPERATIONAL-CONTRACT-059 |
|
|
1 | 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 필수.
부모 (필수)
이 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 ChecklistC 영역 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 / lintgate 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 스캔 경계 주의.
브랜치 계약 패킷
- 생성 시 프로젝트 개정:
1 - 패킷 스키마:
contract_packet: 1 - 완료 조건: static analysis 도구·threshold·CI failure mapping과 fixture가 명시된다
상속한 프로젝트 결정
| 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 |
브랜치 지역 결정
기존 branch-local 결정은 아래
## Decision Evidence Map / 결정-근거 매핑의 D-row가 소유하며 이 packet에서 복제하지 않는다.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|
선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|
목표
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 / lintgate row 의(toolchain)공석(literal gate-listfeature-ci-quality-gates-contract.md:194; 동 노트의 ownership 매트릭스:184는 이미 본 branch 를 owner 로 기재)을 채우는 producer. - 이슈: (ca-tmpl repo — 미생성)
- PR: (미생성)
범위
포함 범위
- 정적 분석 도구 선택 (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
- Spotless + google-java-format Gradle wiring (
subprojects {}+spotlessCheck/spotlessApply) — 등급:locally-verified(8.6.0 + GJF 1.35.0,spotlessApply로 654 파일 일괄 포맷,spotlessCheckgreen) - 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관용구 보정) - 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) - ErrorProne wiring (
net.ltgt.errorprone+error_prone_core) — 등급:locally-verified(5.1.0 + core 2.49.0; main 무오류, test 4건 실수정 후 compileJava/compileTestJava green) - Gradle 9.0.0 + Java 21 에서 4개 도구 plugin 버전 호환 smoke 검증 (
./gradlew check) — 등급:locally-verified(./gradlew checkBUILD SUCCESSFUL, 10모듈 도구+테스트+Testcontainers; gate-bites 음성테스트 확인) - (선택) SonarQube opt-in 문서 (
docs/optional/sonarqube-integration.md) — 등급:documented-only(작성 완료; 단/docs는 gitignore 라 로컬 전용 — 커밋 비포함) - 머지 시 ci-quality-gates
format / lintgate 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-tmplsrc/build.gradle:15-52ground 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 (필수 준수):
- R1. Reference 필수 — 각 sub-section / row / cell 은 본 branch 의
Decision ID(예: D1, D2) + 그 결정의Supporting Claim ID(예:RAW-SLUG-C1) 를 reference. 근거 없는 결정 금지 — 모든 구현 detail 은 결정 + 근거의 도출 이어야 함.- R2. UNSUPPORTED_IMPL_DECISION 명시 — 근거 raw 가 원칙 만 권고하고 detail (메커니즘 선택 / 클래스/rule 명명 / glob 패턴 / algorithm / factory API 모양 등) 은 권고하지 않는 cell 은
UNSUPPORTED_IMPL_DECISION라벨 + 사용자 trade-off 근거 한 줄. 이게 근거 있는 결정 vs 사용자 임의 trade-off 의 경계.- R3. OUT_OF_BRANCH_SCOPE 정제 — 본 branch 결정 범위 밖 cell 은 §구현 가이드에 남기지 않음. 별도 branch 또는 canonical SSOT 로 이관 (이관 history 는 별도 § "Audit & Findings" 등에 보존). 도메인 특화 detail (ca-tmpl skeleton 범위 밖) 도 동일하게 정제.
각 sub-section 의 권장 헤더 패턴:
### 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-tmplsrc/build.gradle:15-52). project §34apply 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')도 기능상 유효.
// 루트 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 자유).
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 각 모듈의 세부 파라미터(예:
LineLength100 vsMissingJavadocMethod의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 무관 사용자 선택. 아래는 권고.
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()↔ CheckstyleCustomImportOrder불일치 → 영구 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로 관리.
- formatter ↔ linter 충돌: google_checks.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).
- raw/branch-notes/feature-ci-quality-gates-contract D1(contract violation=blocking) + D4(warning-only 경계)에 의존 — 본 branch 는 도구 위반을 그 정책 채널로 라우팅만. 그 정책 변경 시 본 branch 의 blocking 매핑 재평가. 역방향: 그 branch 의 ownership 매트릭스(
검증해야 할 주장
공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다. 구현 전/중/후에 실제로 검증해야 하는 주장을 분리한다.
| 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 rowfeature-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-boundedSELF허용.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 문서(frontmattergoverning_docs)가 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지의 결과. 기준:rules/coverage-gate.md. 상태:covered-here(이 브랜치 결정) /delegated(다른 owner 브랜치) /missing(아무도 안 맡음 → Blocking).
| 관심사 | 상태 | owner | 심각도 | 근거 |
|---|---|---|---|---|
| <governing doc 의 관심사> | covered-here | — | — | D |
| <관심사> | delegated | feature- | OK/Should-fix | §Audit 위임 링크 |
| <관심사> | missing | (없음) | 🔴 Blocking | governing doc § 요구, 결정 없음 |
마주친 문제
짧은 메모만. 깊이 있는 트러블슈팅은
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에서 파생된 자료)
- 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
이 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,
extproperty 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):