JS

[JPA #1] JPA란? JPA를 왜 사용할까? JPA 장점은? 본문

JPA

[JPA #1] JPA란? JPA를 왜 사용할까? JPA 장점은?

seunghyunson 2022. 10. 27. 19:14

JPA란 Java Persistence API의 줄임말로 Java 표준 ORM 입니다.

ORM (Object-relational mapping) 이란, 객체는 객체대로 객체지향스럽게 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계해서 함께 사용할 수 있도록 중간에서 매핑해주는 도구입니다.

JPA는 Java 애플리케이션과 JDBC 사이에서 동작하며, 개발자가 직접 JDBC API를 사용하지 않아도 JPA가 데이터베이스로의 SQL문을 호출하고 결과를 객체로 매핑해줍니다.

JPA는 구현체가 아닌 인터페이스의 모음으로 JPA 2.1 표준 명세를 구현한 3가지 구현체가 (Hibernate, EclipseLink, DataNucleus) 존재하며 그중 대표적으로 Hibernate를 대부분 사용합니다.


JPA를 왜 사용해야 하는가?

최근에는 굉장히 많은 기업들이 JPA를 표준 기술로 채택해서 사용하고 있습니다. JPA를 사용하면 어떤 이점이 있길래 그럴까요?

1. 생산성

JPA를 이용하면 CRUD가 아래와 같이 간단해집니다. SQL문을 사용하는 방식과 가장 큰 차이점이라고 할 수 있습니다.

jpa.persist(user) // 저장
User user = jpa.find(userId) // 조회
user.setName("user") // 수정
jpa.remove(user) // 삭제

특히 수정 부분이 마치 Java 컬렉션을 사용하듯이 쓸 수 있어서 큰 도움이 됩니다.

자바 컬렉션에 있는 객체의 필드값을 수정한 뒤 다시 컬렉션에 집어넣어 줘야 할 필요가 없는 것처럼 말이죠.


2. 유지보수

SQL로 매핑하는 방식을 사용할 경우 엔티티에 필드 추가, 변경 시 모든 SQL 쿼리문을 변경해야 하는 굉장히 큰 불편함이 있습니다.

JPA를 이용하면 필드 변경사항이 있을 때 개발자는 엔티티에 필드를 추가하거나 삭제만 하면 SQL은 JPA가 처리해주기 때문에 유지보수에도 큰 장점이 있습니다.


3. 관계형 데이터베이스와 객체의 패러다임의 불일치 해결

상속

JPA는 상속관계에 있는 객체를 저장할 때 필요한 테이블에 대한 INSERT 문을 알아서 생성합니다.

상속관계에 있는 객체를 조회 시에도 알아서 JOIN 쿼리를 생성해줍니다.

SQL을 사용하면 다 직접 만들어야 하는 불편함이 있습니다.

연관관계, 객체 그래프 탐색

JPA를 사용하면 자바 컬렉션을 사용하듯이 연관관계에 있는 객체를 저장할 수 있고, 특정 객체를 통해 연관관계로 참조하고 있는 객체를 쉽게 가져올 수도 있습니다.

비교

JPA를 사용하면 같은 조건으로 불러온 객체에 대한 == 비교가 가능합니다.

단순히 == 비교가 좋다기보다는, 같은 트랜잭션에서 조회한 엔티티는 같은 엔티티임을 보장해준다는 점이 장점입니다.


4. 성능 최적화

JPA를 사용하면 애플리케이션 레벨에서도 다양한 방식으로 성능을 최적화할 수 있습니다.

1차 캐시와 동일성 보장

JPA는 같은 트랜잭션에서 조회한 엔티티를 다시 조회할 경우, 캐시(1차 캐시)를 통해 불러오기 때문에 몇 번을 호출하던 추가 SQL문 호출 없이도 같은 엔티티임을 보장해줍니다. (그래서 == 비교가 가능합니다.)

DB Isolation Level이 Read Committed이어도 애플리케이션에서 Repeatable Read를 보장해줍니다.

트랜잭션을 지원하는 쓰기 지연

1. INSERT

INSERT 문이 여러 개고 트랜잭션이 커밋되기 전에만 INSERT 문들이 실제 DB에 실행돼도 된다면, JPA가 JDBC BATCH SQL을 이용하여 INSERT 문을 모았다가 트랜잭션 커밋 시점에 한 번에 보내줍니다.

2. UPDATE

마찬가지로 트랜잭션 커밋 시점에 UPDATE, DELETE 문이 날아가기 때문에, UPDATE, DELETE 관련 비즈니스 로직을 수행하는 동안 ROW 락으로 인한 딜레이가 발생하지 않습니다.

3. 지연 로딩과 즉시 로딩

지연 로딩

지연 로딩이란 특정 객체를 조회할 때 연관관계로 매핑되어 있는 객체까지 한 번에 가져오지 않고, 연관관계로 매핑되어 있는 객체의 값을 필요로 할 때 조회 쿼리가 수행되는 로딩 방식을 말합니다.

즉, User 객체에 해당 User가 속해있는 Team과 연관관계라고 할 때, User 조회 시 연관관계로 있는 Team 데이터까지 가져오는게 아니라 User 데이터만 가져옵니다. (Team 테이블을 JOIN 하지 않음)

그리고 혹시 Team에 대한 정보가 필요하다면 그때 해당 Team에 대한 데이터만 가져오는 쿼리를 실행합니다.

User user = userDao.find(userId); // 유저 데이터만 가져옴
Team team = user.getTeam(); // 여기서도 아무일이 일어나지 않음
String teamName = team.getName(); // 해당 객체의 특정 값을 조회할 때 조회 쿼리가 날아감

즉시 로딩

즉시 로딩은 지연 로딩과 반대로 User 데이터 조회 시 연관관계로 있는 Team 데이터까지 함께 JOIN 해서 가져옵니다.

User 데이터 조회 시 항상 Team 데이터까지 필요한 경우, 굳이 지연 로딩을 이용해서 불필요하게 쿼리를 나눠 보낼 필요가 없으니 이럴 때 즉시 로딩을 이용할 수 있습니다.

JPA는 이런 기능을 제공하기 때문에 SQL문을 직접 분리하고 합칠 필요없이, 특정 옵션만 건드려 목적에 맞는 로딩 방식을 사용할 수 있습니다.


이렇게 JPA가 왜 많은 기업들의 표준 기술이 되어 사용되고 있는지, 어떤 장점들이 있는지 간단하게 정리해봤습니다.

그럼 이제부터 Deep Dive 해서 알아보겠습니다.

Comments