[Spring] 객체지향 쿼리 언어

2025. 10. 2. 13:39·Spring

JPA에서는 다양한 쿼리 방법을 지원한다. 하나씩 알아보자.

 

1. JPQL 

  • 정의 : 테이블, 칼럼 대신 엔티티와 필드 이름으로 쓰는 쿼리로 JPA가 자동으로 SQL로 바꿔서 DB에서 실행한다. 
  • 필요성 : 코드가 객체(엔티티) 중심이라 이해하기 쉽다. 연관관계도 자연스럽게 조인이 가능하다. 
  • 언제 사용하는가 : 일반적인 조회 전부 
  • 장점 : db에 덜 묶이고 연관관계 사용하기 쉽다. 
  • 단점 : 동적 조건이 많아지면 문자열 쿼리라 지저분해지기 쉽다. 
public interface MemberRepository extends JpaRepository<Member, Long> {

    // 팀 이름으로 회원 찾기 
    @Query("select m from Member m join m.team t where t.name = :team")
    List<Member> findByTeamName(@Param("team") String teamName);
}

 

2. QueryDSL 

  • 정의 : 자바 코드 체인으로 JPQL을 만드는 라이브러리이다. 
  • 필요성 : 검색 조건이 바뀌는 동적 쿼리를 깔끔하고 안전하게 만들려면 문자열 대신 코드가 편하다. 
  • 언제 사용하는가 : 필터가 많은 목록, 검색 화면
  • 장점 : 가독성이 좋다.
  • 단점 : 처음에 Q타입 생성 설정이 필요하다. 
public interface MemberQueryRepository {
  List<MemberDto> search(String teamName, Integer minAge, String keyword);
}

@Repository
@RequiredArgsConstructor
public class MemberQueryRepositoryImpl implements MemberQueryRepository {

  private final JPAQueryFactory qf;
  QMember m = QMember.member;
  QTeam t = QTeam.team;

  @Override
  public List<MemberDto> search(String teamName, Integer minAge, String keyword) {
    return qf.select(Projections.constructor(MemberDto.class, m.id, m.name, t.name))
             .from(m)
             .join(m.team, t).fetchJoin()                         
             .where(
               teamName != null ? t.name.eq(teamName) : null,    
               minAge   != null ? m.age.goe(minAge)   : null,
               keyword       != null ? m.name.containsIgnoreCase(keyword) : null
             )
             .orderBy(m.id.desc())
             .fetch();
  	}
  }

 

3. Spring Data JPA 메소드 쿼리 

  • 정의 : 리파지토리 메소드 이름으로 간단한 쿼리를 만들거나, `@Query` 에 JPQL을 한 줄 적어서 바로 사용한다. 
  • 필요성 : 자주 쓰는 단순 조건을 빠르게 만들고, 쿼리를 리파지토리에 명시적으로 고정하기 좋다.
  • 언제 사용하는가 : 단순 조회, 특정 화면에서 쓰는 고정 쿼리, 연관을 함께 가져오고 싶은 상황 
  • 장점 : 생산성이 높고 `@EntityGraph` 으로 연관을 함께 로딩하도록 선언도 가능하다. 
  • 단점 : 복잡하고 동적인 조건이 있는 경우 한계가 있다. 
public interface MemberRepository extends JpaRepository<Member, Long> {
  // 메소드 이름만으로
  List<Member> findByAgeGreaterThanEqual(int age);

  // 연관을 함께 로딩(화면에서 추가 쿼리 막기)
  @EntityGraph(attributePaths = "team")
  Optional<Member> findWithTeamById(Long id);

  // JPQL 고정
  @Query("select m from Member m where m.name like concat(:kw, '%')")
  List<Member> searchByName(@Param("kw") String keyword);
}

 

