JPA, Hibernate, 그리고 Spring Data JPA의 차이점
JPA란?
자바 ORM 기술에 대한 API 표준 명세로, Java에서 제공하는 API이다.
자바 플랫폼 SE와 자바 플랫폼 EE를 사용하는 응용프로그램에서 관계형 데이터베이스의 관리를 표현하는 자바 API이다.
즉, JPA는 ORM을 사용하기 위한 표준 인터페이스를 모아둔 것이다.
기존에 EJB에서 제공되던 엔터티 빈(Entity Bean)을 대체하는 기술이다.
Springboot 패키지에 spring-boot-starter-data-jpa 라는 놈이 있는데, 이를 사용하면 JPA를 쉽게 사용할 수 있다.
JPA의 구현체에는 여러가지 기법이 있는데 그 중 가장 유명한 방식인 Hibernate를 많이 사용한다.
JPA의 대표적인 구현체로는 Hibernate, EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등이 있다.
이 구현체들을 ORM Framework라고 부른다.
JPA 구성 요소 (세 가지)
1) javax.persistance 패키지로 정의된 API 그 자체
2) JPQL(Java Persistence Query Language)
3) 객체/관계 메타데이터
ORM이란?
ORM(Object Relational Mapping)은 application과 Database사이를 맵핑시켜주는 도구이다. 한층더 추상화된 layer에서 Database에 대한 작업을 할 수 있게 해준다.
ORM을 이용하면 SQL Query가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 있습니다.
예를들어, User 테이블의 데이터를 출력하기 위해서 mysql에서는 SELECT * FROM user; 라는 query를 실행해야 하지만,
ORM을 사용하면 User 테이블과 매핑된 객체를 user라 할 때, user.findAll() 라는 메서드 호출로 데이터 조회가 가능합니다.
ORM을 사용함으로써 얻는 장단점은 다음과 같다.
1) ORM 장점
- 특정 DBMS에 종속되지 않는다.
- SQL문이 코드에 들어가지 않아 깔끔한 코드를 유지할 수 있다.
- ORM이 nesting데이터를 바인딩해준다.
2) ORM 단점
- RAW query에 비해 performance가 느리다.
- Query tuning이 힘들다.
- 서비스가 복잡해 질수록 ORM으로 할 수 있는 작업의 범위에 한계가 있다.
Hibernate란?
Hibernate는 JPA의 구현체 중 하나이다.
Hibernate가 SQL을 직접 사용하지 않는다고 해서 JDBC API를 사용하지 않는다는 것은 아니다.
Hibernate가 지원하는 메서드 내부에서는 JDBC API가 동작하고 있으며, 단지 개발자가 직접 SQL을 직접 작성하지 않을 뿐이다.
HQL(Hibernate Query Language)이라 불리는 매우 강력한 쿼리 언어를 포함하고 있다.
HQL은 SQL과 매우 비슷하며 추가적인 컨벤션을 정의할 수도 있다.
HQL은 완전히 객체 지향적이며 이로써 상속, 다형성, 관계등의 객체지향의 강점을 누릴 수 있다.
HQL쿼리는 자바 클래스와 프로퍼티의 이름을 제외하고는 대소문자를 구분한다.
HQL은 쿼리 결과로 객체를 반환하며 프로그래머에 의해 생성되고 직접적으로 접근할 수 있다.
HQL은 SQL에서는 지원하지 않는 페이지네이션이나 동적 프로파일링과 같은 향상된 기능을 제공한다.
HQL은 여러 테이블을 작업할 때 명시적인 join을 요구하지 않는다.
장점
- 객체지향적 개발 : 객체지향적으로 데이터를 관리할 수 있기 때문에 비즈니스 로직에 집중 할 수 있으며, 객체지향 개발이 가능하다. 로직을 쿼리에 집중하기 보다는 객체자체에 집중할 수 있다.
- 유지보수 : 테이블 생성, 변경, 관리가 쉽다. 테이블 칼럼이 하나 변경되었을 경우, Mybatis에서는 관련 DAO의 파라미터, 결과, SQL 등을 모두 확인하여 수정해야 하지만, JPA를 사용하면 JPA가 이런 일들을 대신해주기 때문에 유지보수 측면에서 좋다.
- 생산성 : 빠른 개발이 가능하다. Hibernate는 SQL을 직접 사용하지 않고, 메서드 호출만으로 쿼리가 수행된다. 즉, SQL반복 작업을 하지 않아도 되므로 생산성이 매우 높아진다. SQL을 직접 사용하지 않는다고해서 SQL을 몰라도 되는것은 아니다. Hibernate가 수행한 쿼리를 콘솔로 출력하도록 설정을 할 수 있는데, 쿼리를 보면서 의도한데로 쿼리가 잘 짜여졌는지, 성능은 어떠한지에 대해 모니터링이 필요하기 때문에 SQL을 잘 알아야 한다.
- 특정 벤더에 종속적이지 않다 : 여러 DB 벤더마다 쿼리 사용이 조금씩 다르기 때문에 애플리케이션 개발 시 처음 선택한 DB를 나중에 바꾸는 것은 매우 어렵다. 그런데 JPA는 추상화된 데이터 접근 계층을 제공하기 때문에 특정 벤더에 종속적이지 않습니다. 즉 설정 파일에서 JPA에게 어떤 DB를 사용하고 있는지 알려주기만 하면 얼마든지 DB를 바꿀 수가 있습니다.
단점
- 어렵다. (많은 내용이 감싸져 있기 때문에 JPA를 잘 사용하기 위해서는 알아야 할 것이 많다.)
잘 이해하고 사용하지 않으면 데이터 손실이 있을 수 있다. (persistence context)
또한, 성능상 문제가 있을 수 있다. - 물론 SQL을 직접 작성하는 것보다 메서드 호출만으로 쿼리를 수행한다는 것은 성능이 떨어질 수 있습니다. 실제로 초기의 ORM은 쿼리가 제대로 수행되지 않았고, 성능도 좋지 못했다. 그러나 지금은 많이 발전하여, 좋은 성능을 보여주고 있고 계속 발전하고 있다.
- 메서드 호출로 DB 데이터를 조작 하기 때문에 세밀함이 떨어집니다. 복잡한 통계 분석 쿼리를 메서드만으로 해결하는 것은 힘든 일입니다. 이것을 보완하기 위해 SQL과 유사한 기술인 JPQL을 지원합니다. 물론 SQL 자체 쿼리를 작성할 수 있도록 지원하고 있습니다.
Mybatis VS Hibernate
구글트렌드에 두 검색어를 조회해보았다.
국내를 비롯한 동아시아국가들은 Mybatis가 우세하다. 하지만, 대부분의 나라에서는 Hibernate를 압도적으로 많이 사용한다.
그 만큼 JDBC를 직접 사용하는 Mybatis보다 JDBC를 노출하지 않고 ORM 기술을 사용하는 JPA가 좋은 방식일 수 있다는 것이다.
하지만 JPA도 분명 단점이 존재하기 때문에, 서비스에 따라 무엇을 사용할지 결정해야한다.
Mybatis에서는 테이블마다 비슷한 CRUD SQL을 계속해서 반복적으로 사용하는 경우가 빈번하다.
또한, 테이블에 컬럼이 하나 추가되면 이와 관련된 모든 DAO의 SQL문을 수정해야한다.
그 이유는객체 모델링보다 데이터 중심 모델링(테이블 설계)을 우선시 했으며, 객체지향의 장점(추상화, 캡슐화, 정보은닉, 상속, 다형성)을 사용하지 않고 객체를 단순히 데이터 전달 목적( VO, DTO )에만 사용했기 때문이다.
다시 말하면 객체지향 개발자들이 개발하고 있는 방법이 전혀 객체 지향적이지 않았다는 것이다.
정리하자면 JDBC API를 사용했을 때의 문제는 다음과 같다.
- 유사한 CURD SQL 반복 작업
- 객체를 단순히 데이터 전달 목적으로 사용할 뿐, 객체 지향적이지 못함
그래서 객체와 테이블을 매핑 시켜주는 ORM이 주목 받기 시작했고, 자바에서는 JPA라는 표준 스펙이 정의 되었다.
구글 트렌드를 볼 때 우리나라는 대부분 Mybatis를 사용하고 있는데, 그 이유는 우리나라 시장 대부분이 SI, 금융 시장이기 때문이다.
비즈니스가 매우 복잡하고, 안정성을 중요시 하는 서비스일 경우에는 JPA보다 SQL을 작성하는 것이 좋을 것이라는 의도일 것이다.
그리고 이미 SQL을 사용하여 개발된 애플리케이션이라면 JPA로 바꾸는 일도 쉽지 않을 것입니다.
이러한 이유로 우리나라에서는 Hibernate가 뜨지 못하는 것 같다.
JPA는 통계 쿼리처럼 복잡한 SQL을 수행하기 힘들기 때문에 비즈니스에 따라 Mybatis를 사용할 지 Hibernate를 사용할 지 상황에 맞는 선택이 중요할 것입니다.
Hibernate가 SQL을 직접 사용하지 않는다고 해서 JDBC API를 사용하지 않는다는 것은 아니다.
단지 개발자가 직접 SQL을 직접 작성하지 않을 뿐, Hibernate가 지원하는 메서드 내부에서는 JDBC API가 동작하고 있다.
Spring Data JPA는 JPA를 쓰기 편하게 만들어놓은 모듈이다
Spring으로 개발하면서 단 한 번도 EntityManager를 직접 다뤄본 적이 없다. DB에 접근할 필요가 있는 대부분의 상황에서는 Repository를 정의하여 사용했다. 이 Repository가 바로 Spring Data JPA의 핵심이다.
Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로, 개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와준다. 이는 JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공함으로써 이루어진다. 사용자가 Repository 인터페이스에 정해진 규칙대로 메소드를 입력하면, Spring이 알아서 해당 메소드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해준다.
Spring Data JPA가 JPA를 추상화했다는 말은, Spring Data JPA의 Repository의 구현에서 JPA를 사용하고 있다는 것이다. 예를 들어, Repository 인터페이스의 기본 구현체인 SimpleJpaRepository의 코드를 보면 아래와 같이 내부적으로 EntityManager을 사용하고 있는 것을 볼 수 있다.