쿼리 문법 자체는 JPQL과 Native SQL의 구분 기준이 아니며, 컴퓨터는 API 사용 방식이나 명시적 설정(e.g., nativeQuery = true)을 통해 쿼리 유형을 판단합니다. JPQL은 실행 전에 JPA가 처리하고 변환하므로 실행 환경에서 차이가 나타납니다.
특징:
엔티티 중심: JPQL은 데이터베이스의 테이블이 아니라 JPA 엔티티를 대상으로 쿼리합니다. 이는 객체 지향적인 접근 방식을 제공합니다.
데이터베이스 독립성: JPQL은 JPA 구현체(Hibernate 등)에 의해 SQL로 변환되므로 특정 데이터베이스에 종속되지 않습니다.
표준화: JPA 표준 스펙의 일부로, JPA를 사용하는 모든 환경에서 동일하게 동작합니다.
구문: SQL과 유사하지만, 테이블 대신 엔티티 이름과 필드를 사용합니다.
예제:
// JPQL 쿼리
String jpql = "SELECT u FROM User u WHERE u.name = :name";
TypedQuery<User> query = em.createQuery(jpql, User.class);
query.setParameter("name", "John");
List<User> users = query.getResultList();
@Query("SELECT u FROM User u WHERE u.name = :name")
List findByName(@Param("name") String name);
데이터베이스 변경 시 쿼리를 수정할 필요가 적음.
객체 중심 설계와 잘 맞아 코드의 가독성이 높음.
데이터베이스에 독립적인 코드 작성 가능.
복잡한 SQL 쿼리를 작성하기 어려움.
데이터베이스 고유 기능(예: 특정 함수 또는 쿼리 힌트) 사용 제한.
특징:
SQL 중심: 데이터베이스의 테이블, 컬럼, SQL 구문을 직접 작성합니다.
데이터베이스 종속적: 작성한 SQL은 특정 데이터베이스에 종속적이며, 데이터베이스 변경 시 쿼리를 수정해야 할 수 있습니다.
유연성: JPQL보다 더 복잡하고 최적화된 쿼리를 작성할 수 있습니다.
구문: 데이터베이스에서 사용하는 표준 SQL을 사용합니다.
Native SQL은 명시적으로 nativeQuery = true로 지정합니다.
nativeQuery = true
@Query(value = "SELECT * FROM users WHERE user_name = :name", nativeQuery = true)
List findByNameNative(@Param("name") String name);
// Native SQL 쿼리
String sql = "SELECT * FROM users WHERE name = :name";
Query query = em.createNativeQuery(sql, User.class);
query.setParameter("name", "John");
List users = query.getResultList();
장점:
단점:

만약 엔터티 이름과 테이블 이름이 동일하거나 비슷하게 설계된 경우, 쿼리 문법만 보고 JPQL인지 Native SQL인지 구분하기 어려울 수 있습니다. 하지만 JPA가 제공하는 실행 메커니즘을 통해 내부적으로 이를 명확히 구분할 수 있습니다.
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
}
@Query("SELECT u FROM User u WHERE u.name = :name")
List findByName(@Param("name") String name);
@Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true)
List findByNameNative(@Param("name") String name);
두 쿼리 모두 users라는 테이블 이름(혹은 엔터티 이름)을 사용하기 때문에 문법적으로 유사해 보입니다. 특히 Native SQL의 경우 JPQL처럼 보이는 경우도 있습니다.
JPA는 JPQL 쿼리를 분석하고, 이를 SQL로 변환하는 작업을 수행합니다.
EntityManager 또는 Spring Data JPA의 @Query에서 JPQL인지 Native SQL인지 명시적으로 설정된 옵션을 확인합니다.
예: nativeQuery = true가 설정되지 않은 경우, 쿼리는 기본적으로 JPQL로 간주됩니다.
JPQL은 엔터티 클래스와 필드를 기준으로 작성되기 때문에, JPA는 이를 파싱하여 엔터티와 속성을 매핑합니다.
예: SELECT u FROM User u에서 User는 테이블이 아니라 엔터티 클래스입니다.
쿼리 실행 흐름
예: @Query("SELECT u FROM User u WHERE u.name = :name")
Native SQL인 경우 반드시 nativeQuery = true를 명시하여 구분합니다.
예: @Query(value = "SELECT * FROM users WHERE name = :name", nativeQuery = true)
엔터티 클래스에 명시된 테이블 이름이 실제 테이블 이름과 다를 수 있습니다.
Entity 클래스:
@Entity
@Table(name = "members")
public class User {
private String name;
}
@Query("SELECT u FROM User u WHERE u.name = :name")
@Query(value = "SELECT * FROM members WHERE name = :name", nativeQuery = true)
문법적으로 혼동될 수 있는 경우라도, 컴퓨터는 실행 환경(예: nativeQuery 여부, EntityManager)과 엔터티 매핑 정보를 통해 JPQL인지 Native SQL인지 명확히 구분합니다.
개발자는 이러한 메커니즘을 이해하고, 쿼리를 작성할 때 명시적으로 구분하는 것이 중요합니다.