Files
llm-wiki/raw/interviews/archunit-static-analysis-limits.md

10 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label
title source_type status related_branches related_projects tags created status_label
interview-prep / archunit-static-analysis-limits interview-prep raw
feature-architecture-enforcement-rules
feature-application-port-usecase-contract
ca-skeleton
interview-prep
ca-skeleton
archunit
fitness-function
static-analysis
reflection
2026-05-28 collecting

interview-prep: archunit-static-analysis-limits

Layer: raw/interviews/ — 면접 질문 원본 수집·연구 노트. 다듬어진 답변은 /interviewizewiki/interview/ 에 별도 작성.

Parent / 부모

질문 / Question

  • 질문 원문: ArchUnit 같은 정적 분석 기반 fitness function 의 한계 를 인지하면서 어떻게 믿을 수 있게 만들었나요? runtime reflection 우회 / 빈 scope 의 vacuous pass / generated code 처리 같은 케이스는 어떻게 다뤘나요?
  • 출처: 예상 질문 (실 면접 아님).
  • 받은 날짜·맥락: 아직 없음.

질문 의도 추론 / Why this question

  • 핵심 평가 대상:
    • 정적 분석의 한계구체적 으로 인지하는지 (단순히 "있다" 가 아니라 어떤 코드 패턴이 catch 되지 않는지).
    • vacuous pass 함정 (scope 가 비어 있을 때도 SUCCESS 반환) 을 인지하고 negative test 로 보완 했는지.
    • runtime bypass 를 code review checklist / Sonar / Spring Modulith 같은 보완 도구 로 메우는 감각.
    • generated code (MapStruct, Lombok, Spring AOT) 와 fitness function 의 충돌 처리.
  • 함정 / 흔히 빠지는 답변 패턴:
    • "ArchUnit 으로 다 막을 수 있다" — reflection / ApplicationContext#getBean(String) / Class.forName(String) 의 catch 불가 인식 없음.
    • "rule 이 있으면 catch 된다고 믿는다" — vacuous pass 가능성 인지 못함.
    • generated code 를 rule 의 예외 로 처리하지 못해 build 가 깨지는 시나리오.
  • 따라올 만한 후속 질문:
    • noClasses().that(...) rule 이 빈 scope 에서 어떤 동작인가요? 어떻게 vacuous pass 를 막을 수 있나요?
    • ApplicationContext#getBean(String) 은 왜 ArchUnit 이 못 잡나요? getBean(Class) 는 어떻게 다른가요?
    • MapStruct generated mapper 를 mapper boundary rule 에 어떻게 예외 처리하나요? Spring AOT 와는?
    • custom ArchCondition 은 언제 필요하나요? 예시?

