[JPA] JPA란 무엇일까?

JPA란?
JPA(Java Persistence API)란 자바 진영의 ORM 기술 표준이다.
이때, ORM(Object Relational Mapping)이란 객체로 연결해준다는 뜻으로, 어플리케이션과 데이터베이스의 통신이 있을 경우 개발자가 가 SQL이 아닌 객체로 데이터베이스에 접근할 수 있도록 만드는 기술이다.
이러한 기술이 왜 탄생하게 되었을까?
JPA가 필요한 이유
먼저 객체를 표현하기 위해 관계형 데이터베이스를 어떻게 구성해야하는지 봐야한다.
public interface Item {
private int id;
private int price;
}
public class Book extends Item {
private int id; // Item's primary key, Book's forien key
private String author;
private String isbn;
}
Item 인터페이스를 Book 클래스가 상속받고 있다.
관계형 데이터베이스에서 상속 관계를 표현할 수 있는 방법은 없다. 하지만, Item의 id를 Item 테이블의 Primary Key로 설정하고 Book 테이블에서 Forien Key 로써 참조하면 연관 관계를 표현할 수는 있다.

관계형 데이터 베이스를 이렇게 구성할 경우 다음과 같은 문제가 있다.
- 유지보수
Book 클래스에 private String name 필드가 추가되었다.
public class Book extends Item {
private int id;
private String author;
private String isbn;
private String name;
}
데이터 베이스에도 추가해야 한다.

아직 끝이 아니다..
Book 테이블에 접근하는 모든 SQL 쿼리를 찾아 수정해야 한다.
INSERT INTO BOOK(AUTHOR, ISBN, NAME) VALUES...
SELECT AUTHOR, NAME FROM BOOK B...
UPDATE BOOK SET ... NAME = ?...
실제 서비스일 경우 많은 양의 작업을 해야할 것이다. (야근..)
- 객체 그래프 탐색 범위

객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
하지만, 객체 조회 시 처음으로 실행하는 SQL에 따라 탐색 범위가 결정된다.
SELECT M.*, O.*
FROM MEMBER M JOIN ORDER O
ON M.ORDER_ID = O.ORDER_ID
order.getMember() // OK
order.getDelivery() // null
이러한 현상은 엔티티에 대한 신뢰 문제까지 이어진다.
즉, DB에서 정보를 가져온 DAO 객체가 어떠한 값을 가질지 보장하지 못한다는 뜻이다.
- 객체 로딩
모든 DAO 객체를 로딩할 수 없다.
Member 만 조회하는 객체, Member와 Team을 조회하는 객체, Member와 Order와 Delivery를 조회하는 객체, ...
상황별로 모든 객체를 생성할 경우 대다수의 상황에 대처하기 힘들어질 것이다.
JPA 동작 원리
그렇다면, JPA가 도대체 무엇을 해주길래 필요한 것일까?
JPA는 어플리케이션과 JDBC 사이에서 동작한다.

위에서 설명했던 SQL 문 작성의 비효율적인 일을 JPA가 자동으로 처리해 JDBC API에 전달한다.
즉, 객체를 관계형 데이터베이스에 표현하는 방법은 변하지 않았지만, 개발자가 더 이상 데이터베이스를 구성하는데 신경쓰지 않고 객체를 구성하는 일에만 집중할 수 있다는 뜻이다.
persist 함수를 통해 객체를 저장한다.
이때, JPA는 엔티티(객체)를 분석하고 INSERT SQL 또는 UPDATE SQL을 생성해 JDBC API에 전달한다.
불필요한 값(상속에 의한 Forien Key 등)을 클래스 안에 표현하지 않아도 JPA가 분석해 데이터베이스에 정보를 전달한다. 이로써 패러다임 불일치를 해결할 수 있다.
find 함수를 통해 객체를 조회한다.
자동으로 연관관계를 참조하고 SELECT SQL을 생성해 JDBC API에 전달한다.
setName 함수를 통해 객체를 수정한다.
새로운 연관관계를 넣을 수 있고, 값을 수정할 수 있다.
remove 함수를 통해 객체를 삭제한다.
JPA의 최적화 기능
- 1차 캐시와 동일성 보장
Transaction 기술을 통해 같은 트랜잭션 안에서 같은 엔티티를 반환하도록 한다. (조회 성능 향상)
- 쓰기 지연
동일하게 Transaction 기술을 통해 커밋 전까지 INSERT SQL을 모으고 JDBC BATCH SQL 기능을 이용해 한 번에 전송한다.
UPDATE, DELETE 로 인한 row lock 시간을 최소화한다.
캐시의 형태로 저장되었다가 커밋 시에 쿼리가 전송되기 때문에 커밋 전 비즈니스 로직을 실행할 때 DB row lock 이 걸려있지 않은 상태가 된다.
- 지연, 즉시 로딩
즉시 로딩이란 JOIN SQL로 한 번에 연관된 객체까지 미리 조회하는 것이다.
리연 로딩이란 객체가 실제 사용될 때 로딩한다.
Order order = orderDAO.find(orderId); // SELECT * FROM ORDER
Member member = order.getMember();
String name = member.getName(); // SELECT * FROM MEMBER
틀린 부분이 있다면 언제든지 지적 부탁드립니다. 😁



