[Spring] JPA, Hibernate, Spring Data JPA 는 다르다!
Spring

[Spring] JPA, Hibernate, Spring Data JPA 는 다르다!

728x90

혹시 JPA에 대해 이런 경험이 있으신가요? 

A: 어? JPA 저도 쓰는데요 그거 완전 편하죠 ㅎㅎㅎ 막 findBy어쩌구하면 DB에서 다 찾아주잖아요
나: 아 그래요? (구글검색) J..P..A..란..? -> JPA란 "자바 ORM에 대한 API 표준 명세"이다.
나: 아니 API 도 아니고 그냥 표준 "명세"라는데 그걸 쓸수가 있나..?
나: J..P.....A 사용법 검색 -> 안녕하세요 잇님들 요즘 날씨가 쌀쌀하죠^^ 오늘은 JPA를 사용해보는법에 대해서 알아볼거에요. 이렇게 설정해주세요
#JPA 설정

#하이버네이트 Dialect (사투리) 설정
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect

#하이버네이트가 실행하는 모든 SQL문을 콘솔로 출력해 준다.
spring.jpa.properties.hibernate.show_sql=true

#콘솔에 출력되는 JPA 실행 쿼리를 가독성있게 표현한다.
spring.jpa.properties.hibernate.format_sql=true

#디버깅이 용이하도록 SQL문 이외에 추가적인 정보를 출력해 준다.
spring.jpa.properties.hibernate.use_sql_comments=true​
나: 하이버네이트..? 난 JPA 쓸건데 ㅠㅡㅜ JPA 별명인가?? 몰라 일단 따라해보자

...라는건 제 경험입니다 하하.. 부끄럽지만 사실입니다.

 

이처럼 JPA에 대해 알아보면 세분화 돼있는 것을 볼 수가 있는데, 보통은 Spring Data JPA를 줄여서 JPA 라고 말하고는 합니다.

 

그럼 이 3가지의 정확한 차이점을 알고 쓸 수 있도록 한번 알아볼까요?

 

**정확히 알고나서 "야 니가 말하는건 Spring Data JPA지 JPA 가 아니야. 정확히 말해 ㅡㅡ" 라는 사회성 떨어지는 훈수를 둬보도록 합시다!!


JPA (Java Persistance API)

JPA란 위에서 검색해본대로 자바 ORM기술에 대한 API 표준 명세입니다.

 

"API 표준 명세"란 무엇이냐?

비유하자면 만드는데 필요한 정해진 부품같은 것이죠. 목표만 정해주면 과정에 정해진 정답은 없는대신, 통일성이 없이 무분별하게 만들어지게 됩니다. 그렇게 하나가 만들어지면 거기서 또 파생이되고 또 파생이되고, 결국에 나중에 사용자가 자바로 ORM 기술을 사용하려고 보면 몇만가지가 넘는 방법을 마주하게 될 것입니다. 사용자 입장에서는 어떤게 가장 효율적인지 어떤 방법을 기준으로 개선을 해야할지에 대해 큰 고민이 생기겠죠.

 

따라서 "자바로 ORM 기술을 사용할때는 JPA에서 제공하는 인터페이스와 각종 부품들을 사용해야만 자바의 ORM 기술이라고 인정해주겠다" 라고해서 모아둔 부품들이 바로 JPA 입니다. 그래서 실제로 JPA를 정의한 javax.persistence 패키지의 대부분은 interface , enum , Exception, 그리고  Annotation 들로 이루어져 있습니다.

 

ORM (Object Relational Mapping) 이 뭐에요?

ORM 기술이란 객체지향 애플리케이션에서 사용하는 객체와 DB를 자동으로 매핑하는 기술입니다. 자바 ORM 기술을 구현한 가장 유명한 프레임워크/모듈에는 MyBatis, Spring Data JPA 가 있죠. 둘의 공통점은 분명 객체를 저장하도록 했는데, 저장을 해보면 DB 테이블에 각 row에 column 별로 데이터가 들어가있고, 불러올때도 마찬가지라는겁니다.

 

생각해보니 이상하지 않나요? 각각 DB에 데이터를 넣을때는 db에 접속해서 sql문 명령어를 입력해야하고, 자바 객체를 만드려면 객체를 새로 생성하고 값을 집어넣어야하는 코드가 필요한데.. 그렇죠! 바로 이 과정을 간편하게 해주는 기술이 ORM 입니다.

 

JPA 정리

따라서 JPA 란 자바에서 객체와 DB를 연결해주는 기술을 구현하기 위해 필요한 부품을 모아놓은 표준 명세라고 할 수 있겠습니다!


하이버네이트(Hibernate)

오호 그럼 JPA에 있는 부품들을 써서 내가 ORM을 구현해서 만들고 사용하면 되는건가요? 아뇨 이미 저쪽 신사분께서 보내셨습니다 (>_ㅇ) 어떤 신사분이시냐고요? 바로 하이버네이트(Hibernate)입니다.

이미 구현된 ORM을 주는 Hibernate

