10 KiB
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 |
|
|
|
2026-05-28 | collecting |
interview-prep: archunit-static-analysis-limits
Layer:
raw/interviews/— 면접 질문 원본 수집·연구 노트. 다듬어진 답변은/interviewize후wiki/interview/에 별도 작성.
Parent / 부모
- raw/branch-notes/feature-architecture-enforcement-rules — D11 (
ApplicationContext금지) + D12 (string-key bypass 한계) + Claims to Verify 의 violations-as-data 보완. - raw/project-notes/ca-skeleton-operational-contract — ca-tmpl skeleton 의 boundary 자동 검증 정책 맥락.
질문 / 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 가 깨지는 시나리오.
- "ArchUnit 으로 다 막을 수 있다" — reflection /
- 따라올 만한 후속 질문:
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.mdD11): 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.mdD12 +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.mdClaims to Verify 마지막 행actually-implemented+feature-application-port-usecase-contract.md구현 결과 round 2): ca-tmpl 의 보완 — Spring Modulithexample/ninvalid패턴 차용.src/app-bootstrap/src/test/java/.../violations/에 6 fixture +ArchitectureViolationFixtureTest에 6 negative test. 각 rule 의 실 catch 동작 을 commit 으로 박음. - 사실 5 (근거:
feature-architecture-enforcement-rules.mdD9 +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.mdD14 +CleanArchitectureTest#notDeclareKeyedIdempotency): annotation parameter 의 enum value 검사는 ArchUnit DSL 로 표현 불가 → customArchCondition<JavaClass>작성.JavaAnnotation.get("idempotency")가JavaEnumConstant를 반환하므로 reflection 없이 bytecode 만으로 enum 값 catch. - 내가 직접 한 경험:
- ca-tmpl 의 14개 ArchUnit rule 중
D11의 banned-class rule +D14의 customArchCondition작성. - vacuous pass 사례 발견 →
testImplementation project(':sample-ticket')으로 scope 확장 →ArchitectureViolationFixtureTest6 negative test 로 catch 동작 보증. - Lombok 금지 rule (
lombok..추가 todomain_is_pure) — Lombok 이 generated bytecode 를 만들어서 domain 의 framework 독립성을 흐릴 위험 차단.
- ca-tmpl 의 14개 ArchUnit rule 중
- 트레이드오프:
- 정적 분석 한계 인정 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@Generatedvs 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 / 근거
- raw/branch-notes/feature-architecture-enforcement-rules — D9, D11, D12 + Claims to Verify status.
- raw/branch-notes/feature-application-port-usecase-contract — D14 custom ArchCondition + violations-as-data round 2.
- raw/errors/archunit-test-scope-sample-ticket-inclusion-2026-05-28 — vacuous pass 의 실 사례.
- raw/official-docs/archunit-user-guide —
JavaAnnotation/JavaEnumConstant/EvaluationResult공식 (ARCHUNIT-UG-C5,ARCHUNIT-UG-C6). - raw/official-docs/mapstruct-generated-annotation-official —
@GeneratedFQN (MS-ANNOT-C1,MS-ANNOT-C2). - raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data —
annotatedWith(Generated.class)predicate +example/ninvalid패턴 (SPRING-MOD-AU-C1,SPRING-MOD-AU-C2).
미해결 / 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
@Generatedexemption 의 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.
Related / 관련
- 관련 면접 질문 (선행/후속): raw/interviews/clean-architecture-boundary-enforcement (선행 — boundary 자동 검증의 자매), raw/interviews/clean-architecture-module-blueprint (선행 — module 분리의 왜), raw/interviews/transaction-port-vs-spring-transactional (자매 — application framework 격리).
- 영감을 받은 채용공고: (없음).
- 관련 블로그 글감: raw/blog-topics/archunit-violations-as-data-pattern-2026-05-28 (같은 작업의 글감).
- 답변 derive 후 위치: 생성 전. 후보
wiki/interview/architecture/archunit-static-analysis-limits.md.