Spring Specification은 왜 사용할까?

이재서·2026년 7월 21일

Spring Specification은 무엇인가?

이전 글에서는 JPQL, Criteria API 그리고 QueryDSL까지 객체 쿼리 언어를 살펴봤다.

Criteria API는 타입 안정성을 제공한다는 장점이 있었지만 코드가 지나치게 장황했고, QueryDSL은 이런 문제를 해결하며 실무에서 가장 많이 선택되는 라이브러리 중 하나가 되었다.

그런데 문서를 읽다 보니 Spring Data JPA에는 Specificiation이라는 기능도 존재했다.

이미 QueryDSL이라는 훌륭한 라이브러리가 있는데도 왜 Speicification이 필요할까?

이번 글에서는 Specification이 등장한 이유와 어떤 상황에서 사용하면 좋을지 정리해보려고 한다.


Specification은 왜 등장했는가?

JPA는 Cirteria API를 표준으로 제공하지만 직접 사용하기에는 코드가 길고 가독성이 좋지 않다.

Spring Data JPA는 이러한 Criteria API를 조금 더 객체지향적으로 사용할 수 있도록 Specification 인터페이스를 제공한다.

해당 인터페이스의 가장 큰 특징은 핵심 조회 조건 자체를 객체로 만드는 점이다.

즉,

"나이가 20살 이상인 회원"

이라는 조건도 하나의 객체가 되고,

"이름이 kim인 회원"

이라는 조건도 하나의 객체가 된다.

그리고 이 조건들을 조합하여 하나의 조회 조건을 만들어낼 수 있다.


Specification의 구조

Specificiation은 하나의 조건(Predicate)을 생성하는 인터페이스이다.

대표적인 메서드는 다음과 같다.

public interface Specification<T> {
	Predicate toPredicate(
    	Root<T> root,
        CriteriaQuery<?> query,
        CriteriaBuilder cb
    );
}

여기서

  • Root: 조회 대상 엔티티
  • CriteriaQuery: 생성 중인 쿼리
  • CriteriaBuilder: Predicate 생성 도우미
  • Predicate: 쿼리의 WHERE 절에 해당하는 조건절

를 의미한다.

결국 내부적으로는 Criteria API를 사용하지만 이를 조금 더 추상화한 형태라고 볼 수 있다.


사용 예시

예를 들어 나이가 20살 이상인 회원을 조회한다고 가정해보자.

public class MemberSpecification {
	public static Specification<Member> ageGoe(int age) {
    	return (root, query, db) -> 
        	cb.greaterThanOrEqual(root.get("age"), age);
    }
}

Repository에서는

public interface MemberRepository extends
JpaRepository<Member, Long>,
JpaSpecificationExecutor<Member> {}

그리고

memberRepository.findAll(MemberSpecification.ageGoe(20));

처럼 사용할 수 있다.


Specification의 장점

Specification의 장점은 조건을 조합할 수 있다는 점이다.

예를 들어

Specifciation<Mmeber> spec = ageGoe(20)
	.and(usernameEq("kim")
    .or(activeTrue());

처럼 AND, OR를 메서드 호출만으로 구성할 수 있다.

조회 조건을 객체로 분리하기 때문에 재사용성도 높아진다.


그런데 왜 많이 사용되지 않을까?

Specification은 Criterai API를 직접 사용하는 것보다는 훨씬 편하다.

하지만 내부적으로는 결국 Criteria API를 기반으로 하기 때문에 복잡한 조회에서는 코드가 빠르게 길어진다.

특히 여러 테이블을 조인하거나 DTO 조회가 많아질수록 QueryDSL에 비해 가독성이 떨어지는 편이다.

그래서 실무에서는

  • 간단한 검색 조건
  • Spring Data JPA만 사용하는 프로젝트
  • 조건 조합이 많은 경우

에는 Specification을 사용하는 경우가 있고,

조인이 많거나 복잡한 조회가 필요한 프로젝트에서는 QueryDSL을 선택하는 경우가 많다.


정리

Specification을 살펴보면서 느낀 점은 QueryDSL의 경쟁자라기보다는 Criteria API를 조금 더 쉽게 사용할 수 있도록 만든 추상화에 가깝다는 것이다.

실제로도 내부적으로 Criteria API를 사용하기 때문에 타입 안정성과 동적 쿼리 작성이라는 장점은 그대로 가져간다.

하지만 안타깝게도 Criteria API의 단점인 복잡한 쿼리에서의 가독성을 해결하지 못해 QueryDSL을 대체하기는 어렵다고 생각한다.

Specification은 "QueryDSL을 대체하는 기술"이라기보다는 Spring Data JPA가 제공하는 쿼리 작성 방식 중 하나로 이해하는 것이 적절하다고 생각한다.

profile
아무거나 쓰는 중

0개의 댓글