4. 네이티브  SQL 

  • 정의 : JPA를 통해 SQL을 그대로 실행하는 방법이다. 
  • 필요성 : JPQL, QueryDSL로 표현하기 어려운 db 전용 기능을 사용하고 싶을 경우에 사용한다. 
  • 언제 사용하는가 : 리포트성 쿼리, 성능 튜닝 포인트가 필요한 경우
  • 장점 : db 기능을 있는 그대로 활용할 수 있다. 
  • 단점 : db에 강하게 묶여 있고, 결과 매핑 코드를 직접 챙겨야 한다. 
public interface MemberRepository extends JpaRepository<Member, Long> {

    // 엔티티로 매핑
    @Query(value = "SELECT * FROM member WHERE team_id = :teamId ORDER BY id DESC", nativeQuery = true)
    List<Member> findNativeByTeamId(@Param("teamId") Long teamId);
}

 

5. JDBC Template 

  • 정의 : 순수 SQL을 깔끔하게 실행하도록 도와주는 스프링 도구이다. 
  • 필요성 : 레거시 SQL 재사용, 대량 조회, 배치, 집계처럼 SQL이 더 빠르고 쉬운 구간이 있다. 
  • 언제 사용하는가 : 보고서나 통계
  • 장점 : 가볍고 직관적이다. 
  • 단점 : JPA 기능이 없다. 그냥 SQL이다. 
public List<MemberDto> report(Long teamId) {
    String sql = "SELECT id, name FROM member WHERE team_id = ? ORDER BY id DESC";
    return jdbc.query(sql,
        (rs, i) -> new MemberDto(rs.getLong("id"), rs.getString("name")),
        teamId);
}

 

6. MyBatis 

  • 정의 : SQL을 XML/어노테이션 매퍼로 관리하고 <if>, <where>와 같은 태그로 동적 SQL을 쉽게 만드는 프레임워크이다. 
  • 필요성 : 조건이 매우 다양한 검색 화면처럼, SQL 주도가 더 읽기 좋은 곳이 있다. 
  • 언제 사용하는가 : 복잡한 동적 WHERE, ORDER 조합 
  • 장점 : 동적 SQL에 강하다. 
  • 단점 : JPA 기능이 없다. 그냥 SQL이다. 

 

'Spring' 카테고리의 다른 글

[Spring] 외부 API 연동하기 (RestTemplate vs. WebClient vs. OpenFeign)  (0) 2025.10.05
[Spring] N+1 문제  (0) 2025.10.03
[Spring] 즉시 로딩과 지연 로딩  (0) 2025.09.21
[Spring] Transactional 사용 시 자기 호출(Self-Invocation) 이슈  (0) 2025.09.11
[Spring] Spring Events 사용해 이벤트 발행하기  (0) 2025.09.07
'Spring' 카테고리의 다른 글
  • [Spring] 외부 API 연동하기 (RestTemplate vs. WebClient vs. OpenFeign)
  • [Spring] N+1 문제
  • [Spring] 즉시 로딩과 지연 로딩
  • [Spring] Transactional 사용 시 자기 호출(Self-Invocation) 이슈
erika0915
erika0915
백엔드 개발자가 되고 싶어요 .
  • erika0915
    erikoding
    erika0915
  • 전체
    오늘
    어제
    • 분류 전체보기 (78)
      • 프로젝트 (13)
        • 끼니콩 (3)
        • 덕메랑 (3)
        • handDoc (7)
        • Haeil (0)
      • Java (9)
        • 클린코더스 (0)
      • Spring (30)
      • Redis (3)
      • CS (7)
        • 운영체제 (3)
        • 컴퓨터구조 (0)
        • 네트워크 (4)
      • DevOps (2)
      • 코딩테스트 (0)
      • Tech (14)
        • TDD (1)
        • 정리 (5)
        • 우테코 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    몽고디비
    네트워크
    redis
    스프링부트
    코드레빗
    jira
    STT
    git
    지라
    깃
    springboot
    운영체제
    MongoDB
    파인튜닝
    java
    Spring
    자바
    docker
    github
    TDD
    레디스
    coderabbit
    도커
    Network
    스프링
    AI
    OS
    깃허브
    promtail
    CoolSMS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
erika0915
[Spring] 객체지향 쿼리 언어

티스토리툴바