본문 바로가기
Spring

Spring JPA / JPA

by yang sing 2023. 6. 20.

안녕하세요.

예전에 JDBC, JdbcTemplate, Mybatis까지의 포스팅을 했었는데요.

이번에는 최근(?)이라기 보다는 몇년 전부터 떠오르고 있는 JPA에 대해서 작성을 하려고 합니다.

아직 대부분의 회사에서 Mybatis를 사용하는거로 알고있는데 JPA는 우아한 형제들, 쿠팡 등 규모가 있는 회사에서 JPA를 사용을 하고 있고 또 많은 기업들이 JPA로 개발을 하려는 시도를 하고 있다고 생각을 하고 있습니다.

 

저도 회사에서 JPA를 사용을 하다가 Mysql의 Stored procedure로 전환을 하면서 최근에는 회사 프로젝트에서 JPA를 사용할 일이 많이 없어졌지만 그래도 꾸준히 JPA를 공부를 하면서 다시 프로젝트에 적용 시킬 준비를 하고 있습니다.

JPA

JPA는 Java Persistence API의 약자로 자바 진영의 ORM 기술 표준으로 사용되는 인터페이스의 집합이다.
Hibernate, Spring JPA 등의 구현체가 있다.

JPA의 장점

- SQL 중심적인 개발에서 객체 중심적인 개발이 가능하다.

- 반복적인 CRUD SQL 쿼리를 자동으로 작성해줘서 단순 코드를 줄일 수 있다.

- 복잡한 쿼리의 경우 직접 쿼리를 작성할 수 있다.

- 생산성과 유지보수가 더 수월해진다.

JPA의 단점

- 프로젝트 규모가 크거나 테이블 연관 관계가 복잡할 경우 오히려 더 복잡해질 수 있다.

- 위와 같이 테이블 연관 관계가 복잡할 때 성능이 안좋게 나올 수 있다.

- 장점이자 단점으로 복잡한 쿼리의 경우 직접 쿼리를 작성을 해야한다. 

ORM 

Object Relational Mapping의 약자로 객체 관계 매핑이라는 뜻으로 객체와 RDBS의 데이터를 매핑 해주는 프레임워크이다.
ORM을 통해 java의 객체와 RDB의 테이블 사이의 패러다임 불일치를 해결 할 수 있다.

EntityManager

영속성 컨텍스트(PersistenceContext)의 논리적인 개념
엔티티 매니저 내부에서 영속성 컨텍스트를 이용해 엔티티를 관리한다.
Thread-safe 하지 않아서 사용할 때마다 객체를 새로 생성해야한다.

PersistenceContext

엔티티를 영구 저장하는 환경
DB와 어플리케이션 사이에 있는 가상의 공간으로 모든 Entity의 생명 주기를 관리

 

EntityManager 동작 방식

자바 ORM 표준 JPA 프로그래밍 - 기본편 / 김영한 강의 참고

1. 요청이 들어오면 EntityManagerFacory에서 EntityManager를 생성

2. 생성 된 EntityManager이 connection pool에서 connection을 얻어 온다.

3. EntityManager의 getTransaction()을 호출해 EntityTransaction 객체 생성 및 트랜잭션 시작

4. Entity 작업 후 트랜잭션 제거

5. DB에 추가 및 변경 된 Entity 데이터를 반영

6. EntityManager 제거

 

Entity의 생명 주기

1. 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

2. 영속 (managed) : 영속성 컨텍스트에 관리되는 상태

3. 준영속 (detached) : 영속성 컨텍스트에 저장되었다가 분리된 상태

4. 삭제 (removed) : 삭제된 상태

// 비영속 상태의 객체 생성
User user = new User();
user.setSeq(1l);
user.setId('userId');

// 엔티티 매니저 객체 생성
EntityManager em = emf.createEntityManager();
// 트랜잭션 시작
em.getTransaction().begin();

// 객체를 영속화
em.persist(user);

// 객체 준영속 상태
em.detach(user);

// 객체 삭제
em.remove(user);

 

PersistenceContext의 이점

 

1. 1차 캐시

 - JPA에서의 1차 캐싱은 영속성 컨텍스트 안에서만 이뤄지는 캐시로 하나의 EntityManager에서 일기, 쓰기 등 작업을 할 때 같은 데이터를 조회하는데에 있어서 DB가 아니라 1차 캐시를 먼저 조회를 해서 데이터를 가져온다.

 - 1차 캐시는 EntityManager 안에서 동작을 하기 때문에 모든 작업이 종료 후 EntityManager가 제거될 때 1차 캐시도 같이 제거가 된다.

 

2. 동일성 보장

 - 1차 캐시로 반복 가능한 읽기(REPEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다.

 

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

 - 하나의 트랜잭션 단위 안에서  insert 구문을 파악하고 쓰기 지연 SQL 저장소에 저장을 시켜 둔 뒤 모든 작업이 종료 된 뒤 commit 을 할 때 모아두었던 쿼리를 한번에 실행 시킬 수 있다. 

 

4. 변경 감지 (Dirty Checking)

 - 1차 캐시 안에 들어있는 스냅샷을 이용해 처음 데이터와 마지막 데이터의 데이터 변경을 감지 후 모든 작업이 종료가 되면 변경된 데이터를 자동으로 DB에 update 쿼리를 실행한다.

 

 

 

많은 개발자분들이 JPA의 단점으로  성능이 안좋을거라고 생각을 하고 계신다.

우리 회사에서도 JPA에서 procedure로 전환을 한 이유가 개발 리더분께서 JPA의 성능을 문제 삼으셨다. 

물론 JPA가 성능면에서 안좋을 수도 있을거라고 생각 하실 수 있지만 요즘에는 다이나믹하게 성능 차이가 심하게 차이가 나지는 않을거라고 생각을해서 procedure 전환을 반대했지만 결국 전환을 하게 되었다.

JPA가 제공하는 여러 옵션들을 잘 활용을 한다면 오히려 성능이 좋아질 수 있다고 생각합니다.

 

다음 포스팅에서는 Spring Data에서 제공해주는 Spring Data JPA에 대해서 작성을 하겠습니다.

감사합니다.

 

참고

인프런 - 자바 ORM 표준 JPA 프로그래밍 - 기본편 / 김영한 강의

 

'Spring' 카테고리의 다른 글

Spring JPA / Entity 연관관계  (0) 2023.06.27
Spring JPA / Entity 매핑  (0) 2023.06.21
Spring AOP  (0) 2023.06.13
Object Storage 이미지 출력  (0) 2023.06.09
@Asnyc를 이용한 멀티 스레드  (0) 2023.06.08