하이버네이트처럼 JPA의 명세로 ORM 기술을 구현한 프레임워크는 여러가지가 있는데 대표적으로 Hibernate, EclipseLink, DataNucleus 가 있습니다. (그 외에도 OpenJPA, TopLink Essentials 등등 많습니다)

 

기술을 구현했다는건, 저 부품들을 조립해서 쓸 수 있는 상태를 만들어놓았다는 것이죠! 따라서 Hibernate 에서 제공하는 메소드를 사용한다면, 위에서 말했던 ORM - 객체와 DB 테이블을 연결함 이 가능해지는 것이죠.

 

대표적인 기술이 바로 개발자가 SQL을 직접 작성하지않고, 객체만 던져주면 알아서 DB 테이블에 들어가도록 해주는 것입니다. DB를 조회할때도 SQL문 없이 바로 원하는 DB내의 데이터를 객체로 넣어줄 수 있죠. 그림으로 보면 아래와 같습니다

정리하면 다음과 같습니다

  • Hibernate는 JPA의 구현체 중 하나입니다.
  • Hibernate는 SQL을 사용하지 않고 직관적인 코드(메소드)를 사용해 데이터를 조작할 수 있습니다.
  • Hibernate가 SQL을 직접 사용하지 않는다고 해서 JDBC API를 사용하지 않는 것은 아닙니다.
  • Hibernate가 지원하는 메소드 내부에서는 JDBC API가 동작하고 있으며, 단지 개발자가 직접 SQL을 작성하지 않을 뿐 입니다.

조금 더 디테일하게 구현부분을 보면 JPA의 핵심인 EntityManagerFactory EntityManager EntityTransaction Hibernate에서는 각각 SessionFactory , Session , Transaction 으로 상속받고 각각 Impl로 구현하고 있음을 확인할 수 있습니다.

 

이들이 핵심인 이유는 영속성 컨텍스트(persistence context)를 관리해주기 때문인데요. 영속성 컨텍스트가 어떻게보면 JPA의 핵심이자 전부(..까지는아닌가?)라고 볼 수 있습니다. 영속성 컨텍스트가 궁금하시면 여기를 참고해주세요!


Spring Data JPA

뭐야 그럼 끝났네요?? Hibernate만 쓰면 이제 ORM 사용할 수 있는거잖아요.. Spring Data JPA는 왜 존ㅈ.. 흡... (쉿.. 귀찮은 널 위해 더 간편한걸 가져왔어)

 

Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로,  Repository라는 인터페이스를 제공해서 개발자가 JPA를 더 쉽게 사용할 수 있도록 도와줍니다. 여기서 절대 오해하시면 안되는게 "인터페이스"를 제공한다고 했죠! 인터페이스는 구현된게 아니라 JPA에 있는 부품처럼 사용하는 부품을 의미합니다. 따라서 Spring Data JPA는 Hibernate 같은 구현체가 아닙니다.

 

오잉?? 뭐야 Hibernate는 구현체고 얘는 인터페이스인데 왜 더 간편하죠..? 내가 구현해야된다는 말이잖아요;;

위에서 설명했듯이 JPA를 구현한 ORM 기술은 여러가지가 있습니다 (Hibernate, EclipseLink, DataNucleus 등등). 따라서 직접 사용한다면 각 기술마다 메소드도 다르고 문법도 조금씩 다를 수 있겠죠. 따라서 Spring Data JPA는 이 ORM 기술중에 어떤걸 사용하든지 사용자는 Repository 라는 인터페이스로 접근해서 똑같은 메소드를 호출해서 ORM 기술 (객체를 사용해서 DB CRUD)을 사용할 수 있게 해줍니다.

 

따라서, Spring Data JPA는 자체적으로 동작할 수 없고, Hibenate같은 ORM 구현체가 반드시 필요합니다

 

직접 Spring Data JPA 가 적용된 코드를 보신분들은 아래와 같은 형식의 코드를 많이 보셨을겁니다.

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ProgramMaHistRepository extends JpaRepository<ProgramMaHist, Long> {
	public void findBySeq(long seq);
	public int countByRegisterIdAndMode(String registerId, String mode);
	List<ProgramMaHist> findBySiteSeqAndMailCodeAndActiveAndDeleted(Long siteSeq, String channelType, String active, String deleted);
	List<ProgramMaHist> findBySiteSeqAndMailCodeAndDeleted(Long siteSeq, String channelType, String deleted);
}

이처럼 개발자가 Repository 인터페이스에 정해진 규칙대로 메소드를 입력하면, Spring이 알아서 해당 메소드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해줍니다. 그리고 Repository는 말그대로 인터페이스이기 때문에 Hibernate 말고 다른 ORM 구현체를 사용할 수도 있습니다. 바로 이게 핵심입니다.


정리

그림으로 위 3가지의 관계를 보면 아래와 같습니다

앞으로는 이 3개를 한번에 JPA라고 부르기보다 확실한 명칭으로 불러주는게 어떨까요? :))

 

 

출처:
- [JPA] JPA와 Hibernate 그리고 Spring Data JPA
- ORM(Object Relational Mapping)이 뭘까? 🤔
- JPA, Hibernate, 그리고 Spring Data JPA의 차이점
728x90