본문으로 건너뛰기

명세 패턴

C# Functorium으로 조합 가능한 비즈니스 규칙을 구현하는 실전 가이드


Repository 메서드가 끝없이 늘어나고, 비즈니스 규칙이 서비스 코드 곳곳에 흩어져 있다면 — Specification 패턴이 해답일 수 있습니다.

이 튜토리얼은 Specification 패턴을 활용한 도메인 규칙 구현을 단계별로 학습할 수 있도록 구성된 종합적인 교육 과정입니다. 기본적인 Specification 클래스에서 시작하여 Expression Tree 기반 Repository 통합까지, 18개의 실습 프로젝트를 통해 Specification 패턴의 모든 측면을 체계적으로 학습할 수 있습니다.

단순한 조건 분기에서 시작하여 조합 가능한 비즈니스 규칙으로 진화하는 과정을 함께 경험해보세요.

수준대상권장 학습 범위
초급C# 기본 문법을 알고 Specification 패턴에 입문하려는 개발자Part 1
중급패턴을 이해하고 실전 적용을 원하는 개발자Part 1~3
고급아키텍처 설계와 도메인 모델링에 관심 있는 개발자Part 4~5 + 부록

이 튜토리얼을 완료하면 다음을 할 수 있습니다:

  1. Specification 패턴의 개념과 필요성을 이해하고 설명
  2. And, Or, Not 조합으로 복합 비즈니스 규칙 구현
  3. Expression Tree를 활용한 ORM 호환 Specification 구현
  4. Repository와 Specification 통합으로 유연한 데이터 조회
  5. 테스트 전략을 적용한 신뢰할 수 있는 도메인 규칙 검증

서론에서는 Specification 패턴의 개념과 환경 설정을 다룹니다.

기본 Specification부터 연산자 오버로딩과 항등원까지 학습합니다.

주제핵심 학습 내용
1첫 번째 SpecificationSpecification 상속, IsSatisfiedBy 구현
2조합And, Or, Not 메서드 조합
3연산자&,
4All 항등원All 항등원, 동적 필터 체이닝

Expression Tree 기반 Specification으로 ORM 통합을 준비합니다.

주제핵심 학습 내용
1Expression 소개Expression Tree 개념과 필요성
2ExpressionSpecification 클래스sealed IsSatisfiedBy, 델리게이트 캐싱
3Value Object 변환 패턴Value Object→primitive 변환
4Expression ResolverTryResolve, 재귀 합성

Specification과 Repository를 통합하여 유연한 데이터 조회를 구현합니다.

주제핵심 학습 내용
1Repository와 SpecificationRepository 메서드 폭발 방지
2InMemory 구현InMemory 어댑터
3PropertyMapPropertyMap, TranslatingVisitor
4EF Core 구현TryResolve + Translate 조합

실전 프로젝트에서 Specification 패턴을 활용하는 방법을 학습합니다.

주제핵심 학습 내용
1Usecase 패턴CQRS에서 Spec 활용
2동적 필터 빌더All 시드 조건부 체이닝
3테스트 전략Spec/조합/Usecase 테스트
4아키텍처 규칙네이밍, 폴더 배치, ArchUnitNET

다양한 도메인에서 Specification 패턴을 적용하는 실전 예제입니다.


Part 1
1장: 첫 번째 Spec → 2장: And/Or/Not 조합 → 3장: 연산자 오버로딩 → 4장: All 항등원
Part 2
1장: Expression 소개 → 2장: ExpressionSpec → 3장: VO 변환 패턴 → 4장: Expression Resolver
Part 3
1장: Repository 통합 → 2장: InMemory 구현 → 3장: PropertyMap → 4장: EF Core 구현
Part 4
1장: Usecase 패턴 → 2장: 동적 필터 → 3장: 테스트 전략 → 4장: 아키텍처 규칙

이 튜토리얼에서 다루는 Functorium의 핵심 타입 계층은 다음과 같습니다.

Specification<T> (추상 클래스)
├── IsSatisfiedBy(T) : bool
├── And() / Or() / Not()
├── & / | / ! 연산자
└── All (항등원)
IExpressionSpec<T> (인터페이스)
└── ToExpression() : Expression<Func<T, bool>>
ExpressionSpecification<T> : Specification<T>, IExpressionSpec<T>
├── abstract ToExpression()
├── sealed IsSatisfiedBy (컴파일 + 캐싱)
└── AllSpecification<T> (internal, 항등원: _ => true)
SpecificationExpressionResolver (Expression 합성)
PropertyMap<TEntity, TModel> (Entity→Model 변환)

  • .NET 10.0 SDK 이상
  • VS Code + C# Dev Kit 확장
  • C# 기초 문법 지식

