데이터 검증(Data Validation) 메시지 지역화(Localization)

몇 일을 고민하다가 떠 오른 방법인데, 공유도 하고 싶기도 하고, 여러 분의 의견도 듣고 싶어 글을 남깁니다.

우선, 솔루션 구성은 아래와 같습니다.

Core.Models.csproj : 도메인 클래스 모음.

UI.Web.csproj : Asp.Net Core 블레이저 서버 ( default culture : ko-KR )
=> Core.Models.csproj 참조

UI.Web.Resources.ErrorMessageResource.resx : Validation 에러 메시지 한국어 자원

저는 리소스(.resx) 파일을 통해 에러 메시지를 지역화하고 싶었습니다.
아시다시피, 닷넷의 기본 Validation 도구는 이를 지원합니다.

using System.ComponentModel.DataAnnotations;
...
    [Required(
        ErrorMessageResourceName = "RequiredError", 
        ErrorMessageResourceType = typeof(ErrorMessageResource)  )]
    public string Name { get; set; } = "";
...

그런데, 문제는 데이터 어노테이션을 모델 프로젝트의 클래스에서 설정하면, 순환 참조가 일어난다는 점입니다.

UI 프로젝트는 Core 에서 정의한 모델 클래스를 참조하고,
Core 프로젝트는 UI에서 정의한 자원 클래스(ErrorMessageResource)를 참조하기 때문입니다.

물론 Custom Validator 나 FluentValidator처럼 별도의 패키지를 통해 해결이 가능하지만, 이 경우 지역화를 위해 부차적인 코드를 너무 많이 써야 하고, 코드 관리도 쉽지 않더군요.

그래서, 해결한 방법은 아래와 같이 Data Validation을 위한 별도의 프록시 모델을 UI 프로젝에 생성하고, 그곳에 어노테이션을 남기는 것입니다.

namespace Core.Models;
public class Person
{
    public string Name { get; set; }
    ...
}
namespace UI.Web.Data;
class PersonData
{
    [Required ( ErrorMessageResourceName = "RequiredError", 
        ErrorMessageResourceType = typeof(ErrorMessageResource) )]    
    public string Name 
    { 
        get => _person.Name;
        set => _person.Name = value;
    }

    private Person _person;

    public PersonData(Person person) => _person = person;
}

프록시를 위한 로직을 별도로 정의하지 않고, 닷넷의 속성 시스템을 이용하니까, 코드가 간결해지고, 관리도 쉬운 것 같습니다.

추가적으로, Data Validation 을 위해, 코어 프로젝트를 들락날락거리지 않아도 되기에, 약간의 OCP 개선도 있습니다.

2개의 좋아요