SpringBoot

[SpringBoot] JPA / Hibernate / Spring Data JPA

감자꾸 2025. 10. 13. 02:32

우리가 스프링부트로 프로젝트를 진행하다 보면, jpa / hibernate/ spring data jpa 를 마주한다. 

우리는 위 세가지를 통해 데이터를 저장하고 조회하고 삭제하고 수정할 수 있다.

 

JPA (Java Persistence API)

JPA는 자바 진영의 표준 ORM 명세이다. 인터페이스와 규칙만 정의한 것이지 실제 구현체는 아니다. JPA 스펙은 데이터베이스와 자바 객체를 매핑하는 방식을 표준화하고, 어떤 메서드가 있어야 하고 어떻게 동작해야 하는지를 정의한다.

쉽게 말해 JPA는 "이렇게 해야 한다"는 규칙 모음 이라고 생각하면 쉽다.

Hibernate

Hibernate는 JPA를 구현한 구체적인 ORM 프레임워크이다. JPA 표준을 따르면서도 Hibernate만의 추가 기능과 최적화를 제공한다. Hibernate가 없으면 JPA 인터페이스들은 동작할 수 없으니까, Hibernate는 JPA 표준의 실제 돌아가는 핵심 부분이라고 할 수 있다.

Hibernate는 오랫동안 자바 진영에서 가장 널리 사용되는 ORM이다.

 

위 개념을 통해 알 수 있는 것은 " Hibernate는 JPA를 구현한 구체적인 ORM 프레임워크"인 것이지, JPA를 사용하기 위해서 반드시 Hibernate를 사용할 필요가 없다. Hibernate의 작동 방식이 마음에 들지 않는다면 언제든지 DataNucleus, EclipseLink 등 다른 JPA 구현체를 사용해도 되고, 심지어 본인이 직접 JPA를 구현해서 사용할 수도 있다.

하지만 우리가 Hibernate를 쓰는 이유는 오랜 기간 검증되어 안정성과 기능 면에서 높은 완성도를 갖추고 있기 때문이다.

Spring Data JPA

Spring Data JPA는 Spring 생태계에서 JPA를 더 쉽게 사용하기 위한 추상화 계층이다. JPA 위에 한 단계를 더 얹은 것으로, 반복적인 데이터 접근 코드를 줄여 준다.

예를 들어 일반적인 CRUD 작업들(저장, 조회, 수정, 삭제)을 메서드 이름만으로 자동으로 구현해준다. findByName(), findByAgeGreaterThan() 같은 식으로 메서드를 선언하면 Spring Data JPA가 자동으로 쿼리를 생성해준다.

 

아래 코드가 그 예시이다.

 

public interface MemberRepository extends JpaRepository<Member, Long> {
    Optional<Member> findByProviderAndProviderId(Provider provider, String providerId);
}

 

 

이 코드를 보면 의문점이 생길 것이다. 그럼 저 Repository가 무엇인가?

Repository란?

Repository는 데이터 접근 계층(Data Access Layer)을 추상화한 디자인 패턴이다. 데이터베이스와의 상호작용을 비즈니스 로직으로부터 분리하는 역할을 한다.

 

즉, 사용자가 Repository 인터페이스에 정해진 규칙대로 메소드를 입력하면, Spring이 알아서 해당 메소드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해준다.

 

다시 코드를 살펴보면,

public interface MemberRepository extends JpaRepository<Member, Long> {
    Optional<Member> findByProviderAndProviderId(Provider provider, String providerId);
}

 

여기서 중요한 점은 인터페이스일 뿐 구현체가 없다는 것이다. 메서드 본체가 없다는 것인데,,,  그럼 누가 이것을 구현할까?

바로,, Spring Data JPA가 런타임에 자동으로 구현체를 생성한다.

Spring Data JPA는 메서드 이름을 분석해서 자동으로 SQL 쿼리를 생성하고, 그 메서드를 구현하는 클래스를 동적으로 만들어낸다.

 

Optional<Member> member = memberRepository.findByProviderAndProviderId(provider, providerId);

이 코드가 spring Data JPA를 통해 아래처럼 생성된다.

@Override
public Optional<Member> findByProviderAndProviderId(Provider provider, BINGINT providerId) {
    return Optional.ofNullable(
        em.createQuery(
            "SELECT m FROM Member m WHERE m.provider = :provider AND m.providerId = :providerId",
            Member.class
        )
        .setParameter("provider", provider)
        .setParameter("providerId", providerId)
        .getSingleResult()
    );
}

 

그럼 여기서 한 가지 헷갈리는 점이 생긴다..

 

그럼 Hibernate가 하는 건 뭔데??

 

위 코드를 다시 살펴보면

  • em.createQuery()는 JPA 인터페이스이고, 이것을 실제로 동작하게 만드는 게 Hibernate다.

즉, Hibernate는 다음과 같은 일을 한다:

  1. SQL 쿼리를 실제로 생성하고 실행: JPA가 정의한 쿼리를 데이터베이스가 이해하는 SQL로 변환
  2. 결과를 자바 객체로 매핑: 데이터베이스에서 가져온 행(row)을 Member 객체로 변환
  3. 데이터베이스와의 실제 통신: JDBC를 통해 데이터베이스에 쿼리 실행

 

계층 구조를 보면,

 

MemberRepository 인터페이스
         ↓
Spring Data JPA (자동으로 구현체 생성)
         ↓
JPA 표준 인터페이스 (EntityManager, Query 등)
         ↓
Hibernate (JPA를 실제로 구현 - 쿼리 생성, 객체 매핑 등)
         ↓
데이터베이스

 

 

즉 JPQL 이 SQL로 변환이 되는 것이다.

// JPQL (JPA 표준)
"SELECT m FROM Member m WHERE m.provider = :provider AND m.providerId = :providerId"

↓ Hibernate가 변환

// SQL
"SELECT member.* FROM member WHERE member.provider = ? AND member.provider_id = ?"

 

 

 

실제 프로젝트에서 위 API를 돌리면, 터미널에 아래와 깉이 Hibernate가 작동된 것을 확인할 수 있다.

SpringData JPA
Hibernate

 

 

참고

https://livenow14.tistory.com/70

 

[DB] 하이버네이트(Hibernate)란?

ORM 기술에 대한 명세인 JPA(Java Persistence API)의 구현체의 한 종류 JPA의 구현체이므로 JPA의 특징을 함께 정리했어요. Hibernate란? 하이버네이트는 자바 언어를 위한 ORM 프레임워크에요. JPA의 구현체

livenow14.tistory.com

https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/