JPA, Hibernate, 그리고 Spring Data JPA의 차이점

정웅·2026년 1월 7일

개발지식

목록 보기
3/3
post-thumbnail

들어가며

Spring Boot로 백엔드 개발을 시작하면 가장 먼저 마주치는 개념 중 하나가 JPA다. 코드를 작성하다 보면 JPA, Hibernate, Spring Data JPA라는 용어들이 뒤섞여 등장하면서 혼란스러워진다.

“JPA 쓴다는데 왜 Hibernate 설정이 보이지?”

“Spring Data JPA는 JPA랑 뭐가 달라?”

이 글에서는 세 가지의 역할과 관계를 한 번에 정리해본다.


JPA: 표준 명세

JPA(Java Persistence API, Jakarta Persistence)는 자바 진영의 ORM 표준 명세(specification)다. 즉, 동작하는 라이브러리 자체가 아니라 “어떻게 DB를 다룰지”에 대한 규약(인터페이스/어노테이션/동작 규칙)이다.

예를 들어, 핵심 인터페이스 중 하나인 EntityManager는 구현이 아니라 시그니처 중심의 API로 제공된다.

import jakarta.persistence.EntityManager;

public interface EntityManager {
    void persist(Object entity);
    <T> T merge(T entity);
    void remove(Object entity);
    <T> T find(Class<T> entityClass, Object primaryKey);
}

참고: Spring Boot 3.x부터는 javax.persistence가 아니라 jakarta.persistence 패키지를 사용한다. (JPA 3.0에서 javax. → jakarta.로 변경)


Hibernate: JPA의 대표 구현체(ORM Provider)

Hibernate는 JPA 명세를 실제로 동작하게 만드는 ORM 구현체(Provider)다. JPA를 사용하면 내부적으로는 Hibernate 같은 구현체가 SQL 생성/실행, 영속성 컨텍스트 관리 등을 수행한다.

정리하면:

JPA = 표준(규칙)

Hibernate = 그 규칙을 구현한 엔진

Hibernate 외에도 EclipseLink 등 다른 JPA 구현체가 존재하지만, 실무에서는 Hibernate가 가장 널리 사용된다.

참고: EntityManager(JPA)와 Session(Hibernate)은 역할이 비슷하게 느껴질 수 있지만, 하나가 다른 하나로 “완전히 치환”되는 개념이라기보다는 표준 API vs Hibernate 고유 API라는 관점으로 이해하는 게 안전하다.


Spring Data JPA: Repository 추상화로 “더 편하게”

실제 Spring 프로젝트에서 EntityManager를 직접 다루는 경우는 많지 않다. 보통은 JpaRepository를 상속받아 메서드 이름만으로 조회 로직을 만들거나, 기본 CRUD를 자동으로 사용한다.

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
    Optional<User> findByEmail(String email);
}

Spring Data JPA의 핵심은 “JPA를 대체한다”가 아니라, JPA 위에서 Repository 패턴을 제공해 개발을 편하게 해준다는 점이다.

실제로 JpaRepository의 기본 구현체는 내부에서 EntityManager를 사용한다. 예를 들어 findByIdEntityManager.find 기반으로 동작한다.


계층 구조 정리

각 계층의 역할

Spring Data JPA: Repository 패턴, 메서드명 기반 쿼리, 페이징/정렬 등 “개발 편의”
JPA: ORM 표준 API/동작 규약(명세)
Hibernate: JPA를 실제로 실행하는 ORM 엔진(구현체)
JDBC: DB 연결 및 SQL 실행 레벨


마치며

실무에서는 대부분 Spring Data JPA의 Repository만으로 개발이 가능하다. 하지만 복잡한 쿼리나 성능 최적화가 필요한 순간에는 JPQL/네이티브 쿼리, 혹은 EntityManager를 직접 사용하는 선택지가 필요해질 수 있겠다.

그때 “지금 내가 어느 계층을 쓰고 있는지”를 알고 있으면, 문제를 더 정확한 레벨에서 해결할 수 있을 것이다.

profile
즐거운 개발 :) 신입 서버 개발자입니다

0개의 댓글