diff --git a/CLAUDE.md b/CLAUDE.md index 5face9f..cce37be 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,6 +117,72 @@ public class SubmitInquiryDto - 복잡한 검증은 서비스 로직에서 처리 - 모든 에러 메시지는 사용자 친화적 +### DataAnnotations vs FluentValidation 선택 기준 + +**DataAnnotations 사용 (현재 기본)** + +언제 사용: +- 필수/선택, 길이, 정규식 등 기본 검증 +- 대부분의 DTO 검증 + +장점: +- 프레임워크 내장 (추가 패키지 불필요) +- 간단하고 빠름 +- DTO에서 한눈에 볼 수 있음 + +```csharp +public class SubmitInquiryDto +{ + [Required] + [StringLength(100)] + public string Name { get; set; } + + [Required] + [RegularExpression(@"^01[0-9]\d{7,8}$")] + public string Phone { get; set; } +} +``` + +**FluentValidation 사용 (필요시 도입)** + +언제 사용: +- 조건부 검증 (필드 A가 있으면 필드 B는 필수) +- 데이터베이스 조회 필요한 검증 (중복 체크) +- 복잡한 비즈니스 규칙 검증 +- 여러 필드 간 관계 검증 + +도입 절차: +1. `FluentValidation` NuGet 패키지 추가 +2. `AbstractValidator` 상속한 검증기 클래스 생성 +3. `Program.cs`에 등록 +4. 서비스 또는 엔드포인트에서 검증기 주입 + +```csharp +public class SubmitInquiryValidator : AbstractValidator +{ + public SubmitInquiryValidator() + { + RuleFor(x => x.Name) + .NotEmpty().WithMessage("이름을 입력하세요.") + .MaximumLength(100); + + RuleFor(x => x.Phone) + .NotEmpty() + .Matches(@"^01[0-9]\d{7,8}$").WithMessage("올바른 전화번호"); + + // 복잡한 검증 + RuleFor(x => x.ServiceType) + .NotEmpty() + .When(x => x.Name.Contains("법인")).WithMessage("법인은 상담분야 필수"); + } +} +``` + +**결정 규칙:** +- ✅ **기본 (지금)**: DataAnnotations +- ⏳ **필요시 (향후)**: FluentValidation 도입 +- ❌ **혼용 금지**: 같은 DTO에 두 방식 섞지 않기 + ### Telegram 알림 통합 패턴 **구현 단계:**