[스프링 JPA] @Query, 네이티브 쿼리, 페이징/정렬, QueryDSL, 그리고 인증/인가 개념 정리
스프링 데이터 JPA(Sprint Data JPA)를 사용하다 보면, @Query를 이용해 복잡한 쿼리를 작성하거나, 네이티브 쿼리를 통해 특정 DB에 최적화된 SQL을 사용해야 하는 경우가 있습니다. 또한 페이징, 정렬, 동적 쿼리(특히 QueryDSL 활용), 그리고 보안 영역에서 인증(Authentication)과 인가(Authorization)를 고려해야 합니다. 본 글에서는 이러한 개념들을 간단하게 정리해 보겠습니다.
1. @Query
1) @Query 란?
- 스프링 데이터 JPA에서는 기본적인 CRUD와 메서드 이름으로 쿼리를 추론하여 사용할 수 있지만, 복잡한 조건이나 특정 DB에 종속적인 기능이 필요할 때는 @Query 애너테이션을 사용합니다.
- @Query는 JPQL(Java Persistence Query Language)뿐 아니라, 네이티브 쿼리까지 실행할 수 있도록 지원합니다.
2) @Query 파라미터 방식
- 위치 기반 파라미터
- @Query(“SELECT e FROM Entity e WHERE e.name = ?1 AND e.age = ?2”)
- List
findByNameAndAge(String name, int age); - ?1, ?2와 같이 메서드 파라미터 순서대로 매핑됩니다.
- 이름 기반 파라미터
- @Query(“SELECT e FROM Entity e WHERE e.name = :name AND e.age = :age”)
- List
findByNameAndAge(@Param(“name”) String name, @Param(“age”) int age); - :name, :age 형태로 명시하여 가독성을 높일 수 있고, 파라미터 순서가 바뀌어도 안전합니다.
- 특정 변수만 조회하기
- @Query(“SELECT e.name FROM Entity e WHERE e.age > :age”)
- List
findNamesByAge(@Param(“age”) int age); - 엔티티 전체가 아닌 필요한 컬럼만 추출할 수도 있습니다.
3) @Query 주의사항
- @Query로 정의한 쿼리는 프로젝트 로딩 시점에 파싱되므로, SQL에 오류가 있을 경우 애플리케이션 실행 시 예외가 발생합니다.
- 한 번에 많은 쿼리를 등록하기보다는, 하나씩 테스트하며 확실히 검증한 뒤 추가하는 것이 안전합니다.
2. 네이티브 쿼리( Native Query )
- @Query로 JPQL을 작성하는 대신, 네이티브 쿼리(= 특정 DB에 종속적인 SQL)를 직접 사용할 수도 있습니다.
- 예시:
- @Query(value = “SELECT * FROM my_table WHERE name = :name”, nativeQuery = true)
- List<MyEntity> findByNameNative(@Param(“name”) String name);
- 주의할 점은, 네이티브 쿼리는 특정 DB 문법에 의존적이므로, 다른 DB로 교체 시 호환성 이슈가 생길 수 있습니다.
3. 페이징 및 정렬 처리하기
1) 페이징(Pageable)
- 스프링 데이터 JPA에서 페이징을 위해 Pageable 인터페이스를 사용합니다.
- 쿼리 메서드와 동일하게 @Query에도 Pageable을 인자로 받아 페이징 기능을 적용할 수 있습니다.
- @Query(“SELECT e FROM Entity e WHERE e.age > :age”)
- Page<Entity> findByAgeGreaterThan(@Param(“age”) int age, Pageable pageable);
- 반환 타입을 Page<T>로 지정하면, 총 페이지 수나 현재 페이지 정보도 함께 받을 수 있습니다.
2) 정렬(Sort)
- Sort 객체를 이용해 정렬 조건을 추가할 수 있습니다.
- List<Entity> findByNameContaining(String keyword, Sort sort);
- // 사용 예시
- List<Entity> results = repository.findByNameContaining(“test”, Sort.by(“age”).descending());
- 페이징과 정렬을 동시에 적용하려면 PageRequest.of(page, size, sort)를 사용합니다.
4. QueryDSL 이란?
1) 동적 쿼리의 필요성
- @Query로 등록한 쿼리는 프로젝트 로딩 시점에 파싱되어야 하므로, 동적으로 변경하기 어렵습니다.
- MyBatis같은 SQL 매퍼를 사용하면 if문 등으로 동적 쿼리를 처리할 수 있지만, JPA 환경에서는 QueryDSL을 사용해 자바 코드 형태로 JPQL을 빌드합니다.
2) QueryDSL 개요
- QueryDSL은 타입 안전한 방식으로 JPQL을 생성해주는 빌더(Binder)입니다.
- 엔티티를 기반으로 Q 클래스를 자동 생성(QEntity), 자바 코드를 통해 조건을 걸어가며 동적 쿼리를 작성할 수 있습니다.
예시 (단순화):
QEntity entity = QEntity.entity;
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
List<Entity> results = queryFactory
.selectFrom(entity)
.where(entity.age.gt(30)
.and(entity.name.contains(“test”)))
.fetch();
- 위와 같이 자바 코드로 작성되므로, 컴파일 시점에 문법 오류를 잡아낼 수 있고, 동적으로 조건을 추가/제거할 수 있습니다.
5. 인증(Authentication)과 인가(Authorization)
1) 개념
- 인증(Authentication): 사용자를 식별(로그인 등)하여, 해당 사용자가 누구인지 확인하는 절차입니다.
- 예) 사원증, RFID, 아이디/비밀번호
- 인가(Authorization): 인증을 통과한 사용자에게 시스템 자원(리소스)에 대한 접근 권한을 부여(또는 제한)합니다.
- 예) 직급에 따라 열람 가능한 문서가 달라짐
2) 예시 시나리오
- 회사 사무실 출입:
- 인증: 사원증으로 문을 통과 가능한지 확인 (본인 확인)
- 인가: 사원증에 기록된 부서/직급 정보에 따라 접근 가능한 층, 열람 문서를 제한
스프링 부트에서 보안이 필요하다면, Spring Security 등을 활용하여 인증과 인가 로직을 체계적으로 구성할 수 있습니다.
마무리 & 요약
- @Query
- 복잡한 SQL 또는 네이티브 쿼리 작성 시 사용
- 위치 기반, 이름 기반 파라미터를 지원
- SQL 오류 시 로딩 시점 예외 발생에 유의
- 네이티브 쿼리
- 특정 DB 기능 활용 시 사용
- DB 교체 시 호환성 이슈가 발생할 수 있음
- 페이징(Pageable) & 정렬(Sort)
- @Query와 함께 Pageable, Sort를 이용하여 간단하게 페이징/정렬 기능 구현
- QueryDSL
- 자바 코드로 동적 쿼리를 작성할 수 있는 JPQL 빌더
- 타입 안전성, 동적 쿼리 지원
- 인증 vs. 인가
- 인증: 사용자 식별
- 인가: 사용자 권한(자원 접근)을 제한
위 개념들을 바탕으로 스프링 부트에서 데이터베이스 연동 및 보안 기능을 더욱 폭넓게 활용할 수 있습니다. 특히 복잡하거나 동적인 쿼리가 필요한 상황에서는 QueryDSL을, 고급 보안 요구 사항에는 Spring Security와 연계하여 인증/인가를 탄탄하게 구성할 수 있습니다.
- 스프링 부트(Spring Boot)
- 스프링 데이터 JPA, @Query, 네이티브 쿼리(Native Query)
- JPQL, 페이징(Pageable), 정렬(Sort)
- QueryDSL, 동적 쿼리
- 인증(Authentication), 인가(Authorization)
- Spring Security
본 가이드가 스프링 데이터 JPA를 활용한 쿼리 작성, 페이징/정렬, 보안 개념(인증/인가)에 대한 이해에 도움이 되길 바랍니다. 더 궁금한 점이 있으시면 언제든 댓글이나 문의로 알려주세요!