specification-pattern/
├── Part0-Introduction/ # Part 0: 서론
├── Part1-Specification-Basics/ # Part 1: Specification 기초 (4개)
│ ├── 01-First-Specification/
│ ├── 02-Composition/
│ ├── 03-Operators/
│ └── 04-All-Identity/
├── Part2-Expression-Specification/ # Part 2: Expression Specification (4개)
│ ├── 01-Expression-Introduction/
│ ├── 02-ExpressionSpecification-Class/
│ ├── 03-ValueObject-Primitive-Conversion/
│ └── 04-Expression-Resolver/
├── Part3-Repository-Integration/ # Part 3: Repository 통합 (4개)
│ ├── 01-Repository-With-Specification/
│ ├── 02-InMemory-Implementation/
│ ├── 03-PropertyMap/
│ └── 04-EfCore-Implementation/
├── Part4-Real-World-Patterns/ # Part 4: 실전 패턴 (4개)
│ ├── 01-Usecase-Patterns/
│ ├── 02-Dynamic-Filter-Builder/
│ ├── 03-Testing-Strategies/
│ └── 04-Architecture-Rules/
├── Part5-Domain-Examples/ # Part 5: 도메인별 실전 예제 (2개)
│ ├── 01-Ecommerce-Product-Filtering/
│ └── 02-Customer-Management/
├── Appendix/ # 부록
└── index.md # 이 문서

모든 Part의 예제 프로젝트에는 단위 테스트가 포함되어 있습니다. 테스트는 단위 테스트 가이드를 따릅니다.

Terminal window
# 튜토리얼 전체 빌드
dotnet build specification-pattern.slnx
# 튜토리얼 전체 테스트
dotnet test --solution specification-pattern.slnx

Part 1: Specification 기초 (4개)

테스트 프로젝트주요 테스트 내용
1FirstSpecification.Tests.UnitIsSatisfiedBy 동작 검증
2Composition.Tests.UnitAnd, Or, Not 조합 검증
3Operators.Tests.Unit연산자 오버로딩 검증
4AllIdentity.Tests.UnitAll 항등원, 동적 체이닝

Part 2: Expression Specification (4개)

테스트 프로젝트주요 테스트 내용
1ExpressionIntro.Tests.UnitExpression Tree 기본
2ExpressionSpec.Tests.Unitsealed IsSatisfiedBy, 캐싱
3ValueObjectConversion.Tests.UnitVO→primitive 변환
4ExpressionResolver.Tests.UnitTryResolve, 재귀 합성

Part 3: Repository 통합 (4개)

테스트 프로젝트주요 테스트 내용
1RepositorySpec.Tests.UnitRepository + Spec 통합
2InMemoryImpl.Tests.UnitInMemory 어댑터
3PropertyMapDemo.Tests.UnitPropertyMap, TranslatingVisitor
4EfCoreImpl.Tests.UnitEF Core TryResolve + Translate

Part 4: 실전 패턴 (4개)

테스트 프로젝트주요 테스트 내용
1UsecasePatterns.Tests.UnitCQRS + Spec 활용
2DynamicFilter.Tests.Unit동적 필터 체이닝
3TestingStrategies.Tests.UnitSpec 테스트 패턴
4ArchitectureRules.Tests.Unit아키텍처 규칙 검증

Part 5: 도메인별 실전 예제 (2개)

테스트 프로젝트주요 테스트 내용
1EcommerceFiltering.Tests.Unit상품 필터링 Spec
2CustomerManagement.Tests.Unit고객 관리 Spec

T1_T2_T3 명명 규칙을 따릅니다:

// Method_ExpectedResult_Scenario
[Fact]
public void IsSatisfiedBy_ReturnsTrue_WhenProductIsActive()
{
// Arrange
var spec = new ActiveProductSpec();
var product = new Product { IsActive = true };
// Act
var actual = spec.IsSatisfiedBy(product);
// Assert
actual.ShouldBeTrue();
}

이 튜토리얼의 모든 예제 코드는 Functorium 프로젝트에서 확인할 수 있습니다:

  • 프레임워크 타입: Src/Functorium/Domains/Specifications/
  • 튜토리얼 프로젝트: Docs.Site/src/content/docs/tutorials/specification-pattern/

이 튜토리얼은 다음 튜토리얼과 함께 학습하면 더 효과적입니다:


이 튜토리얼은 Functorium 프로젝트의 실제 Specification 프레임워크 개발 경험을 바탕으로 작성되었습니다.