1. Specification 패턴이란?

Specification 패턴은 비즈니스 규칙(조건)을 명확하고 선언적으로 표현하고, 다양한 조건을 조합할 수 있도록 설계하는 패턴입니다. 주로 객체 필터링, 조건 분리, 동적 쿼리 조합 등에 사용됩니다.


2. 사용 목적

  • 복잡한 조건 로직을 캡슐화하여 재사용 가능하게 만듦
  • 다양한 조건을 동적으로 조합 (AND / OR / NOT)
  • 코드 중복을 줄이고 가독성 및 테스트 용이성 향상

3. Java 예시

public interface Specification<T> {
    boolean isSatisfiedBy(T t);

    default Specification<T> and(Specification<T> other) {
        return t -> this.isSatisfiedBy(t) && other.isSatisfiedBy(t);
    }

    default Specification<T> or(Specification<T> other) {
        return t -> this.isSatisfiedBy(t) || other.isSatisfiedBy(t);
    }

    default Specification<T> not() {
        return t -> !this.isSatisfiedBy(t);
    }
}
public class AgeSpecification implements Specification<User> {
    public boolean isSatisfiedBy(User user) {
        return user.getAge() >= 18;
    }
}

public class NameSpecification implements Specification<User> {
    public boolean isSatisfiedBy(User user) {
        return user.getName().startsWith("K");
    }
}

// 조합 사용
Specification<User> adultNamedK = new AgeSpecification().and(new NameSpecification());

4. JPA & Spring Data 에서의 실무 활용

Spring Data JPA의 JpaSpecificationExecutor는 이 패턴을 기반으로 조건을 쿼리 객체로 변환해 동적 where 절을 생성합니다.

Specification<User> spec = (root, query, cb) -> cb.greaterThan(root.get("age"), 18);
userRepository.findAll(spec);

복잡한 쿼리를 분리된 조건 단위로 구성하고, 필요 시 조합하여 동적으로 처리할 수 있어 유지보수성이 높아집니다.


5. 실무 사례와 비판적 관점

실제로 마이크로서비스 아키텍처(MSA) 프로젝트에서는 하나의 서비스가 하나의 스키마만 접근하는 원칙 하에, 여러 서비스에서 데이터를 가져와 조합하는 방식이 사용됩니다. 이때 서비스 계층에서 각 조건을 재사용 가능한 컴포넌트로 만들어 조합한 경우, Specification 패턴의 개념을 어느 정도 따랐다고 볼 수 있습니다.

일반적인 JPA 기반 프로젝트에서 Specification 패턴의 사용 빈도는 팀이나 프로젝트의 성격에 따라 달라집니다. 흔하게 사용되지는 않지만, 다음과 같은 장점 때문에 채택하는 사례도 존재합니다:

  • 비즈니스 규칙을 명확히 분리하고 재사용할 수 있는 구조가 필요할 때
  • 도메인 중심 설계(DDD)를 채택한 프로젝트에서 복잡한 조건을 도메인 객체와 가까운 위치에서 선언적으로 처리하고자 할 때
  • Querydsl의 도입이 어렵거나, 의존성을 최소화하고 싶은 경우

다만 다음과 같은 현실적인 이유로 Querydsl이 더 널리 채택되는 경향도 분명 존재합니다:

  • JPA의 Criteria API는 문법이 복잡하고 직관성이 떨어짐
  • Querydsl은 컴파일 타임에 타입 검사를 지원하며, 쿼리 작성이 간결하고 명확함
  • Specification 패턴은 설계 난이도와 러닝 커브가 높고, 클래스 수가 늘어나 유지보수가 어려워질 수 있음

결론적으로, Specification 패턴은 "JPA 환경에서 잘 쓰이지 않는다"기보다는 특정한 설계 철학이나 프로젝트 구조에 따라 신중하게 도입되는 경향이 있는 패턴입니다. 복잡한 비즈니스 조건을 자주 재사용하고 조합해야 하는 환경에서는 오히려 매우 유용한 선택이 될 수 있습니다.

+ Recent posts