1. Native Query란?
Spring Data JPA에서는 기본적으로 JPQL(Java Persistence Query Language)을 사용하지만, 복잡한 SQL을 실행해야 할 경우 @Query 어노테이션을 활용하여 Native Query를 사용할 수 있습니다.
Native Query는 직접 SQL을 작성하여 실행하는 방식으로, 복잡한 조인, 성능 최적화, 데이터베이스 특정 기능을 사용할 때 유용합니다.
2. Native Query 사용법
(1) 기본적인 Native Query 사용
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(value = "SELECT * FROM member WHERE username = :username", nativeQuery = true)
Member findByUsername(@Param("username") String username);
}
위 코드에서는 nativeQuery = true를 설정하여 순수 SQL을 실행하고 있습니다.
(2) 여러 컬럼을 조회하는 경우
@Query(value = "SELECT id, username FROM member WHERE team_id = :teamId", nativeQuery = true)
List<Object[]> findMembersByTeamId(@Param("teamId") Long teamId);
위와 같이 List<Object[]> 형태로 데이터를 받을 수 있으며, 필요하면 DTO로 변환해야 합니다.
(3) DTO 매핑하여 조회하기
Native Query의 결과를 DTO로 매핑하려면 @SqlResultSetMapping 또는 Constructor Expression을 사용할 수 있습니다.
1) @SqlResultSetMapping 사용
@SqlResultSetMapping(
name = "MemberDtoMapping",
classes = @ConstructorResult(
targetClass = MemberDto.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "username", type = String.class)
}
)
)
@Query(value = "SELECT id, username FROM member WHERE team_id = :teamId", nativeQuery = true)
@SqlResultSetMapping("MemberDtoMapping")
List<MemberDto> findMemberDtoByTeamId(@Param("teamId") Long teamId);
2) Constructor Expression 사용
@Query(value = "SELECT new com.example.dto.MemberDto(m.id, m.username) FROM Member m WHERE m.team.id = :teamId")
List<MemberDto> findMemberDtoByTeamId(@Param("teamId") Long teamId);
3. Native Query 사용 시 주의점
(1) 데이터베이스 종속성
- Native Query는 특정 데이터베이스의 SQL 문법을 따르므로, DBMS 변경 시 유지보수 비용이 증가할 수 있습니다.
(2) 결과 매핑 문제
- Native Query는 자동으로 엔티티와 매핑되지 않기 때문에, 컬럼명을 정확하게 매칭하거나 DTO를 활용해야 합니다.
(3) 동적 쿼리 지원 부족
- JPQL이나 QueryDSL과 달리, Native Query는 동적 쿼리 지원이 어렵기 때문에 String 기반으로 직접 조합해야 하는 불편함이 있습니다.
- 이를 해결하기 위해 EntityManager.createNativeQuery() 또는 QueryDSL + SQL Templates를 활용할 수도 있습니다.
4. 결론
Spring Data JPA의 Native Query는 복잡한 SQL을 실행하거나, 성능 최적화가 필요할 때 유용하지만, 데이터베이스 종속성과 유지보수 비용이 높아질 수 있습니다. 따라서 가급적이면 JPQL, QueryDSL을 우선적으로 고려하고, 필요할 때만 Native Query를 활용하는 것이 좋습니다.
'Back-End > JPA' 카테고리의 다른 글
JPA 트랜잭션 관리와 @Transactional의 동작 방식 (0) | 2025.03.09 |
---|---|
JPA랑 Hibernate (0) | 2025.03.09 |
JPA에서 일어나는 영속성 컨텍스트의 동작 원리 (1차 캐시, 변경 감지 등) (0) | 2025.03.09 |
JPA와 QueryDSL: 복잡한 쿼리 효율적으로 작성하기 (0) | 2025.03.09 |
JPA 성능 최적화: N+1 문제 해결 및 페치 전략 (Fetch Join, Entity Graph) (0) | 2025.03.09 |