이 문서는 Functorium의 아키텍처 규칙이 각 레이어와 패턴에 대해 어느 수준까지 검증되는지 보여주는 커버리지 매트릭스입니다. 아키텍처 테스트의 현재 범위를 파악하거나, 추가 규칙이 필요한 영역을 식별할 때 참고하세요.
ArchRuleDefinition . Classes () . That ()
. ImplementInterface ( typeof (IValueObject))
. ValidateAllClasses (Architecture, @class => @class
. RequirePublic () . RequireSealed () . RequireImmutable ())
. ThrowIfAnyFailures ( " ValueObject Rule " );
// DelegateArchRule로 커스텀 규칙
var rule = new DelegateArchRule<Class>(
" No infrastructure suffixes " ,
(target, _) => target . Name . EndsWith ( " Dto " )
? [ new RuleViolation( target . FullName , " Naming " , " ... " )]
// CompositeArchRule로 규칙 합성
var composite = new CompositeArchRule<Class>(
new ImmutabilityRule(), namingRule, dependencyRule);
// ArchUnitNET 필터로 레이어 의존성 검증
Types () . That () . ResideInNamespace (DomainNamespace)
. Should () . NotDependOnAnyTypesThat ()
. ResideInNamespace (ApplicationNamespace)
1. 규칙 검증 가능 여부 판별:
ClassValidator/InterfaceValidator/MethodValidator API에 1:1 매핑되는가? → ✅ 직접 지원
IArchRule<T> / DelegateArchRule<T>로 구현 가능한가? → 🔧 커스텀 규칙
ArchUnitNET의 ArchRuleDefinition 필터로 검증 가능한가? → ⚠️ ArchUnitNET 필터
어셈블리 메타데이터/IL 수준에서 판별 불가능한가? → ❌ 검증 불가
2. 새 아키텍처 규칙 추가:
가이드 문서에서 규칙 식별
이 매트릭스에서 검증 가능 여부 확인
적합한 API 선택 (✅ > 🔧 > ⚠️ 순)
테스트 클래스에 규칙 추가
1. 커버리지 통계
검증 상태 기호 규칙 수 비율 직접 지원 ✅ 55 57% 커스텀 규칙 🔧 9 9% ArchUnitNET 필터 ⚠️ 10 10% 검증 불가 ❌ 23 24% 합계 97 100%
2. 검증 가능 합계: 74건 (76%) — 프레임워크로 자동 검증 가능
3. ArchitectureRules API 구성
컴포넌트 역할 ClassValidator클래스 수준 규칙 (visibility, modifier, inheritance, constructor, method, property, naming) InterfaceValidator인터페이스 수준 규칙 (naming, inheritance, method) MethodValidator메서드 수준 규칙 (visibility, static, return type, parameter) IArchRule<T>커스텀 규칙 확장 인터페이스 DelegateArchRule<T>람다 기반 커스텀 규칙 CompositeArchRule<T>여러 규칙의 AND 합성 ImmutabilityRule불변성 종합 검증 (6가지 차원)
요약에서 커버리지 통계와 API 구성을 확인했습니다. 이제 검증에 사용하는 API를 상세히 살펴본 뒤, 규칙별 커버리지 매트릭스를 검토합니다.
카테고리 메서드 설명 Visibility RequirePublic(), RequireInternal()접근 제한자 Modifier RequireSealed(), RequireNotSealed()sealed 여부 Modifier RequireStatic(), RequireNotStatic()static 여부 Modifier RequireAbstract(), RequireNotAbstract()abstract 여부 Type RequireRecord(), RequireNotRecord()record 여부 Type RequireAttribute(string)특정 어트리뷰트 존재 Inheritance RequireInherits(Type)기본 클래스 상속 Inheritance RequireImplements(Type)인터페이스 구현 Inheritance RequireImplementsGenericInterface(string)제네릭 인터페이스 구현 Constructor RequireAllPrivateConstructors()모든 생성자 private Constructor RequirePrivateAnyParameterlessConstructor()매개변수 없는 private 생성자 Property RequireNoPublicSetters()public setter 금지 Property RequireOnlyPrimitiveProperties(params string[])원시 타입 프로퍼티만 허용 Property RequireProperty(string)특정 프로퍼티 존재 Field RequireNoInstanceFields()인스턴스 필드 금지 Method RequireMethod(string, Action<MethodValidator>)특정 메서드 검증 Method RequireAllMethods(Action<MethodValidator>)모든 메서드 검증 Method RequireAllMethods(Func<MethodMember, bool>, Action<MethodValidator>)필터링된 메서드 검증 Method RequireMethodIfExists(string, Action<MethodValidator>)메서드 존재 시 검증 Naming RequireNameStartsWith(string)이름 접두사 Naming RequireNameEndsWith(string)이름 접미사 Naming RequireNameMatching(string)정규식 패턴 매칭 Dependency RequireNoDependencyOn(string)특정 타입 의존 금지 Nested RequireNestedClass(string, Action<ClassValidator>?)중첩 클래스 필수 Nested RequireNestedClassIfExists(string, Action<ClassValidator>?)중첩 클래스 존재 시 검증 Immutability RequireImmutable()불변성 종합 검증 Composition Apply(IArchRule<TType>)커스텀 규칙 적용
카테고리 메서드 설명 Visibility RequireVisibility(Visibility)접근 제한자 Modifier RequireStatic(), RequireNotStatic()static 여부 Modifier RequireExtensionMethod()확장 메서드 여부 Modifier RequireVirtual(), RequireNotVirtual()virtual 여부 Return RequireReturnType(Type)반환 타입 검증 Return RequireReturnTypeOfDeclaringClass()선언 클래스 반환 Return RequireReturnTypeOfDeclaringTopLevelClass()최상위 클래스 반환 Return RequireReturnTypeContaining(string)반환 타입 이름 포함 Parameter RequireParameterCount(int)매개변수 개수 Parameter RequireParameterCountAtLeast(int)최소 매개변수 개수 Parameter RequireFirstParameterTypeContaining(string)첫 번째 매개변수 타입 Parameter RequireAnyParameterTypeContaining(string)임의 매개변수 타입
타입 용도 예시 IArchRule<TType>커스텀 규칙 인터페이스 ImmutabilityRule : IArchRule<Class>DelegateArchRule<TType>람다 기반 인라인 규칙 인프라 접미사 금지, 인프라 네임스페이스 의존 금지 CompositeArchRule<TType>여러 규칙 AND 합성 ImmutabilityRule + 네이밍 + 의존성 = ValueObject 핵심 규칙
API 요약에서 사용 가능한 검증 도구를 확인했습니다. 이제 가이드 문서에 정의된 97개 규칙 각각의 자동 검증 가능 여부를 매트릭스로 정리합니다.
검증 가능 상태 범례:
기호 상태 설명 ✅ 직접 지원 ClassValidator / InterfaceValidator / MethodValidator 기존 API로 검증 🔧 커스텀 규칙 IArchRule<T> 또는 DelegateArchRule<T>로 구현 가능⚠️ ArchUnitNET 필터 ArchRuleDefinition 필터 + Should() 체인으로 검증❌ 검증 불가 사유 명시
규칙 출처 검증 가능 사용 API / 불가 사유 public sealed 클래스05a ✅ RequirePublic() + RequireSealed()불변성 (6가지 차원) 05a ✅ RequireImmutable() (ImmutabilityRule)모든 생성자 private 05a ✅ RequireAllPrivateConstructors()Create() 팩토리 (public static, Fin<T> 반환)05a ✅ RequireMethod("Create", m => m.RequireStatic().RequireReturnType(typeof(Fin<>)))Validate() 메서드 (public static, Validation<,> 반환)05a ✅ RequireMethod("Validate", m => m.RequireStatic().RequireReturnType(typeof(Validation<,>)))IValueObject 인터페이스 구현05a ⚠️ ArchUnitNET 필터: .ImplementInterface(typeof(IValueObject)) IEquatable<> 구현05a ✅ RequireImplements(typeof(IEquatable<>))SimpleValueObject<T> 또는 ValueObject 상속05a ✅ RequireInherits(typeof(SimpleValueObject<>))중첩 DomainErrors 클래스 규칙 08b ✅ RequireNestedClassIfExists("DomainErrors", ...)implicit operator 정의 05a 🔧 DelegateArchRule: op_Implicit 메서드 존재 확인ValidationRules<T> 사용05a ❌ 소스 코드 분석 필요 (IL에서 호출 패턴 추적 불가) CreateFromValidation() 패턴 사용05a ❌ 소스 코드 분석 필요 인프라 접미사 금지 (Dto, ViewModel 등) 04 🔧 DelegateArchRule: 금지 접미사 패턴 매칭인프라 네임스페이스 의존 금지 04 🔧 DelegateArchRule: 의존성 네임스페이스 검사
규칙 출처 검증 가능 사용 API / 불가 사유 public sealed 클래스06b ✅ RequirePublic() + RequireSealed()Not static 06b ✅ RequireNotStatic()AggregateRoot<TId> 상속06b ✅ RequireInherits(typeof(AggregateRoot<>))Entity<TId> 상속 (일반 Entity)06b ✅ RequireInherits(typeof(Entity<>))[GenerateEntityId] 어트리뷰트06b ✅ RequireAttribute("GenerateEntityId")모든 생성자 private 06b ✅ RequireAllPrivateConstructors()매개변수 없는 private 생성자 (ORM) 06b ✅ RequirePrivateAnyParameterlessConstructor()Create() 팩토리 (선언 클래스 반환)06b ✅ RequireMethod("Create", m => m.RequireStatic().RequireReturnTypeOfDeclaringClass())CreateFromValidated() 팩토리06b ✅ RequireMethod("CreateFromValidated", m => m.RequireStatic().RequireReturnTypeOfDeclaringClass())Create()에서 AddDomainEvent() 호출06b ❌ 소스 코드 분석 필요 (메서드 본문 검증 불가) 가변 컬렉션 직접 노출 금지 06b 🔧 DelegateArchRule: public 프로퍼티의 반환 타입에서 List<> 등 탐지IConcurrencyAware 구현 (선택적)06c ✅ RequireImplements(typeof(IConcurrencyAware))인프라 접미사 금지 04 🔧 DelegateArchRule: 금지 접미사 패턴 매칭인프라 네임스페이스 의존 금지 04 🔧 DelegateArchRule: 의존성 네임스페이스 검사
규칙 출처 검증 가능 사용 API / 불가 사유 sealed record07 ✅ RequireSealed() + RequireRecord()이름이 “Event”로 끝남 07 ✅ RequireNameEndsWith("Event")DomainEvent 기반 클래스 상속07 ✅ RequireInherits(typeof(DomainEvent))AggregateRoot 내부에 중첩 정의 07 🔧 DelegateArchRule: 타입의 DeclaringType 검사과거 시제 이름 (Created, Shipped 등) 07 ❌ 의미론적 분석 필요 (자연어 시제 판별 불가)
참고: 아래 규칙 중 “Stateless (인스턴스 필드 없음)“과 “Public 메서드 Fin 반환”은 순수 패턴(기본)에 적용됩니다.
Evans Ch.9 Repository 패턴에서는 Repository 인터페이스 참조 필드가 허용되고, 반환 타입이 FinT<IO, T>입니다.
프로젝트에서 Repository 패턴을 사용하는 경우 해당 규칙을 조정하세요. 상세: 09-domain-services.md
규칙 출처 검증 가능 사용 API / 불가 사유 public sealed 클래스09 ✅ RequirePublic() + RequireSealed()IDomainService 구현09 ⚠️ ArchUnitNET 필터: .ImplementInterface(typeof(IDomainService)) Stateless (인스턴스 필드 없음) 09 ✅ RequireNoInstanceFields() (순수 패턴에 적용)IObservablePort 의존 금지09 ✅ RequireNoDependencyOn("IObservablePort")Public 메서드 Fin 반환 09 ✅ RequireAllMethods(filter, m => m.RequireReturnTypeContaining("Fin")) (순수 패턴에 적용; Evans 패턴은 FinT 반환)Record 금지 09 ✅ RequireNotRecord()순수 함수, I/O 없음 09 ❌ 런타임 동작 검증 (정적 분석 한계)
규칙 출처 검증 가능 사용 API / 불가 사유 public sealed 클래스10 ✅ RequirePublic() + RequireSealed()Specification<T> 상속10 ✅ RequireInherits(typeof(Specification<>))Domain 레이어에 위치 10 ⚠️ ArchUnitNET: .Should().ResideInNamespaceMatching() ToExpression() 오버라이드10 🔧 DelegateArchRule: 메서드 존재 및 virtual override 확인
규칙 출처 검증 가능 사용 API / 불가 사유 중첩 DomainErrors 클래스 (internal sealed) 08b ✅ RequireNestedClassIfExists("DomainErrors", n => n.RequireInternal().RequireSealed())DomainErrors 메서드 (public static, Error 반환) 08b ✅ .RequireAllMethods(m => m.RequireStatic().RequireReturnType(typeof(Error)))DomainError.For<T>() 팩토리 패턴 사용08a ❌ 소스 코드 분석 필요 (메서드 본문의 호출 패턴) 에러 코드 형식 (DomainErrors.Type.Name) 08a ❌ 런타임 검증 필요 (단위 테스트로 검증) Custom 에러 타입이 sealed record 08b 🔧 DelegateArchRule: 특정 네임스페이스의 Error 파생 타입 검사
규칙 출처 검증 가능 사용 API / 불가 사유 Command 클래스 sealed 11 ✅ RequireSealed()Command 내부 Request (sealed record, ICommandRequest) 11 ✅ RequireNestedClass("Request", n => n.RequireSealed().RequireRecord().RequireImplementsGenericInterface("ICommandRequest"))Command 내부 Response (sealed record) 11 ✅ RequireNestedClass("Response", n => n.RequireSealed().RequireRecord())Command 내부 Usecase (sealed, ICommandUsecase) 11 ✅ RequireNestedClass("Usecase", n => n.RequireSealed().RequireImplementsGenericInterface("ICommandUsecase"))Query 클래스 sealed 11 ✅ RequireSealed()Query 내부 Request (sealed record, IQueryRequest) 11 ✅ RequireNestedClass("Request", n => n.RequireSealed().RequireRecord().RequireImplementsGenericInterface("IQueryRequest"))Query 내부 Response (sealed record) 11 ✅ RequireNestedClass("Response", n => n.RequireSealed().RequireRecord())Query 내부 Usecase (sealed, IQueryUsecase) 11 ✅ RequireNestedClass("Usecase", n => n.RequireSealed().RequireImplementsGenericInterface("IQueryUsecase"))Request/Response는 원시 타입 프로퍼티만 허용 11 ✅ RequireOnlyPrimitiveProperties()Usecase는 ValueTask<FinResponse<T>> 반환 11 ❌ 인터페이스가 강제하므로 별도 검증 불필요 (컴파일러 보장) FinT<IO, T> LINQ 체인 사용11 ❌ 소스 코드 분석 필요
규칙 출처 검증 가능 사용 API / 불가 사유 Query Usecase가 IRepository에 의존 금지 11 ⚠️ ArchUnitNET: .Should().NotDependOnAnyTypesThat().HaveNameEndingWith("Repository") Command 이름이 “Command”로 끝남 11 ⚠️ ArchUnitNET 필터: .HaveNameEndingWith("Command") Query 이름이 “Query”로 끝남 11 ⚠️ ArchUnitNET 필터: .HaveNameEndingWith("Query")
규칙 출처 검증 가능 사용 API / 불가 사유 Validator가 AbstractValidator 상속 14a ✅ RequireImplementsGenericInterface("AbstractValidator")Sealed 클래스 14a ✅ RequireSealed()Usecase 내부에 중첩 (선택적) 11 ✅ RequireNestedClassIfExists("Validator", ...)
규칙 출처 검증 가능 사용 API / 불가 사유 ApplicationError.For<T>() 팩토리 패턴 사용08b ❌ 소스 코드 분석 필요 에러 코드 형식 (ApplicationErrors.Usecase.Name) 08b ❌ 런타임 검증 필요 Shared Application DTO (sealed record, primitive) 17 ✅ RequireSealed() + RequireRecord() + RequireOnlyPrimitiveProperties()
규칙 출처 검증 가능 사용 API / 불가 사유 Repository 네이밍 (I 접두사) 12 ✅ RequireNameStartsWith("I") (InterfaceValidator)Repository가 IObservablePort 구현 12 ✅ RequireImplements(typeof(IObservablePort))Repository 메서드가 FinT 반환 12 ✅ RequireAllMethods(m => m.RequireReturnTypeContaining("FinT"))Domain Port는 Domain 레이어에 위치 12 ⚠️ ArchUnitNET: .Should().ResideInNamespaceMatching() Application Port는 Application 레이어에 위치 12 ⚠️ ArchUnitNET: .Should().ResideInNamespaceMatching()
규칙 출처 검증 가능 사용 API / 불가 사유 [GenerateObservablePort] 어트리뷰트13 ✅ RequireAttribute("GenerateObservablePort")메서드가 virtual 13 ✅ RequireAllMethods(m => m.RequireVirtual())RequestCategory 프로퍼티 존재13 ✅ RequireProperty("RequestCategory")Not sealed (Observable 상속 허용) 13 ✅ RequireNotSealed()AdapterError.For<T>() 팩토리 사용08c ❌ 소스 코드 분석 필요
규칙 출처 검증 가능 사용 API / 불가 사유 Mapper는 internal static 클래스 13 ✅ RequireInternal() + RequireStatic()ToModel() 확장 메서드13 ✅ RequireMethod("ToModel", m => m.RequireStatic().RequireExtensionMethod())ToDomain() 확장 메서드13 ✅ RequireMethod("ToDomain", m => m.RequireStatic().RequireExtensionMethod())Model은 public, not sealed, POCO 13 ✅ RequirePublic() + RequireNotSealed() + RequireOnlyPrimitiveProperties()EF Core Configuration (FluentAPI) 13 ❌ 소스 코드 분석 필요
규칙 출처 검증 가능 사용 API / 불가 사유 Endpoint는 sealed 13 ✅ RequireSealed()중첩 Request (sealed record, primitive) 13 ✅ RequireNestedClassIfExists("Request", ...)중첩 Response (sealed record, primitive) 13 ✅ RequireNestedClassIfExists("Response", ...)FastEndpoints 상속 13 ❌ 제네릭 타입 매칭 복잡 (다양한 Endpoint 기반 클래스)
규칙 출처 검증 가능 사용 API / 불가 사유 등록 메서드 네이밍 (RegisterAdapter{Category}) 14a ❌ 확장 메서드 네이밍은 정적 분석 가능하나, 관례 수준 미들웨어 등록 순서 14a ❌ 런타임 동작 검증 (코드 실행 순서) OptionsConfigurator<T> 패턴 사용14a ❌ 소스 코드 분석 필요
규칙 출처 검증 가능 사용 API / 불가 사유 AdapterError.For<T>() 팩토리 패턴 사용08c ❌ 소스 코드 분석 필요 에러 코드 형식 (AdapterErrors.Adapter.Name) 08c ❌ 런타임 검증 필요
규칙 출처 검증 가능 사용 API / 불가 사유 테스트 프로젝트 폴더가 소스 구조를 미러링 15a ❌ 파일/디렉토리 구조 검증 (어셈블리 메타데이터 범위 밖) 테스트 네이밍: {Method}_{ShouldBehavior}_{Condition} 15a ❌ 테스트 메서드 이름은 IL에 있지만, 의미론적 패턴 검증 어려움 AAA (Arrange-Act-Assert) 패턴 15a ❌ 소스 코드 분석 필요 (코드 구조/주석 검증 불가) xunit.runner.json 병렬 설정15a ❌ 설정 파일 검증 (JSON 파일 파싱 필요) Shouldly assertion 사용 15a ❌ 소스 코드 분석 필요 (특정 라이브러리 호출 추적)
규칙 출처 검증 가능 사용 API / 불가 사유 Signal 접두사 (Logging, Tracing, Metrics) 18b 🔧 DelegateArchRule: 클래스 이름 패턴 매칭Component 접미사 (Logger, Span, Metric) 18b 🔧 DelegateArchRule: 클래스 이름 패턴 매칭Logger 메서드 네이밍 (Log{Context}{Phase}{Status}) 18b ❌ 소스 코드 분석 필요 (LoggerMessage 어트리뷰트 파싱) [LoggerMessage] 어트리뷰트 사용18b ❌ 메서드 수준 어트리뷰트 검증은 가능하나 partial 메서드 제약
규칙 출처 검증 가능 사용 API / 불가 사유 Domain → Application 의존 금지 01 ⚠️ ArchUnitNET: Types().Should().NotDependOnAnyTypesThat() Domain → Adapter 의존 금지 01 ⚠️ ArchUnitNET: Types().Should().NotDependOnAnyTypesThat() Application → Adapter 의존 금지 01 ⚠️ ArchUnitNET: Types().Should().NotDependOnAnyTypesThat() Adapter 간 교차 의존 금지 01 ⚠️ ArchUnitNET: Types().Should().NotDependOnAnyTypesThat()
규칙 출처 검증 가능 사용 API / 불가 사유 AssemblyReference.cs 존재01 ❌ 파일 존재 확인 (어셈블리 메타데이터 범위 밖) Using.cs 존재01 ❌ 파일 존재 확인 csproj 의존성 방향01 ❌ 설정 파일 검증 (MSBuild XML 파싱 필요) 네임스페이스 패턴 준수 01 ⚠️ ArchUnitNET: .Should().ResideInNamespaceMatching()
커버리지 매트릭스에서 24%의 규칙이 자동 검증 불가로 분류되었습니다. 이 규칙들이 왜 검증 불가한지, 어떤 대안으로 보완할 수 있는지 분석합니다.
IL(Intermediate Language) 수준에서는 메서드 본문의 로직 흐름을 추적할 수 없습니다. ArchUnitNET은 어셈블리 메타데이터(타입, 메서드 시그니처, 의존성)를 분석하지만, 메서드 내부에서 어떤 패턴을 사용하는지는 판별할 수 없습니다.
검증 불가 규칙 대안 ValidationRules<T> 사용 여부코드 리뷰, Roslyn Analyzer DomainError.For<T>() 팩토리 패턴 사용단위 테스트에서 에러 코드 검증 Create()에서 AddDomainEvent() 호출단위 테스트에서 이벤트 발행 검증 AAA 패턴, Shouldly 사용 코드 리뷰, Roslyn Analyzer FinT<IO, T> LINQ 체인 사용컴파일러가 타입 안전성 보장 [LoggerMessage] 어트리뷰트 사용로그 스냅샷 테스트로 간접 검증
어셈블리 메타데이터에는 파일 시스템 구조 정보가 포함되지 않습니다.
검증 불가 규칙 대안 테스트 폴더가 소스 구조를 미러링 빌드 스크립트, CI 검증 AssemblyReference.cs 존재빌드 스크립트, CI 검증 Using.cs 존재빌드 스크립트, CI 검증
csproj, JSON, xunit.runner.json 등의 설정 파일은 어셈블리 메타데이터 범위 밖입니다.
검증 불가 규칙 대안 csproj 의존성 방향MSBuild 타겟, CI 검증 xunit.runner.json 병렬 설정CI 검증 EF Core FluentAPI 설정 통합 테스트에서 마이그레이션 검증
정적 분석으로는 코드 실행 순서나 런타임 동작을 검증할 수 없습니다.
검증 불가 규칙 대안 Domain Service의 순수 함수/I/O 없음 코드 리뷰, 의존성 분석으로 간접 추론 미들웨어 등록 순서 통합 테스트 에러 코드 형식 일관성 단위 테스트의 ShouldFailWithErrorCode()
원인: DelegateArchRule<Class>의 target 파라미터는 ArchUnitNET의 Class 타입으로, .NET Reflection의 Type과 다릅니다.
해결: target.Dependencies, target.Members, target.Name, target.FullName 등 ArchUnitNET이 제공하는 속성을 사용하세요. 필요한 경우 Architecture 파라미터에서 추가 타입을 조회할 수 있습니다.
원인: ResideInNamespace()는 정확한 네임스페이스만 매칭합니다.
해결: ResideInNamespaceMatching($@"{BaseNamespace}\..*")으로 정규식 기반 매칭을 사용하세요.
원인: Equals, GetHashCode, ToString 등 System.Object에서 상속된 메서드가 검증 대상에 포함됩니다.
해결: 필터 오버로드를 사용하세요:
@class . RequireAllMethods (
m => m . Visibility == Visibility . Public && m . MethodForm == MethodForm . Normal ,
method => method . RequireReturnTypeContaining ( " Fin " ));
가이드에 정의된 97개 구현 규칙 중 74개가 ArchitectureRules 프레임워크로 자동 검증 가능합니다. 나머지 24%는 소스 코드 분석, 파일 구조 검증, 런타임 동작 등 정적 분석의 한계를 넘어서는 규칙이며, 단위 테스트, 코드 리뷰, CI 검증 등으로 보완해야 합니다.
✅ 직접 지원은 ClassValidator.RequireSealed()처럼 기존 API를 호출하면 되는 것이고, 🔧 커스텀 규칙은 DelegateArchRule<T> 또는 IArchRule<T> 구현을 직접 작성해야 하는 것입니다. 커스텀 규칙은 프로젝트별로 작성하며 재사용 가능합니다.
⚠️ ArchUnitNET 필터는 ArchRuleDefinition.Types().Should().NotDependOnAnyTypesThat() 같은 ArchUnitNET 자체 DSL을 사용하는 것이고, ✅ 직접 지원은 ValidateAllClasses() 이후 ClassValidator 콜백에서 사용하는 Functorium 자체 API입니다. 둘 다 테스트 코드에서 사용하지만 API 레이어가 다릅니다.
카테고리 보완 방법 소스 코드 분석 Roslyn Analyzer, 코드 리뷰 파일/디렉토리 구조 CI 빌드 스크립트, dotnet new 템플릿 설정 파일 CI 검증 스크립트 런타임 동작 단위 테스트, 통합 테스트
가이드 문서에 새 규칙을 정의합니다
이 매트릭스에서 해당 규칙의 검증 가능 여부를 판별합니다
✅/🔧/⚠️이면 아키텍처 테스트 클래스에 추가합니다
❌이면 대안(단위 테스트, CI 등)을 선택합니다
이 문서의 매트릭스를 업데이트합니다
여러 규칙을 AND로 합성하여 재사용할 때 사용합니다. 예를 들어, ValueObject의 핵심 규칙(불변성 + 네이밍 + 의존성)을 하나의 CompositeArchRule로 합성하면, 여러 테스트에서 일관되게 적용할 수 있습니다.
private static readonly CompositeArchRule<Class> s_valueObjectCoreRule = new (
s_noInfrastructureDependencyRule);
Tests.Hosts/01-SingleHost/Tests/LayeredArch.Tests.Unit/Architecture/에 13개 테스트 클래스가 구현되어 있습니다. 16-testing-library.md 의 “SingleHost 아키텍처 테스트 인벤토리”를 참조하세요.