[Spring Boot] Spring Boot 3.XX 버전 이상 QueryDSL 설정 및 실행 과정

2023. 9. 11. 15:44기술 창고/Spring

728x90
SMALL

저는 Spring Boot를 사용하여 개발을 진행할 때 보통 QueryDSL을 자주 애용하는 편입니다.

 

흔히 사용하는 JPA의 경우에는 사용 방법이 많이 알려져있기도 하고 가장 대중적인 데이터 관리 / 사용 기술이라고 볼 수 있겠지만 복잡한 조건의 데이터를 사용해야할 때 사용하기 번거롭다는 단점이 존재하고, JPA 함수를 사용할 때 아무래도 쿼리문 형태가 아닌 함수 형식이다 보니 사용할 때마다 매번 찾아보거나 해야하기 때문에 불편하다고 느꼈습니다.

 

MyBatis의 경우에는 옛날부터 많이 사용했던 데이터 기술이긴 하지만 오래된 기술이니만큼 개인적으로 사용하고 싶지 않았습니다.

또한, MyBatis를 사용하게 되면 Mapper 라고 하는 xml로 쿼리문을 따로 관리해줘야하거나 추가로 DAO를 만들어주어야 하고 추가적인 작업 요소가 들어가기 때문에 이 기술 또한 사용하기 싫었습니다.

(가장 큰 이유는 많이 낡은 기술이라고 생각하기 때문입니다 ㅎㅎ;;)

 

QueryDSL은 JPA에서는 하기 어려운 비교적 복잡한 조건의 데이터를 쉽게 조회할 수도 있고, 동적 쿼리를 지원하기 때문에 좀 더 유연한 데이터들을 활용하는 것이 가능합니다.

이런 QueryDSL을 사용하기 위해서는 초기에 설정을 몇 가지 해주어야 하는데 저는 이때까지 Spring Boot 2.X.X 버전들을 사용했기 때문에 기존에 설정했던 값들을 지속적으로 사용하기에는 무리가 있었습니다.

따라서 이번에는 Spring Boot 3 이상의 버전들을 사용하게 될 시 적용할 설정들을 정리해보도록 하겠습니다.

 

 

1. Build.Gradle 설정

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.1.3'
	id 'io.spring.dependency-management' version '1.1.3'
	//querydsl 추가
	id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

group = 'music.is.my.life'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-authorization-server'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-web-services'
	implementation 'org.springframework.boot:spring-boot-starter-validation'

	// QueryDSL 설정
	implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
	implementation 'org.jetbrains:annotations:24.0.0'
	annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
	annotationProcessor "jakarta.annotation:jakarta.annotation-api"
	annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
	useJUnitPlatform()
}

// Querydsl 설정부
def generated = 'build/generated'

querydsl {
	jpa = true
	querydslSourcesDir = generated
}

sourceSets {
	main.java.srcDir generated
}

// complieQuerydsl Task에 clean 동작 추가
tasks.compileQuerydsl.dependsOn(clean);

compileQuerydsl{
	options.annotationProcessorPath = configurations.querydsl
}

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
	querydsl.extendsFrom compileClasspath
}

 

 

  • plugins 에 QueryDSL 관련 플러그인을 넣어줍니다.
id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"

 

 

  • dependencies에 QuertDSL 관련 의존성 디펜던시들을 넣어줍니다.
implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
implementation 'org.jetbrains:annotations:24.0.0'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

Spring Boot가 업데이트 됨에 따라 dependendy들이 jakarta 디펜던시인 것을 확인할 수 있습니다.

 

 

  • 추가 설정부를 작성해줍니다.
def generated = 'build/generated'

querydsl {
    jpa = true
    querydslSourcesDir = generated
}

sourceSets {
    main.java.srcDir generated
}

// complieQuerydsl Task에 clean 동작 추가
tasks.compileQuerydsl.dependsOn(clean);

compileQuerydsl{
    options.annotationProcessorPath = configurations.querydsl
}

