Spring

[Spring] 동적 쿼리 - BooleanBuilder와 BooleanExpression의 차이

montmer27 2026. 2. 24. 21:13

About this article: 

Today I learned - 오늘 배운 것들을 간단히 기록합니다.

 

Article Body:

두 방식 비교 요약

구분 BooleanBuilder BooleanExpression
개념 조건을 모아두는 컨테이너 단일 조건의 표현식
객체 성격 가변(Mutable) 불변(Immutable)
null 처리 직접 제어 자동 무시
where 작성 방식 .where(builder) .where(조건1, 조건2, 조건3..)
재사용성 낮음 높음
코드 가독성 복잡함 깔끔함

 

모두 데이터베이스 쿼리를 동적으로 생성하기 위해 사용

 

Trade-Off 관계:

재사용성 + 가독성 -> BooleanExpression

조건의 유연성 -> BooleanBuilder

 

예) 필터 조건이 많거나, 조건이 동적으로 추가되거나 제거되는 경우가 빈번한 경우

-> BooleanBuilder가 적합

// BooleanBuilder 사용
// 예: 사용자 정보를 검색하는 상황 (사용 필드: 이름, 이메일, 권한)
// 특징: 검색 조건이 늘어나도 if문 추가로 간단하게 적용 가능 (높은 유연성)

@Override
    public List<UserSearchResponse> searchUserByMultiCondition(UserSearchRequest request) {
        // BooleanBuilder 타입의 조건을 만드는 과정
        BooleanBuilder builder = new BooleanBuilder();

        if (request.getUsername() != null && !request.getUsername().isBlank()) {
            builder.and(user.username.eq(request.getUsername()));
        }
        if (request.getEmail() != null && !request.getEmail().isBlank()) {
            builder.and(user.email.endsWith(request.getEmail()));
        }
        if (request.getUserRole() != null) {
            builder.and(user.roleEnum.eq(request.getUserRole()));
        }

        return queryFactory
                // 엔티티에서 필요한 필드만 가져오고 싶은 경우 Projection 사용
                .select(Projections.constructor(UserSearchResponse.class,
                        user.username,
                        user.email,
                        user.roleEnum
                ))
                .from(user)
                .where(builder)
                .fetch();
    }

 

 

 

예) 조건이 많지 않거나, 대체로 고정적임 / 필터링 조건을 한눈에 파악하고 싶음

-> BooleanExpression이 적합

// BooleanExpression 사용
// 예: 사용자 정보를 검색하는 상황 (사용 필드: 이름, 이메일, 권한)
// 특징: 어떤 조건으로 동적 쿼리를 생성하는지 where()에서 한눈에 파악 가능
// where() 내부 조건이 대체로 고정된 경우 사용
// 조건을 메서드로 구현하여 재사용 용이
@Override
    public List<UserSearchResponse> searchUserByMultiConditionV2(UserSearchRequest request) {
        return queryFactory
                .select(Projections.constructor(UserSearchResponse.class,
                        user.username,
                        user.email,
                        user.roleEnum
                ))
                .from(user)
                .where(
                        usernameCondition(request.getUsername()),
                        emailCondition(request.getEmail()),
                        roleCondition(request.getUserRole())
                )
                .fetch();
    }

    private BooleanExpression usernameCondition(String username) {
        return username != null ? user.username.eq(username) : null;
    }

    private BooleanExpression emailCondition(String email) {
        return email != null ? user.email.endsWith(email) : null;
    }

    private BooleanExpression roleCondition(UserRoleEnum userRole) {
        return userRole != null ? user.roleEnum.eq(userRole) : null;
    }

}

 

결론

1. 검색 기능에서 사용자의 자유도가 높은 환경 -> BooleanBuilder 권장

- 높은 유연성, 복잡한 조건 처리에 유리

 

2. 검색 기능에서 서버의 통제가 높은 환경 -> BooleanExpression 권장

- 높은 재사용성

- 높은 가독성

- *코드가 단순한 경우 권장