JPA
JPA란 자바 ORM 기술에 대한 API 표준 명세를 의미합니다.
JPA는 ORM을 사용하기 위한 인터페이스를 모아둔 것이며, JPA를 사용하기 위해서는 JPA를 구현한 Hibernate, EclipseLink, DataNucleus 같은 ORM 프레임워크를 사용해야 합니다.
ORM
ORM이란 객체와 DB의 테이블이 매핑을 이루는 것을 말합니다. (Java 진영에 국한된 기술은 아닙니다.)
즉, 객체가 테이블이 되도록 매핑 시켜주는 것을 말합니다.
ORM을 이용하면 SQL Query가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 있습니다.
예를들어, User 테이블의 데이터를 출력하기 위해서 MySQL에서는 SELECT * FROM user; 라는 query를 실행해야 하지만,
ORM을 사용하면 User 테이블과 매핑된 객체를 user라 할 때, user.findAll() 라는 메서드 호출로 데이터 조회가 가능합니다.
query를 직접 작성하지 않고 메서드 호출만으로 query가 수행되다 보니, ORM을 사용하면 생산성이 매우 높아집니다.
그러나 query가 복잡해지면 ORM으로 표현하는데 한계가 있고, 성능이 raw query에 비해 느리다는 단점이 있는데요,
그래서 나중에 다루게 될 JPQL, QueryDSL 등을 사용하거나 한 프로젝트 내에서 Mybatis와 JPA를 같이 사용하기도 합니다.
Java에서 DB를 다룰 때, JDBC를 직접 사용하는 것보다 Mybatis를 사용했을 때 코드가 간결해지고 유지보수가 편했다는 것을 느꼈습니다.
Hibernate를 배우게 되면 Mybatis보다 코드가 더 간결하며, 더 객체 지향적이고 생산성이 매우 높다는 것을 느끼게 될 것입니다.
먼저, 전 세계 개발자들은 Mybatis와 Hibernate 중 어떤 것을 더 많이 사용하는지 알아보겠습니다.
동아시아를 제외하고 대부분 나라에서는 Hibernate를 압도적으로 많이 사용하고 있다는 것을 알 수 있습니다.
그만큼 JDBC를 직접 사용하는 Mybatis보다 JDBC를 노출하지 않고 ORM 기술을 사용하는 JPA를 선호한다는 것을 알 수 있습니다.
( JPA도 분명 단점이 존재하기 때문에 서비스에 따라 Mybatis를 사용할 지 JPA를 사용할 지 결정해야 합니다. )
아래의 모델링은 Book과 Album 테이블의 공통된 컬럼인 name과 price를 Item이라는 테이블에 정의하여 상속받도록 한 객체 지향 모델링(OOM)입니다.
ERD에서 사용하는 데이터 모델링과 달리 객체지향 모델링에는 상속이라는 개념이 있습니다.
모델링을 위와 같이 객체 지향적으로 설계 했을 때, SQL을 작성해야 하는 JDBC로 사용하기 위해서는 ERD로 다시 바꿔줘야 하는데 ERD에서는 상속 관계를 표현하기가 까다롭습니다.
그런데 객체 지향 설계에 대해서, 상속 관계를 잘 표현 해주는 데이터 모델링으로 바꿔주는 기술이 있다면?
그리고 상속 관계에 있는 테이블에 대해 Join도 알아서 해결 해준다면 객체 지향적인 설계가 가능할 것입니다.
정리하자면 JDBC API를 사용했을 때의 문제는 다음과 같습니다.
유사한 CURD SQL 반복 작업
객체를 단순히 데이터 전달 목적으로 사용할 뿐, 객체 지향적이지 못함 ( 페러다임 불일치 )
그래서 객체와 테이블을 매핑 시켜주는 ORM이 주목 받기 시작했고, 자바 진영에서는 JPA라는 표준 스펙이 정의 되었습니다.
장점
생산성
Hibernate는 SQL를 직접 사용하지 않고, 메서드 호출만으로 쿼리가 수행됩니다.
즉, SQL 반복 작업을 하지 않으므로 생산성이 매우 높아집니다.
그런데 SQL을 직접 사용하지 않는다고 해서 SQL을 몰라도 된다는 것은 아닙니다.
Hibernate가 수행한 쿼리를 콘솔로 출력하도록 설정을 할 수 있는데, 쿼리를 보면서 의도한 대로 쿼리가 짜여졌는지, 성능은 어떠한지에 대한 모니터링이 필요하기 때문에 SQL을 잘 알아야 합니다.
유지보수
테이블 컬럼이 하나 변경되었을 경우,
Mybatis에서는 관련 DAO의 파라미터, 결과, SQL 등을 모두 확인하여 수정해야 함
JPA를 사용하면 JPA가 이런 일들을 대신해주기 때문에 유지보수 측면에서 좋습니다.
특정 벤더에 종속적이지 않음
여러 DB 벤더( MySQL, Oracle 등.. )마다 SQL 사용이 조금씩 다르기 때문에 애플리케이션 개발 시 처음 선택한 DB를 나중에 바꾸는 것은 매우 어렵습니다.
그런데 JPA는 추상화된 데이터 접근 계층을 제공하기 때문에 특정 벤더에 종속적이지 않습니다.
즉, 설정 파일에서 JPA에게 어떤 DB를 사용하고 있는지 알려주기만 하면 얼마든지 DB를 바꿀 수가 있습니다.
단점
성능
메서드 호출로 쿼리를 실행한다는 것은 내부적으로 많은 동작이 있다는 것을 의미하므로, 직접 SQL을 호출하는 것보다 성능이 떨어질 수 있습니다.
실제로 초기의 ORM은 쿼리가 제대로 수행되지 않았고, 성능도 좋지 못했다고 합니다.
그러나 지금은 많이 발전하여, 좋은 성능을 보여주고 있고 계속 발전하고 있습니다.
세밀함
메서드 호출로 SQL을 실행하기 때문에 세밀함이 떨어집니다. 또한 객체간의 매핑( Entity Mapping )이 잘못되거나 JPA를 잘못 사용하여 의도하지 않은 동작을 할 수도 있구요.
복잡한 통계 분석 쿼리를 메서드 호출로 처리하는 것은 힘든 일입니다.
이것을 보완하기 위해 JPA에서는 SQL과 유사한 기술인 JPQL을 지원합니다.
물론 SQL 자체 쿼리를 작성할 수 있도록 지원도 하고 있습니다.
러닝커브
JPA를 잘 사용하기 위해서는 알아야 할 것이 많습니다.
그래서 이러한 복잡성을 해결하고자 최근에는 Spring Data JDBC가 주목을 받고 있습니다. ( 2018-09-21 첫 1.0.0 RELEASE )
JPA는 통계 쿼리처럼 복잡한 SQL을 수행하기 힘들기 때문에, 비즈니스에 따라 Mybatis를 사용할 지 Hibernate를 사용할 지 상황에 맞는 선택이 중요할 것입니다.
우리나라는 대부분 Mybatis를 사용하고 있는데, 그 이유는 우리나라 시장 대부분이 SI, 금융 시장이기 때문입니다.
비즈니스가 매우 복잡하고, 안정성을 중요시 하는 서비스일 경우에는 JPA보다 SQL을 작성하는 것이 더 좋다는 의도일 것입니다.
이미 SQL을 사용하여 개발된 애플리케이션이라면 JPA로 바꾸는 일도 쉽지 않기 때문에, 우리나라에서는 JPA가 많이 사용되지 못하는 것 같습니다.
그런데 최근에는 서비스 업체, 신규 프로젝트들은 JPA를 많이 사용하고 있는 것 같네요.