답변 재료 / Raw answer material

  • 사실 1 (근거: feature-architecture-enforcement-rules.md D11): ArchUnit 의 banned-class rule (noClasses().that(pkg).should().dependOnClassesThat().haveFullyQualifiedName("...ApplicationContext")) 은 class literal 이 bytecode 에 박힌 의존만 catch. ca-tmpl 의 application_does_not_depend_on_application_context 가 이 패턴.
  • 사실 2 (근거: feature-architecture-enforcement-rules.md D12 + raw/official-docs/archunit-user-guide.md 의 negative claim): ArchUnit 은 bytecode 의 method/constructor call 만 본다. string content 자체는 bytecode 에 노출되지만 의미 분석은 안 한다. 결과적으로 getBean("repository") 같은 string-key bean lookup 과 Class.forName(System.getenv("FOO")) 같은 dynamic target 은 catch 불가.
  • 사실 3 (근거: 파생 에러 raw/errors/archunit-test-scope-sample-ticket-inclusion-2026-05-28): ArchUnit 의 vacuous pass 함정 — @AnalyzeClasses(packages = ...) 가 패키지 필터 이고 scan source 가 아니다. 분석 대상이 0개일 때도 rule 은 SUCCESS. ca-tmpl 의 첫 시도에서 app-bootstrap 의 test classpath 가 sample-ticket 을 안 보아 새 rule 이 vacuously pass 한 사례.
  • 사실 4 (근거: feature-architecture-enforcement-rules.md Claims to Verify 마지막 행 actually-implemented + feature-application-port-usecase-contract.md 구현 결과 round 2): ca-tmpl 의 보완 — Spring Modulith example/ninvalid 패턴 차용. src/app-bootstrap/src/test/java/.../violations/ 에 6 fixture + ArchitectureViolationFixtureTest 에 6 negative test. 각 rule 의 실 catch 동작 을 commit 으로 박음.
  • 사실 5 (근거: feature-architecture-enforcement-rules.md D9 + raw/official-docs/mapstruct-generated-annotation-official.md#MS-ANNOT-C1): MapStruct generated mapper 는 javax.annotation.processing.Generated 어노테이션 부착. ArchUnit .and().areNotAnnotatedWith(Generated.class)annotation-based exemption 가능. annotation FQN 주의 — MapStruct 와 Spring AOT (org.springframework.aot.generate.Generated) 가 다른 클래스.
  • 사실 6 (근거: feature-application-port-usecase-contract.md D14 + CleanArchitectureTest#notDeclareKeyedIdempotency): annotation parameter 의 enum value 검사는 ArchUnit DSL 로 표현 불가 → custom ArchCondition<JavaClass> 작성. JavaAnnotation.get("idempotency")JavaEnumConstant 를 반환하므로 reflection 없이 bytecode 만으로 enum 값 catch.
  • 내가 직접 한 경험:
    • ca-tmpl 의 14개 ArchUnit rule 중 D11 의 banned-class rule + D14 의 custom ArchCondition 작성.
    • vacuous pass 사례 발견 → testImplementation project(':sample-ticket') 으로 scope 확장 → ArchitectureViolationFixtureTest 6 negative test 로 catch 동작 보증.
    • Lombok 금지 rule (lombok.. 추가 to domain_is_pure) — Lombok 이 generated bytecode 를 만들어서 domain 의 framework 독립성을 흐릴 위험 차단.
  • 트레이드오프:
    • 정적 분석 한계 인정 vs 만능 도구화: ArchUnit 으로 대부분 의 boundary 위반은 catch 가능. 단 string-key bypass / reflection / DI runtime lookup 은 catch 불가 — code review checklist + Sonar custom rule 로 보완. ca-tmpl 은 후자를 documented-only 로 유지.
    • rule 작성 비용 vs 위반 catch 정밀도: 단순 DSL rule 은 빠르지만 vacuous pass 위험. custom condition + negative test fixture 는 catch 정밀도 ↑ 이지만 작성/유지 비용 ↑. ca-tmpl 은 core rule 14개 에만 fixture 적용 (정밀도 우선).
    • generated code exemption: 너무 넓은 exemption (예: package..mapper.. 통째 제외) 은 hand-written 위반도 함께 통과. annotation-FQN 기반 exemption 이 좁고 안전 — MapStruct @Generated vs Spring AOT @Generated 의 FQN 차이 인식.
  • 한계 / "이건 안 해봤다":
    • Sonar custom rule / IDE inspection 으로 string-key bypass 를 얼마나 보완할 수 있는지 정량 측정 미수행.
    • Spring Modulith verifier 의 named interface 검증과 ca-tmpl 의 ArchUnit rule 의 중복/대체 비교 미수행.
    • ApplicationContext#getBean(Class) class-literal 호출이 ca-tmpl 의 D11 rule 로 실제 catch 되는지는 negative test 로 보증했지만, 실 사업 도메인에서의 false-positive 비율 측정 안 함.

Sources / 근거

미해결 / Unknown

  • 모르는 것: Sonar / SpotBugs custom rule 이 string-key bean lookup 류를 얼마나 잘 catch 하는지 — Sonar Quality Profile 의 표준 rule set 보강 필요.
  • 모르는 것: Spring Modulith named interface 검증의 internal model 이 ArchUnit 의 JavaClass 와 어떻게 다른지 — Modulith 도입 시 중복 rule 청산 비용.
  • 확인 방법: feature-ci-quality-gates-contract 후속 branch 에서 Sonar custom rule + Modulith verifier 도입 PoC.

답변 경계 / Answer boundary

  • 자신 있게 말할 수 있는 범위:
    • ca-tmpl 의 14 ArchUnit rule + 6 negative test fixture 의 직접 구현 범위.
    • vacuous pass 함정 두 갈래 (production 0개 매칭 vs scope 0개 매칭) 의 구체 사례보완 방법.
    • custom ArchCondition 으로 annotation parameter (enum value) catch 한 D14 의 구현 패턴.
    • MapStruct @Generated exemption 의 annotation-FQN 기반 패턴 (구현은 안 했지만 adapter-persistence/CLAUDE.md 에 example 명시).
  • "이 부분은 공식 문서를 다시 보고 답변드리겠습니다" 라고 해야 하는 부분:
    • Sonar custom rule 작성의 Quality Profile 표준 운영.
    • Spring Modulith verifier 의 named interface 구체 configuration (도입 안 했음).
    • 운영 환경에서 ArchUnit rule 변경의 CI 차단 정책 (개인 경험 없음, feature-ci-quality-gates-contract 후속).
  • 절대 과장하지 말 것:
    • "ArchUnit 으로 모든 boundary 위반을 catch 한다" 표현 금지 — D12 의 string bypass 한계가 명시됨.
    • "violations-as-data 가 fitness function 의 모든 regression 을 잡는다" 표현 금지 — negative test 자체도 정적이라 reflection bypass 는 못 잡음.
    • 운영 환경 검증 경험인 것처럼 표현 금지 — locally-verified 등급. ca-tmpl 은 template repository.