본문 바로가기
공부 자료/Java Spring

[Java Spring] JPA와 Spring Data JPA

by 미노킴 2022. 12. 1.

*이 글의 내용은 제가 이해한 것을 바탕으로 작성되었습니다. 글의 내용 중 잘못된 내용이 있다면 댓글로 피드백 해주시면 감사하겠습니다.

0. 개요

이동욱님의 '스프링 부트와 AWS로 혼자 구현하는 웹 서비스' 로 공부를 하던 중 JPA와 Spring Data JPA에 대한 설명을 보았었다. 처음 읽을 때는 가볍게 넘겼는데, JPA에 대해 공부하다 보니 둘은 완전히 다른 개념이고 그 차이를 이해하는 게 꽤 중요하다는 것을 알게 되었다.

 

그래서 이 글에서는 JPA와 Spinrg Data JPA가 정확히 어떻게 다른 것인지 설명하고자 한다.

 

이 글을 읽기 전에 Entity manager와 영속성 컨텍스트에 대해 알고 있으면 좋다. 해당 내용은 아래 글에서 확인할 수 있다.

https://kimdirector1090.tistory.com/92

 

[Java Spring] Entity Manager와 영속성 컨텍스트

 

kimdirector1090.tistory.com

 

1. JPA는 '인터페이스' 이다

JPA는 Java Persistence API의 약자로, 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 '인터페이스' 이다. JPA는 인터페이스일 뿐 특정 기능을 하는 '라이브러리'가 아니다.

 

JPA는 단순히 명세이기 때문에 구현이 없다. JPA를 정의한 javax.persistence 패키지의 대부분은 interface, enum, Exception, 그리고 각종 Annotation으로 이루어져 있다. 예를 들어, JPA의 핵심이 되는 EntityManager는 아래와 같이 javax.persistence.EntityManager 라는 파일에 interface로 정의되어 있다.

 

package javax.persistence;

import ...

public interface EntityManager {

    public void persist(Object entity);

    public <T> T merge(T entity);

    public void remove(Object entity);

    public <T> T find(Class<T> entityClass, Object primaryKey);

    // More interface methods...
}

 

2. JPA는 구현체가 필요하다

JPA는 인터페이스이므로 실제로 구현된 기능은 아무것도 없다. 우리가 실제로 사용해야 하는 것은 JPA 인터페이스를 활용한 '구현체'이다.

 

Hibernate도 JPA의 여러 구현체 중 하나이다. 그렇기에 DataNucleus, EclipseLink 같은 다른 JPA 구현체를 사용하거나 우리가 직접 JPA 구현체를 만들어서 사용할 수 있다. 다만 현재 Hibernate가 다른 구현체들에 비해 완성도가 높기 때문에 대부분 Hibernate를 사용하는 것이다. 더 좋은 구현체가 나온다면 Hibernate는 얼마든지 교체될 수 있다.

 

JPA와 Hibernate(구현체)의 관계는 자바의 interface와 해당 interface를 구현한 class와 같다. 

 

3. Spring Data JPA는 구현체를 쓰기 위한 '모듈'이다

Spring Data JPA는 Spring에서 제공하는 '모듈' 중 하나로,개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와준다.

 

Spring Data JPA는 JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공한다. 해당 모듈에는 적절한 쿼리를 날리는 구현체들이 만들어져 있어서 개발자들은 Repository의 메소드들로 쿼리를 대신 진행할 수 있다.

 

Repository는 JPA를 추상화한 것이기에 Repository의 구현체들은 내부적으로 JPA를 사용하고 있다. Repository 인터페이스의 기본 구현체인 SimpleJpaRepository의 코드를 보면 아래와 같이 내부적으로 EntityManager을 사용하고 있는 것을 볼 수 있다.

package org.springframework.data.jpa.repository.support;

import ...

public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {

    private final EntityManager em;

    public Optional<T> findById(ID id) {

        Assert.notNull(id, ID_MUST_NOT_BE_NULL);

        Class<T> domainType = getDomainClass();

        if (metadata == null) {
            return Optional.ofNullable(em.find(domainType, id));
        }

        LockModeType type = metadata.getLockModeType();

        Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();

        return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
    }

    // Other methods...
}

 

4. 요약

전체적인 흐름을 그림으로 요약하자면 다음과 같다.

출처: suhwan.dev

 

레퍼런스

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