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 권장
- 높은 재사용성
- 높은 가독성
- *코드가 단순한 경우 권장