configurations {
    compileOnly {
       extendsFrom annotationProcessor
    }
    querydsl.extendsFrom compileClasspath
}
  • generated : QueryDSL을 적용하게 되어 컴파일을 하게 되면 Q 객체가 생성이 되어 Q객체가 생성된 엔티티들에 한해 QueryDSL을 사용할 수 있게 되는데 이 Q 객체들이 생성된어 저장되는 경로가 이 generated 변수에 설정한 경로 값입니다.
  • querydsl { ~ } : QueryDSL을 사용할 때 jpa 를 사용할 수 있도록 하는 설정값과, generated에서 설정한 경로 값을 이제 실질적으로 반영하여 Q객체들을 반영시키도록 하는 설정을 합니다.
  • sourceSets : generated 경로에 설정된 Q객체들을 source(자원)으로 사용하겠다고 설정하는 부분입니다.
  • task.compileQuerydsl.dependson(clean) : Q객체들을 반영할 태스크 (작업 빌드)를 돌릴 때마다 clean을 하겠다는 설정입니다. 이전 버전에서는 덜 했지만 최신 버전에 근접하면 할 수록 clean을 해주지 않으면 빌드 자체가 되지 않는 현상도 간간히 발생되기도 합니다.

    !! 이 설정 부분이 좀 중요한 부분일 수도 있는 것이 제가 이전 2 버전 대의 Spring boot 들을 사용했을 때는 그냥 compileQueryDsl을 시도해도 별다른 에러없이 새로 Q객체가 생성이 되었었는데 버전을 올려보니 기존에 Q타입이 존재하면 에러가 발생되는 이슈가 있었습니다.
    따라서 이 설정값도 될 수 있으면 해놓는 것이 좋다고 생각합니다.

 

 

2. Configuration 파일 생성

package music.is.my.life.musicismylife.configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import jakarta.persistence.EntityManager;

@Slf4j
@Configuration
public class QueryDslConfig {

    @Bean
    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager){
        log.info("QueryDSL 설정 - EntityManager : {})", entityManager);
        return new JPAQueryFactory(entityManager);
    }
}

QueryDSL을 사용하기 위해서 JpaQueryFactory를 사용하게 되는데 이 JPAQueryFactory 에  JPA를 사용핳면서 많이 접했을, 데이터 1차 임시 저장소라고도 불리우는 EntityManager를 받아서 사용하게 됩니다.

 

 

3. Task 실행

이제 프로젝트(인텔리제이 기준) 의 오른쪽에 붙어있는 gradle 코끼리를 누르게 되면 Task들을 확인할 수 있습니다.

여기서 other 항목의 compileQuerydsl Task를 실행합니다.

이 과정이 현재 설정한 정보들을  가지고 QueryDSL을 적용하고 Q객체들을 만들게 되는 과정입니다.

 

 

정상적으로 Task 가 실행이 완료되었다면 이전에 build.gradle에서 설정한 generated 경로에 해당 Q객체들이 생성된 것을 확인할 수 있습니다.

 

 

4. 사용

이제 설정 및 컴파일까지 완료하며 사용 준비가 끝났습니다.

본격적으로 사용해봅니다.

 

import static music.is.my.life.musicismylife.member.domain.QMember.member;
import static music.is.my.life.musicismylife.jwt.domain.QToken.token;
import static music.is.my.life.musicismylife.music.domain.QMusic.music;
import static music.is.my.life.musicismylife.likepick.domain.QLikePick.likePick;
import static music.is.my.life.musicismylife.follow.domain.QFollowHistory.followHistory;
import static music.is.my.life.musicismylife.album.domain.QAlbum.album;

@Slf4j
@Component
@RequiredArgsConstructor
public class QueryData {

    private final JPAQueryFactory jpaQueryFactory;
    private final EntityManager entityManager;
    private final CalendarUtils calendarUtils;
    private final MusicUploadInterface musicUploadInterface;

    // 이메일을 통한 유저 조회
    public Member findMemberByEmail(String email) {
        return jpaQueryFactory
                .selectFrom(member)
                .where(member.email.eq(email))
                .fetchOne();
    }
}

사용할 때 기본적으로 import 해야하는 것이 있습니다.
바로 Configuration에서 Bean 객체로 등록해주었던 JPAQueryFactory 를 의존성 주입하여야 하고, 생성된 Q객체를 통해 QueryDsl을 사용할 것이기 때문에 사용할 Q객체들을 import 문을 작성하는 곳에 static import 시켜주어야 합니다.

이제 진짜 사용하기만 하면 됩니다.

위의 코드 예시에서도 기입해놨듯이 jpaQueryFactory를 통해 select문이나 delete문, update문을 사용하면 됩니다.

보다시피 기존의 다른 여타 데이터 사용 기술과는 다르게 직관적으로 MySQL과 같은 데이터베이스 관리 시스템에서 작성했던 쿼리문과 매우 유사하게 닮아있어 금방 익숙해지고 사용할 수 있습니다.

 

QueryDSL 의 사용 명령어도 추후에 차츰차츰 정리해나가 보도록 하겠습니다.

이로서 Spring Boot 3 버전 이상 사용 시 설정할 QueryDSL의 설정 방법과 사용 과정까지 간단하게 정리해보았습니다.

728x90
반응형
LIST