IT Developer/Spring

Spring 기초 <26. JPA + QueryDSL을 활용한 복잡한 쿼리 최적화>

TEMA_ 2025. 4. 12. 13:38
반응형

스프링 Spring

26. JPA + QueryDSL을 활용한 복잡한 쿼리 최적화

 

안녕하세요! 태마입니다.

Spring 기초 강좌입니다.

 

강좌의 경우 

1. 주제 간단 정리

2. 상세 주제 정리

으로 이루어져 있습니다.

 

스프링 Spring

포스팅 시작하겠습니다 :)

 


 

1. 주제 간단 정리

 

1. QueryDSL이란?

QueryDSL은 타입 안전한(Typed-Safe) 쿼리를 작성할 수 있도록 도와주는 프레임워크
JPQL을 더욱 직관적이고 가독성 높게 사용할 수 있도록 도와줌

📌 QueryDSL의 주요 특징

특징설명
타입 안전한 쿼리 컴파일 타임에 SQL 오류를 방지 가능
코드 자동 완성 지원 IDE에서 쿼리를 쉽게 작성 가능
복잡한 쿼리를 직관적으로 작성 조인(Join) 및 서브쿼리를 간결하게 구현
JPQL과 비교하여 성능 최적화 JPQL보다 가독성이 높고 유지보수성이 향상됨

📌 QueryDSL을 사용하면 "SQL과 유사한 방식으로 JPA 쿼리를 간결하고 직관적으로 작성 가능"


2. JPQL vs QueryDSL 비교

JPQL은 문자열 기반이라 가독성이 떨어지고, QueryDSL은 코드 기반으로 직관적임

📌 JPQL과 QueryDSL 비교

비교 항목JPQLQueryDSL
쿼리 방식 문자열 기반 코드 기반
타입 안정성 런타임 오류 발생 가능 컴파일 타임에 오류 확인 가능
IDE 자동완성 지원 지원하지 않음 지원됨
가독성 및 유지보수 문자열이라 복잡한 쿼리 작성이 어려움 코드 기반이라 가독성이 높음

📌 QueryDSL을 활용하면 "타입 안정성을 보장하고 유지보수하기 쉬운 쿼리를 작성 가능"


✅ 여기까지 QueryDSL의 개념과 JPQL과의 차이를 배웠습니다!
👉 "그렇다면, Spring Boot에서 QueryDSL을 어떻게 설정하고 활용할까?"
✅ 2부에서 Spring Boot에서 QueryDSL을 설정하고, 복잡한 쿼리를 최적화하는 방법을 배워봅시다!

반응형

 


 

2. 상세 주제 정리

 

1. QueryDSL 설정 및 의존성 추가

QueryDSL을 사용하려면 querydsl-jpa 라이브러리를 추가해야 함

📌 1️⃣ build.gradle 설정

dependencies {
    implementation 'com.querydsl:querydsl-jpa:5.0.0'
    annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jpa'
}

QueryDSL을 지원하는 라이브러리 추가

📌 2️⃣ QueryDSL 빌드 설정 추가

tasks.withType(JavaCompile) {
    options.annotationProcessorGeneratedSourcesDirectory = file("src/main/generated")
}

QueryDSL 빌드 시 src/main/generated 디렉토리에 Q클래스를 생성하도록 설정


2. QueryDSL 사용을 위한 엔티티 설정

QueryDSL을 사용하려면 JPA 엔티티를 정의해야 함

📌 User 엔티티 생성 (User.java)

import jakarta.persistence.*;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private int age;

    // 기본 생성자 및 Getter, Setter
}

JPA를 활용하여 User 엔티티를 생성

📌 QueryDSL을 사용하면 "기존 JPQL보다 가독성이 뛰어난 쿼리 작성 가능"


3. QueryDSL을 활용한 복잡한 쿼리 작성

QueryDSL을 사용하여 다양한 조건을 조합한 복잡한 쿼리 작성 가능

📌 QueryDSL Repository 생성 (UserQuerydslRepository.java)

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.springframework.stereotype.Repository;
import java.util.List;

import static com.example.demo.domain.QUser.user;

@Repository
public class UserQuerydslRepository {

    private final JPAQueryFactory queryFactory;

    public UserQuerydslRepository(EntityManager entityManager) {
        this.queryFactory = new JPAQueryFactory(entityManager);
    }

    public List<User> findUsersByAgeGreaterThan(int minAge) {
        return queryFactory
                .selectFrom(user)
                .where(user.age.gt(minAge))  // age > minAge
                .fetch();
    }

    public List<User> findUsersByName(String name) {
        return queryFactory
                .selectFrom(user)
                .where(user.name.eq(name))  // name = '입력한 값'
                .fetch();
    }
}

JPAQueryFactory를 사용하여 where() 조건을 적용한 복잡한 쿼리를 실행 가능

📌 QueryDSL을 활용하면 "조건 조합이 자유롭고, 유지보수성이 뛰어난 쿼리 작성 가능"


4. QueryDSL을 활용한 복잡한 조인(Join) 쿼리

QueryDSL을 활용하면 여러 엔티티 간의 조인(Join)도 쉽게 처리 가능

📌 User & Order 엔티티 생성 (Order.java)

import jakarta.persistence.*;

@Entity
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    private User user;

    private String productName;
}

각 주문(Order)은 특정 사용자(User)와 연결됨 (ManyToOne 관계)

📌 QueryDSL을 활용한 조인 쿼리 (UserQuerydslRepository.java)

import static com.example.demo.domain.QUser.user;
import static com.example.demo.domain.QOrder.order;

public List<User> findUsersWithOrders() {
    return queryFactory
            .selectFrom(user)
            .join(user.orders, order)
            .fetch();
}

QueryDSL을 활용하면 join()을 통해 여러 엔티티를 쉽게 조인 가능

📌 QueryDSL을 활용하면 "SQL과 유사한 방식으로 복잡한 조인 쿼리 작성 가능"


✅ 여기까지 JPA + QueryDSL을 활용한 복잡한 쿼리 최적화 방법을 배웠습니다!
👉 "그렇다면, Spring Boot에서 트랜잭션 관리 최적화 (@Transactional, REQUIRES_NEW)은 어떻게 할까?"
✅ 다음 회차에서 **Spring Boot에서 트랜잭션 관리 최적화 (@Transactional, REQUIRES_NEW)**를 배워봅시다!

 



 

반응형