13 KiB
title, source_type, url, archive_url, status, confidence, related_branches, related_projects, tags, created, last_reviewed
| title | source_type | url | archive_url | status | confidence | related_branches | related_projects | tags | created | last_reviewed | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ArchUnit Annotation-as-Registry Pattern Evaluation | official-doc | https://www.archunit.org/userguide/html/000_Index.html | needs-confirmation | medium |
|
|
|
2026-05-22 | 2026-05-27 |
ArchUnit Annotation-as-Registry Pattern Evaluation
Layer:
raw/official-docs/— ArchUnit User Guide 발췌 + ca-tmpl Group G-G(feature-contract-registry-governance)의 markdown SSOT 채택에 대한 후속 대안 평가 의 외부 근거.평가 결과: ArchUnit annotation 기반 registry는 검토되었으나 채택되지 않음. markdown SSOT 유지. 본 문서는 그 결정의 근거를 보존한다.
Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| raw/branch-notes/feature-contract-registry-governance | Group G-G 결정 — "ArchUnit annotation-as-registry" 대안 평가 후 markdown SSOT 유지 결정의 근거 (annotation 의 공식 능력 범위 + registry SSOT 로 권고되지 않는다는 absence-of-evidence) |
컨텍스트 / 왜 저장했는지
ca-tmpl feature-contract-registry-governance (Group G-G)는 markdown SSOT + YAML generated constants를 contract registry 저장 형식으로 채택했다. 이때 검토되었어야 하나 상세 평가가 누락된 대안이 있다.
ArchUnit이 제공하는
@ArchTest,@AnalyzeClasses, custom@interface패턴을 그 자체로 registry로 쓰는 방식.
본 문서는 (a) ArchUnit annotation 기능이 무엇인지 인용으로 보존하고, (b) markdown SSOT vs annotation-as-registry 비교 표를 남겨, ca-tmpl 결정을 사후에 검증 가능하도록 한다.
출처 / Source
- 원본 URL (ArchUnit User Guide): https://www.archunit.org/userguide/html/000_Index.html
- 보조 URL: https://github.com/TNG/ArchUnit-Examples
- 보조 참조: Building Evolutionary Architectures (Ford, Parsons, Kua) — fitness functions 개념
- 보조 URL: https://www.baeldung.com/java-archunit-intro
- 아카이브 URL: (미수집)
- 저자 / 조직: ArchUnit 프로젝트 (TNG Technology Consulting)
- 발행 상태: ArchUnit User Guide v1.4.x 기준 지속 갱신 (2026-04 기준 최신)
- 마지막 확인일: 2026-05-27
핵심 인용 / Key quotes (verbatim)
[§JUnit support —
@ArchTest/@AnalyzeClasses] "declare ArchUnit'sArchUnitRunner(only JUnit 4), declare the classes to import via@AnalyzeClassesand add the respective rules as fields" + "The JUnit test support will automatically import (or reuse) the specified classes and evaluate any rule annotated with@ArchTestagainst those classes."
[§Custom
@interfacemeta-annotation] "@AnalyzeClassescan also be used as a meta-annotation to avoid repeating the same configuration" + "This annotation can then be used on test classes without repeating the specific configuration of@AnalyzeClasses"
[§LayeredArchitecture rule] "
layeredArchitecture()...layer("Controller").definedBy("..controller..")...whereLayer("Controller").mayNotBeAccessedByAnyLayer()"
[§Writing Custom Rules — DescribedPredicate + ArchCondition] "most architectural rules take the form: classes that ${PREDICATE} should ${CONDITION}" (implementation requires "exposing the concepts of
DescribedPredicateandArchCondition")
[§Building Evolutionary Architectures (Ford et al.)] "Architectural fitness functions — any mechanism that provides an objective integrity assessment of some architectural characteristic(s)."
Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| AAR-C1 | @ArchTest 는 ArchUnit JUnit runner 가 평가할 ArchRule field 를 마킹하는 annotation; @AnalyzeClasses 는 import 대상 classes 를 선언하는 annotation. 둘은 runner 입력 (framework annotation) 역할 |
[§JUnit support — @ArchTest / @AnalyzeClasses] "declare the classes to import via @AnalyzeClasses and add the respective rules as fields... evaluate any rule annotated with @ArchTest against those classes." |
official-vendor-doc |
ArchUnit JUnit 통합 환경 | @ArchTest/@AnalyzeClasses 가 도메인 contract registry (error code, env key 등) 를 표현하는 용도라는 뜻은 아님 — runner 입력 전용 |
| AAR-C2 | ArchUnit 공식이 안내하는 custom @interface 패턴의 명시 목적은 @AnalyzeClasses 설정 중복 제거용 meta-annotation |
[§Custom @interface meta-annotation] "@AnalyzeClasses can also be used as a meta-annotation to avoid repeating the same configuration" |
official-vendor-doc |
ArchUnit User Guide 가 안내하는 meta-annotation 패턴 | 도메인 contract 를 custom annotation 으로 registry 화 하는 것이 공식 권장 패턴이라는 뜻은 아님 (User Guide 에 명시 부재 — absence of evidence) |
| AAR-C3 | ArchUnit 의 LayeredArchitecture rule 은 DSL string + ArchRule 형태로 layer 를 정의하고 접근 제약을 표현 (.layer().definedBy("..controller..").whereLayer().mayNotBeAccessedByAnyLayer()) |
[§LayeredArchitecture rule] "layeredArchitecture()...layer("Controller").definedBy("..controller..")...whereLayer("Controller").mayNotBeAccessedByAnyLayer()" |
official-vendor-doc |
layer 기반 아키텍처 강제 | custom annotation 으로 layer 를 "등록" 하는 패턴이 공식 예제에 포함된다는 뜻은 아님 |
| AAR-C4 | ArchUnit 의 custom rule 작성 패턴은 DescribedPredicate + ArchCondition 조합으로 "classes that ${PREDICATE} should ${CONDITION}" 형식 |
[§Writing Custom Rules — DescribedPredicate + ArchCondition] "most architectural rules take the form: classes that ${PREDICATE} should ${CONDITION}" | official-vendor-doc |
custom ArchRule 작성 | 이 패턴이 SSOT registry 역할을 한다는 뜻은 아님 — 검증 (verifier) 형식 |
| AAR-C5 | Building Evolutionary Architectures 의 fitness function 정의는 "아키텍처 특성에 대한 객관적 무결성 평가를 제공하는 모든 mechanism" — ArchUnit 은 이 정의의 mechanism (verifier) 에 해당 | [§Building Evolutionary Architectures (Ford et al.)] "any mechanism that provides an objective integrity assessment of some architectural characteristic(s)." | engineering-blog (서적 출처) |
fitness function 개념 일반 | fitness function 이 SSOT 역할까지 포함한다는 정의가 있다는 뜻은 아님 — verifier 정의에 한정 |
Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
AAR-C1:@ArchTest/@AnalyzeClasses의 runner-입력 역할AAR-C2: ArchUnit User Guide 가 명시적으로 안내한 custom@interface유일 use case (=@AnalyzeClassesmeta-annotation)AAR-C3:LayeredArchitecture의 DSL string 기반 layer 정의 패턴AAR-C4: custom rule 작성의 표준 형식 (PREDICATE + CONDITION)AAR-C5: fitness function 의 정의 = mechanism/verifier
- 이 자료가 증명하지 않는 것:
- ArchUnit annotation 을 도메인 contract registry SSOT 로 권장한다는 명제 (User Guide 에 명시 부재)
- markdown SSOT vs annotation 의 우월성 비교 (본 자료는 ArchUnit 능력 정의만 — 비교 표는 ca-tmpl 자체 분석)
- polyglot stack (Python, frontend) 에서 ArchUnit annotation 이 작동한다는 명제 (JVM 한정)
- "annotation 없는 사용을 javac/ArchUnit 이 silently pass" 라는 명제 (별도 검증 메커니즘 부재 — 본 자료는 그 사실을 직접 말하지 않음)
- 내 프로젝트(ca-tmpl) 에 적용하려면 추가 확인이 필요한 것:
- markdown SSOT 의 drift 검증 스크립트 실제 구현 여부 (ca-tmpl 한계로 문서화됨)
- polyglot 환경 도래 시 IDL registry (Protobuf/Smithy) 로의 마이그레이션 결정 (raw/official-docs/schema-protobuf-vs-json-evolution 참고)
- Building Evolutionary Architectures 책 원문에서 annotation-as-SSOT 권고/반대 구절 직접 확인 (현재 needs-confirmation)
markdown SSOT vs annotation-as-registry 비교 표 (내 프로젝트 해석 — 미검증)
본 표는 자료 직접 인용 아님. ca-tmpl 자체 평가.
| 항목 | markdown SSOT + YAML generated (ca-tmpl 채택) | ArchUnit annotation-as-registry (대안) |
|---|---|---|
| 저장 위치 | branch-note + docs/registries/*.yml |
src/.../annotations/*.java (@interface 또는 marker class) |
| 사람이 읽기 | markdown table — 외부 리뷰어·비개발자도 가능 | Java 소스 — IDE/컴파일러 필요 |
| framework 종속 | 없음 (Spring/JPA/JUnit과 분리) | Java + ArchUnit lock-in |
| 다언어 재사용 | YAML 파생을 어느 언어든 로딩 가능 | JVM 한정. polyglot stack에는 부적합 |
| git diff review | 표 row 단위 변경 명확 | annotation attribute diff는 가독성 떨어짐 |
| 외부 도구 호환 | Obsidian dataview, IDE markdown 미리보기, GitHub render | ArchUnit + javac만 |
| "왜" 컨텍스트 보존 | branch-note의 결정/근거/대안 라인이 함께 위치 | annotation attribute는 짧은 string에 한정 |
| 누락 검출 | drift 검증 스크립트 자체 작성 필요 (한계) | annotation 없는 코드는 silently pass — 더 위험 |
| 변경 절차 | row 추가 → contract test → .env.example 갱신 (명문화됨) |
annotation 추가 → 새 rule field 정의. 절차가 분산 |
| fitness function 적합도 | registry는 SSOT, fitness function은 별도 verifier | annotation = SSOT + verifier 혼합. 역할 경계 흐려짐 |
| 단일 팀 적용 비용 | markdown 작성 비용만 | annotation 설계 + ArchUnit rule 작성 + maintenance |
| breaking change 정책 | row의 compatibility_impact 열로 명시 |
annotation attribute 변경 시 모든 사용처 수정 |
메모 / Notes (내 프로젝트 해석) — 평가 결론
ca-tmpl은 markdown SSOT를 유지한다. 근거:
- framework-neutral. registry는 Spring/JPA/JUnit과 분리되어야 한다. error code/env key/header/log field는 polyglot stack(예: Python sidecar, frontend)에도 동일하게 적용될 수 있어야 하며, Java annotation은 이를 막는다.
- 외부 도구 호환. Obsidian dataview, IDE markdown 미리보기, GitHub web view, LLM Wiki
/query가 모두 markdown을 1급으로 다룬다. annotation은 javac/ArchUnit/IDE plugin이 필요하다. - git diff review가 가능하다. PR review에서 비개발자(예: PM, 운영) 또는 외부 컨설턴트가 row 변경을 읽을 수 있다. annotation diff는 Java 문법 지식이 필요하다.
- "왜" 컨텍스트가 branch-note와 같이 위치. branch-note ≈ mini-ADR 패턴이 깨지지 않는다.
- annotation은 verifier로만 사용. ArchUnit은 registry가 아닌 fitness function 실행 mechanism으로만 ca-tmpl에 들어간다 (이미 §12 verification suite에 반영).
단, 다음 사실을 명시한다.
- ca-tmpl의 markdown SSOT는 drift 검증 스크립트가 미작성이다 (concept 문서 한계 섹션과 동일). annotation 방식은 javac/ArchUnit이 "어노테이션 없는 사용"을 잡을 수 있다는 강점이 있으나, 어노테이션 자체의 누락 검출이 별도로 필요하다는 점은 양쪽 모두 동일.
- 본 평가는 ca-tmpl의 단일 팀 / 단일 release train / JVM 단일 stack 컨텍스트에 한정. 멀티 팀·polyglot 환경에서는 IDL registry(Protobuf/Smithy)가 우위일 수 있으며, 이는 raw/official-docs/schema-protobuf-vs-json-evolution 참고.
추가 검증 필요 (needs-confirmation 사유)
- ArchUnit User Guide에서 "annotation을 도메인 contract registry로 권고"하는 공식 문구는 발견되지 않음. 본 문서는 ArchUnit이 그 목적으로 설계되지 않았다는 해석이며, 공식적으로 명시되지 않은 부재(absence)에 근거함.
- TNG/ArchUnit-Examples 저장소는
@ArchTest/@AnalyzeClasses사용 예제만 포함, custom@interfaceregistry 예제는 없음 (확인 완료). - Building Evolutionary Architectures 인용은 fitness function 정의 부분만 확인. annotation-as-SSOT를 권고하는 구절은 본 문서에서 확인되지 않음. 책 원문 재확인 필요.
Related / 관련
- 같은 주제 다른 official-doc:
- raw/official-docs/governance-archunit-official (ArchUnit 공식 소개)
- raw/official-docs/archunit-conditional-on-property-3-layer-pattern (Layer 2 정적 검사 가능 범위)
- 인용하는 branch:
- raw/branch-notes/feature-contract-registry-governance (Group G-G 본체)
- canonical contract 섹션:
- raw/project-notes/ca-skeleton-operational-contract — §21 Contract Registry, §29 Group G-G
- 관련 wiki: