본문 바로가기
프로그래밍

Composite 패턴과 Method Chaining 방식을 활용한 Validator 구현하기

by kdohyeon (김대니) 2025. 1. 26.
반응형

배경

비즈니스 로직을 구현하다 보면, 특정 로직이 수행되기 전에 입력값이나 상태를 검증해야 하는 경우가 있다. 어떤 작업을 처리하기 위해 입력 데이터가 특정 조건을 충족해야 하는 경우를 생각해볼 수 있다.

Spring Boot 을 사용하는 환경이라면 일반적으로 각 검증을 별도 Validator 로 구현하고, 이를 스프링 빈으로 등록하여 사용할 수 있다. 이 방식에서 Validation 결과를 Errors 객체에 담아 처리하거나, 조건을 만족하지 않으면 로직 수행을 반려하는 형태로 동작한다. 하지만 이 방식에는 몇 가지 한계점이 존재하는데, Validator 를 AND 조건으로 평가해야 하며, OR 조건 등 다른 Operation 이 필요한 경우에 대한 확장성이 좀 떨어진다.

입맛에 맞게 검증 로직을 처리하기 위해서 커스텀하게 Validator 를 구현해보았다. 최대한 가독성이 좋게 구현하고자 했고, SOLID 원칙도 지켜보려고 했다. 원하는 느낌의 validation 은 아래와 같이 구현하는 것이다.

validator1.and(validator2).or(validator3).and(validator4.not())

 

위와 같은 느낌으로 만들면 각 validator 에 검증 로직을 분리하여 넣을 수 있고, 서로 연결하기도 쉬울 것이다.

Composite 패턴으로 Validator 설계

먼저 인터페이스로 Validator 를 만든다. 모든 데이터 타입을 처리할 수 있도록 Generic 으로 만든다. 검증 로직을 표현하는 validate 함수가 있고, 메소드 체이닝 (method chaining) 방식으로 각 validator 를 연결할 수 있도록 구현한다. 이번 예시에서는 and, or, not 을 구현했으며, 필요한 경우에 더 많은 operation 을 구현할 수 있다.

각 AndValidator, OrValidator, NotValidator 는 별도 클래스로 구현해야 한다.

AndValidator, OrValidator, NotValidator

AndValidator 는 두 개의 validator 를 받아서 and 조건으로 검증을 한다.

OrValidator 는 두 개의 validator 를 받아서 or 조건으로 검증을 한다.

NotValidator 는 하나의 validator 를 받아서 반대 검증을 한다.

Concrete 클래스

인터페이스를 만들었으니, 이제 각 validator 의 구현체를 만들면 된다. 이번 예시에서는 PrimeNumberValidator, LargeNumberValidator, EvenNumberValidator 총 3개의 validator 를 만들어보려고 한다.

Validator 인터페이스를 상속받아서 클래스를 만들고, validate 메소드를 구현하면 된다. 구현 방식은 아래를 참고하자.

소수인지 판단하는 PrimeNumberValidator
100 보다 큰 수인지 판단하는 LargeNumberValidator
짝수인지 판단하는 EvenNumberValidator

Validator 조립

Validator 를 사용해야 하는 곳에서 Validator 클래스를 선언하고, and, or, not operation 을 사용해서 각 validator 를 조립한다.

숫자 500 이 짝수이고 100 보다 커야 하고 소수가 아니어야 하는 조건에 충족하는지 판단한다.

(짝수) && (100보다 크고) && (소수가 아니고)

위 조건을 코드로 표현하면 아래와 같다.

 

반응형

댓글