JPA ( Java Persistent API )와 ORM ( Object Relational Mapping )
JPA란 자바 ORM 기술에 대한 API 표준 명세를 의미합니다.
JPA는 ORM을 사용하기 위한 인터페이스를 모아둔 것이며, JPA를 사용하기 위해서는 JPA를 구현한 Hibernate, EclipseLink, DataNucleus 같은 ORM 프레임워크를 사용해야 합니다.
그렇다면 ORM은 무엇일까요?
ORM이란 객체와 DB의 테이블이 매핑을 이루는 것을 말합니다.
즉 객체가 테이블이 되도록 매핑 시켜주는 것을 말합니다.
ORM을 이용하면 SQL Query가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 있습니다.
예를들어, User 테이블의 데이터를 출력하기 위해서 mysql에서는 SELECT * FROM user; 라는 query를 실행해야 하지만,
ORM을 사용하면 User 테이블과 매핑된 객체를 user라 할 때, user.findAll() 라는 메서드 호출로 데이터 조회가 가능합니다.
query를 직접 작성하지 않고 메서드 호출만으로 query가 수행되다 보니, ORM을 사용하면 생산성이 매우 높아집니다.
그러나 query가 복잡해지면 ORM으로 표현하는데 한계가 있고, 성능이 raw query에 비해 느리다는 단점이 있습니다.
Mybatis vs Hibernate
JPA를 구현한 여러 프레임워크가 있지만 Hibernate가 JPA를 주도하고 있기 때문에 JPA를 Hibernate라 생각하고 혼용해서 사용하도록 하겠습니다.
JDBC를 직접 사용하는 것보다 Mybatis를 사용했을 때 코드가 간결해지고 유지보수가 편했다는 것을 느꼈습니다.
Hibernate를 배우게 되면 Mybatis보다 코드가 더 간결하며, 더 객체 지향적이고 생산성이 매우 높다는 것을 느끼게 될 것입니다.
먼저 전 세계 개발자들은 Mybatis와 Hibernate 중 어떤 것을 더 많이 사용하는지 알아보겠습니다.
[ 구글 트렌드 ( 링크 ) ]
동아시아를 제외하고 대부분 나라에서는 Hibernate를 압도적으로 많이 사용하고 있다는 것을 알 수 있습니다.
그만큼 JDBC를 직접 사용하는 Mybatis보다 JDBC를 노출하지 않고 ORM 기술을 사용하는 JPA가 좋은 방식일 수 있다는 것을 알 수 있습니다.
( JPA도 분명 단점이 존재하기 때문에 서비스에 따라 Mybatis를 사용할 지 JPA를 사용할 지 결정해야 합니다. )
이제 Hibernate가 이렇게 인기가 많아지게 된 배경을 살펴보기로 하겠습니다.
JPA 탄생 배경
Mybatis에서는 테이블 마다 비슷한 CRUD SQL을 계속 반복적으로 사용했었습니다.
소규모라도 Mybatis로 애플리케이션을 만들어 보셨다면, DAO 개발이 매우 반복되는 작업이며, 이 작업이 매우 귀찮다는 경험을 해보았을 것입니다.
또한 테이블에 칼럼이 하나 추가된다면 이와 관련된 모든 DAO의 SQL문을 수정해야 합니다.
즉 DAO와 테이블은 강한 의존성을 갖고 있습니다.
이러한 이유로 SQL을 자동으로 생성해주는 툴이 개발 되기도 했지만 반복 작업은 마찬가지였고, 큰 효과를 얻지 못했던 것 같습니다.
그 이유는 객체 모델링보다 데이터 중심 모델링(테이블 설계)을 우선시 했으며, 객체지향의 장점(추상화, 캡슐화, 정보은닉, 상속, 다형성)을 사용하지 않고 객체를 단순히 데이터 전달 목적( VO, DTO )에만 사용했기 때문입니다.
다시 말하면 객체지향 개발자들이 개발하고 있는 방법이 전혀 객체 지향적이지 않다는 것을 느끼게 되었습니다.
아래의 모델링은 Book과 Album 테이블의 공통된 칼럼인 name과 price를 Item이라는 테이블에 정의하여 상속받도록 한 객체 지향 모델링입니다.
ERD에서 사용하는 데이터 모델링과 달리 상속이라는 개념이 있습니다.
모델링을 위와 같이 객체 지향적으로 설계 했을 때, SQL을 작성해야 하는 JDBC로 사용하기 위해서는 ERD로 바꿔야 합니다.
그런데 ERD에서는 상속 관계를 표현하기가 까다롭습니다.
그런데 객체 지향 설계에 대해서, 상속 관계를 잘 표현 해주는 데이터 모델링으로 바꿔주는 기술이 있다면?
그리고 상속 관계에 있는 테이블에 대해 join도 알아서 해결 해준다면 객체 지향적인 설계가 가능할 것입니다.
정리하자면 JDBC API를 사용했을 때의 문제는 다음과 같습니다.
1. 유사한 CURD SQL 반복 작업
2. 객체를 단순히 데이터 전달 목적으로 사용할 뿐, 객체 지향적이지 못함 ( 페러다임 불일치 )
그래서 객체와 테이블을 매핑 시켜주는 ORM이 주목 받기 시작했고, 자바 진영에서는 JPA라는 표준 스펙이 정의 되었습니다.
Hibernate의 특징
Hibernate를 사용하면 위의 문제들을 해결할 수 있습니다.
그리고 항상 완벽한 기술은 없듯이 Hibernate에도 단점이 존재하는데, 지금부터 Hibernate의 장단점을 알아보겠습니다.
장점
1) 생산성
Hibernate는 SQL를 직접 사용하지 않고, 메서드 호출만으로 쿼리가 수행됩니다.
즉 SQL 반복 작업을 하지 않으므로 생산성이 매우 높아집니다.
그런데 SQL을 직접 사용하지 않는다고 해서 SQL을 몰라도 된다는 것은 아닙니다.
Hibernate가 수행한 쿼리를 콘솔로 출력하도록 설정을 할 수 있는데, 쿼리를 보면서 의도한 대로 쿼리가 짜여졌는지, 성능은 어떠한지에 대한 모니터링이 필요하기 때문에 SQL을 잘 알아야 합니다.
2) 유지보수
Hibernate 사용의 또 다른 장점은 테이블 칼럼이 하나 변경되었을 경우, Mybatis에서는 관련 DAO의 파라미터, 결과, SQL 등을 모두 확인하여 수정해야 하지만, JPA를 사용하면 JPA가 이런 일들을 대신해주기 때문에 유지보수 측면에서 좋습니다.
3) 특정 벤더에 종속적이지 않음
여러 DB 벤더마다 쿼리 사용이 조금씩 다르기 때문에 애플리케이션 개발 시 처음 선택한 DB를 나중에 바꾸는 것은 매우 어렵습니다.
그런데 JPA는 추상화된 데이터 접근 계층을 제공하기 때문에 특정 벤더에 종속적이지 않습니다.
즉 설정 파일에서 JPA에게 어떤 DB를 사용하고 있는지 알려주기만 하면 얼마든지 DB를 바꿀 수가 있습니다.
단점
1) 성능
물론 SQL을 직접 작성하는 것보다 메서드 호출만으로 쿼리를 수행한다는 것은 성능이 떨어질 수 있습니다.
실제로 초기의 ORM은 쿼리가 제대로 수행되지 않았고, 성능도 좋지 못했다고 합니다.
그러나 지금은 많이 발전하여, 좋은 성능을 보여주고 있고 계속 발전하고 있습니다.
2) 세밀함
메서드 호출로 DB 데이터를 조작 하기 때문에 세밀함이 떨어집니다.
복잡한 통계 분석 쿼리를 메서드만으로 해결하는 것은 힘든 일입니다.
이것을 보완하기 위해 SQL과 유사한 기술인 JPQL을 지원합니다.
물론 SQL 자체 쿼리를 작성할 수 있도록 지원하고 있습니다.
3) 러닝커브
JPA를 잘 사용하기 위해서는 알아야 할 것이 많습니다.
즉 러닝커브가 높습니다.
정리
처음에 살펴본 구글 트렌드를 볼 때 우리나라는 대부분 Mybatis를 사용하고 있는데, 그 이유는 우리나라 시장 대부분이 SI, 금융 시장이기 때문입니다.
비즈니스가 매우 복잡하고, 안정성을 중요시 하는 서비스일 경우에는 JPA보다 SQL을 작성하는 것이 좋을 것이라는 의도일 것입니다.
그리고 이미 SQL을 사용하여 개발된 애플리케이션이라면 JPA로 바꾸는 일도 쉽지 않을 것입니다.
이러한 이유로 우리나라에서는 Hibernate가 뜨지 못하는 것 같습니다.
JPA는 통계 쿼리처럼 복잡한 SQL을 수행하기 힘들기 때문에 비즈니스에 따라 Mybatis를 사용할 지 Hibernate를 사용할 지 상황에 맞는 선택이 중요할 것입니다.
Hibernate가 SQL을 직접 사용하지 않는다고 해서 JDBC API를 사용하지 않는다는 것은 아닙니다.
Hibernate가 지원하는 메서드 내부에서는 JDBC API가 동작하고 있으며, 단지 개발자가 직접 SQL을 직접 작성하지 않을 뿐입니다.
ORM은 꾸준히 발전하고 있는 기술이며, 저는 높은 생산성을 자랑하는 ORM을 매우 좋아합니다.
처음 접한 프레임워크가 Ruby on Rails 였는데, ROR에서는 ORM이 내장되어 있습니다.
그 영향인지는 몰라도 Node.js 공부할 때도 ORM이 있는지 먼저 찾았었네요.
역시나 자바에서도 Hibernate라는 멋진 기술이 있었습니다.
'JAVA > Spring' 카테고리의 다른 글
RestTemplate (정의, 특징, URLConnection, HttpClient, 동작원리, 사용법, connection pool 적용) (0) | 2019.03.21 |
---|---|
Spring boot yml 파일 사용 (1) | 2019.03.21 |
Mapper XML 파일 (0) | 2016.06.23 |
logback 설정 (0) | 2016.06.17 |
iBatis MyBatis 차이 (0) | 2016.06.17 |