--- title: interview-prep / formatter-vs-style-linter-responsibility-split-2026-06-20 source_type: interview-prep status: raw related_branches: [feature-static-analysis-quality-contract] related_projects: [ca-skeleton] tags: [interview-prep, ca-skeleton, static-analysis, spotless, checkstyle, ci, formatter] created: 2026-06-20 status_label: collecting --- # interview-prep: formatter-vs-style-linter-responsibility-split-2026-06-20 > Layer: `raw/interviews/` — 면접 질문 원본 수집·연구 노트. 다듬어진 답변은 `/interviewize` 후 `wiki/interview/` 에 별도 작성. ## Parent / 부모 - [[raw/branch-notes/feature-static-analysis-quality-contract]] — Spotless(google-java-format) + Checkstyle 을 한 빌드에 같이 도입할 때 부딪힌 핵심 결정(D1/D2/§3 catalog). ## 질문 / Question - 질문 원문: 코드 포매터(google-java-format)와 스타일 린터(Checkstyle)를 같은 CI 에 둘 다 넣을 때, 둘의 책임을 어떻게 나눠야 하나요? 나누지 않으면 무슨 일이 일어나나요? - 출처: 예상 질문 (실 면접 아님). - 받은 날짜·맥락: 아직 없음 — 2026-06-20 static-analysis-quality-contract 구현에서 도출. ## 질문 의도 추론 / Why this question - 핵심 평가 대상: - "도구를 많이 넣는 것" 과 "도구 책임을 분리하는 것" 의 차이를 아는지. 같은 규칙을 두 도구가 강제하면 도구 수가 늘수록 충돌이 는다는 걸 이해하는지. - CI 가 자기 자신과 싸우는 실패 모드(무한 reformat 루프)를 예측·예방할 수 있는지. ## 답변 뼈대 / Answer skeleton - **원칙: 한 규칙은 한 도구만 소유한다.** 포매터는 *기계적으로 결정 가능한 표현*(들여쓰기, 줄바꿈, 공백, import 순서)을 소유. 린터는 *포매터가 결정 못 하는 의미*(naming, Javadoc 존재, NeedBraces/FallThrough 같은 logical 규칙)를 소유. - **나누지 않으면**: google-java-format 이 코드를 A 모양으로 고치고 Checkstyle 의 `Indentation`/`LineLength`/`CustomImportOrder` 가 그걸 위반이라 reject → 개발자가 다시 고치면 포매터가 또 A 로 → CI 무한 reformat 루프(checkstyle 이슈 #6527). 특히 import order 가 양쪽(Spotless `importOrder()` ↔ Checkstyle `CustomImportOrder`)에 다 있으면 영구 충돌. - **구체적 처리**: Checkstyle ruleset 에서 formatting 모듈(`Indentation`, `LineLength`, `WhitespaceAround`, `LeftCurly`/`RightCurly`, `SeparatorWrap`, `OperatorWrap`, `EmptyLineSeparator`)과 `CustomImportOrder` 를 **아예 빼고**, naming + Javadoc + logical 만 남긴다. google-java-format 은 100-char·결정론적 포맷이라 LineLength 도 포매터가 보장. - **검증**: `./gradlew spotlessApply && ./gradlew checkstyleMain` 을 연속 실행해 위반 0(서로 안 싸움)을 확인. 의도적 포맷 깨뜨림 후 `spotlessCheck` 가 BUILD FAILED 하는지(gate bites)도 확인. - **CI 규약**: CI 는 `spotlessApply`(파일 mutate)를 절대 실행하지 않고 `spotlessCheck`(검증)만 — 자동수정은 개발자 로컬에서. ## 꼬리 질문 / Follow-ups - "그럼 LineLength 를 누가 보장하나?" → 포매터(google-java-format 100-char). 린터에서 빼도 길이는 강제됨. - "기존 코드가 포맷·Javadoc 을 안 지키면 도입 시 어떻게?" → 포맷은 `spotlessApply` 일괄 적용(표준), Javadoc 처럼 기계수정 불가·대량인 규칙은 warning-tier 로 시작해 점진 승급(또는 ratchet). [[raw/branch-notes/feature-static-analysis-quality-contract]] §3/§4. - "관용구를 규칙이 false-positive 로 잡으면?" → 코드 rename 말고 규칙 보정(예: ConstantName 이 SLF4J `log` 를 잡으면 패턴에 `log`/`logger` 허용 — Logger 는 Google §5.2.4 상 상수가 아님). ## 관련 / Related - [[raw/branch-notes/feature-static-analysis-quality-contract]] - [[raw/blog-topics/gradle9-java21-static-analysis-baseline-2026-06-20]]