Files
llm-wiki/raw/errors/archunit-empty-should-anchor-2026-05-27.md
T

76 lines
4.4 KiB
Markdown

---
title: error / archunit-empty-should-anchor-2026-05-27
source_type: error-note
status: raw
related_branches: [feature-skeleton-package-blueprint-contract]
related_projects: [ca-skeleton]
tags: [error, ca-skeleton, architecture, testing, archunit, clean-architecture]
created: 2026-05-27
status_label: resolved
---
# error: archunit-empty-should-anchor-2026-05-27
> Layer: `raw/errors/` — 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.
## Parent / 부모
- [[raw/branch-notes/feature-skeleton-package-blueprint-contract]] — skeleton package/module blueprint 구현 중 빈 production anchor package가 ArchUnit rule의 empty check에 걸렸다.
- [[raw/project-notes/ca-skeleton-operational-contract]] — ca-tmpl skeleton의 package/module boundary 검증 이슈다.
## 증상 / Symptom
- 에러 메시지 (원문 그대로):
```text
Rule 'no classes that reside in a package '..domain..' should depend on classes that reside in any package ...' failed to check any classes.
```
- 발생 컨텍스트: `cd src && ./gradlew clean test` 실행 중 `CleanArchitectureTest`의 `domain_is_pure`, `application_does_not_depend_on_adapters_or_transport`, `persistence_adapter_does_not_depend_on_web_or_outbound_adapters`, `web_dtos_stay_in_web_adapter`가 실패.
- 발생 시점: 2026-05-27
- 발생 환경: local ca-tmpl repository.
- 재현 가능 여부: `always` — production 샘플 도메인을 `sample-ticket`으로 격리하고 본체 모듈이 anchor/package-info 중심이 되면 재현.
## 재현 절차 / Reproduction
1. production 모듈에서 reference domain/application/persistence DTO class를 제거하고 skeleton anchor만 남긴다.
2. `cd src && ./gradlew clean test`를 실행한다.
3. 기대 결과: 빈 anchor module도 skeleton blueprint의 유효한 상태로 인정된다.
4. 실제 결과: ArchUnit 기본 설정이 empty `that()` clause를 실패로 처리한다.
## 조사 단계 / Investigation log
- 2026-05-27 — full test 실행 → `CleanArchitectureTest` 4개 rule 실패.
- 2026-05-27 — test result XML 확인 → 실제 dependency violation이 아니라 검사 대상 class가 없는 empty should 실패임을 확인.
- 2026-05-27 — 빈 skeleton package가 의도된 상태인 rule에만 `allowEmptyShould(true)` 적용.
- 2026-05-27 — full `./gradlew test` 재실행 → 성공.
## 근본 원인 / Root cause
- 직접 원인: ArchUnit은 기본적으로 `that()` 조건에 매칭되는 class가 없으면 rule 실패로 처리한다.
- 근본 원인: skeleton template에서는 production domain/application/persistence/dto가 아직 비어 있을 수 있는데, 기존 ArchUnit rule은 "빈 anchor도 유효한 skeleton 상태"라는 전제를 표현하지 않았다.
- 트리거 조건: sample/reference 코드를 `sample-ticket`으로 격리하여 production 모듈의 일부 package가 빈 상태가 됨.
## Sources / 근거
- [[raw/branch-notes/feature-skeleton-package-blueprint-contract]] — 빈 anchor module과 ArchUnit guardrail을 함께 유지하기로 한 branch 결정.
- [[wiki/projects/ca-tmpl/clean-architecture-package-layout]] — ca-tmpl에 실제 적용된 module/package layout canonical.
## 해결 / Resolution
- 적용한 조치: 빈 상태가 skeleton contract상 유효한 rule에만 `allowEmptyShould(true)`를 붙였다.
- 검증 방법:
- `cd src && ./gradlew test` 성공.
- `cd src && ./gradlew verifyCleanArchitectureDependencies` 성공.
- 잔여 위험 / 후속 작업: 실제 production domain/application class가 생긴 뒤에도 동일 rule이 의존성 위반을 잡는지 red/green test로 보강할 필요가 있다.
## 회고 / Lessons
- 빨리 감지하는 신호: ArchUnit failure message에 "failed to check any classes"가 나오면 dependency violation이 아니라 empty rule 문제일 가능성이 높다.
- 예방 체크리스트 항목 후보: skeleton anchor package를 허용하는 rule과 실제 production code가 있어야 하는 rule을 구분한다.
- wiki로 끌어올릴 가치가 있는 일반화된 교훈: template repository에서는 "아직 비어 있음"이 실패가 아니라 의도된 중간 상태일 수 있으므로 architecture test가 그 상태를 명시해야 한다.
## Related / 관련
- 트리거된 daily note: [[raw/daily-notes/2026-05-27]]
- 관련 branch note: [[raw/branch-notes/feature-skeleton-package-blueprint-contract]]
- 관련 wiki 개념: [[wiki/concepts/clean-architecture-package-layout]]