FluentValidation은 .NET 애플리케이션에서 강력한 형식(Strongly-Typed) 기반의 유효성 검사 규칙을 손쉽게 작성할 수 있도록 도와주는 오픈소스 라이브러리입니다. 유창한 인터페이스(Fluent Interface) 스타일과 람다 식(Lambda Expression)을 활용해 규칙을 선언형으로 구성할 수 있으며, 이를 통해 도메인 코드를 깔끔하게 유지하고 응집도를 높일 수 있습니다. 또한 여기저기 흩어지기 쉬운 유효성 검사 로직을 한 곳에서 체계적으로 관리할 수 있다는 점이 큰 장점입니다.
FluentValidation 패키지 설치
FluentValidation을 사용하려면 먼저 아래 NuGet 패키지를 프로젝트에 설치해야 합니다. Visual Studio의 NuGet 패키지 관리자 또는 .NET CLI를 통해 설치할 수 있습니다.
<PackageReference Include="FluentValidation" Version="9.2.2" />
예제 1: Person 모델 유효성 검사
아래 예제는 이름(FirstName), 성(LastName), 계좌 잔액(AccountBalance), 생년월일(DateOfBirth)을 가진 PersonModel 객체의 유효성을 검사하는 전체 과정을 보여줍니다. AbstractValidator<T>를 상속받는 PersonValidator 클래스에서 각 속성에 대한 검증 규칙을 정의합니다.
static class Program {
static void Main(string[] args) {
List<string> errors = new List<string>();
PersonModel person = new PersonModel();
person.FirstName = "";
person.LastName = "S";
person.AccountBalance = 100;
person.DateOfBirth = DateTime.Now.Date;
PersonValidator validator = new PersonValidator();
ValidationResult results = validator.Validate(person);
if (results.IsValid == false) {
foreach (ValidationFailure failure in results.Errors) {
errors.Add(failure.ErrorMessage);
}
}
foreach (var item in errors) {
Console.WriteLine(item);
}
Console.ReadLine();
}
}
public class PersonModel {
public string FirstName { get; set; }
public string LastName { get; set; }
public decimal AccountBalance { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class PersonValidator : AbstractValidator<PersonModel> {
public PersonValidator() {
RuleFor(p => p.FirstName)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("{PropertyName} is Empty")
.Length(2, 50).WithMessage("Length ({TotalLength}) of {PropertyName} Invalid")
.Must(BeAValidName).WithMessage("{PropertyName} Contains Invalid Characters");
RuleFor(p => p.LastName)
.Cascade(CascadeMode.StopOnFirstFailure)
.NotEmpty().WithMessage("{PropertyName} is Empty")
.Length(2, 50).WithMessage("Length ({TotalLength}) of {PropertyName} Invalid")
.Must(BeAValidName).WithMessage("{PropertyName} Contains Invalid Characters");
}
protected bool BeAValidName(string name) {
name = name.Replace(" ", "");
name = name.Replace("-", "");
return name.All(Char.IsLetter);
}
}코드 설명
- RuleFor: 검사할 대상 속성을 지정하고, 해당 속성에 적용할 규칙들을 연결합니다.
- Cascade(CascadeMode.StopOnFirstFailure): 한 속성에서 첫 번째 오류가 발생하면 나머지 규칙 검사를 중단해 불필요한 검증을 줄입니다.
- NotEmpty / Length / Must: 각각 빈 값 여부, 문자열 길이 범위, 사용자 지정 조건을 검사합니다.
BeAValidName처럼 직접 만든 메서드도Must로 연결해 사용할 수 있습니다. - WithMessage: 검증 실패 시 출력할 메시지를 지정합니다.
{PropertyName},{TotalLength}같은 자리 표시자(Placeholder)를 활용하면 동적인 메시지 작성이 가능합니다. - Validate:
validator.Validate(person)호출 결과로ValidationResult가 반환되며,IsValid속성으로 성공 여부를 확인하고Errors컬렉션에서 실패 상세 정보를 얻을 수 있습니다.
실행 결과
FirstName이 비어 있고, LastName의 길이가 최소 2자 미만이므로 콘솔에 다음과 같은 오류 메시지가 출력됩니다.
First Name is Empty Length (1) of Last Name Invalid