[JPA] JPA 엔티티와 영속성 컨텍스트 - JPA 주요 기능 살펴보기

·2024년 2월 15일
0

JPA

목록 보기
1/2
post-thumbnail

JPA

Java Persistence API 의 약자로, Spring 진영에서 대표적으로 사용되는 ORM 스펙이다. 객체와 관계형 DB 간의 상호작용을 표준화 하는 역할을 한다.

ORM : Object-Relational Mapping 의 약자로, back-end 환경에서 영속성을 보장하기 위해, 객체와 관계형 DB 의 불일치를 해결하여, 둘의 상호작용을 지원하는 기술을 의미한다. 참고로 객체와의 불일치를 해결하고 상호작용을 도와주는 기술은 ORM 만 있는 것이 아니다. MongoDB 와 같이 문서 DB 와 상호작용을 지원하는 경우는 ODM 이라 하며, 객체와 XML 과의 상호작용을 도와주는 기술은 OXM 이라고 한다.

ORM의 자세한 정의는 이전에 작성한 내용이 있으니 이를 참고하자.
[Spring] Persistence - 서버에서 데이터를 DB에 옮기기까지

JPA와 JPA 구현체

JPA의 경우는, 객체와 관계형 DB 간의 상호작용하기 위한 기술들을 명세한 인터페이스이며, JPA 구현체JPA 의 명세를 바탕으로 실질적인 구현이 이루어진 코드를 의미한다. 즉 JPA 는 하나의 기술 표준 혹은 스펙 이라 분류할 수 있고, JPA 구현체는 하나의 프레임워크, 라이브러리 로 분류할 수 있다.

대표적인 JPA 구현체 로는 HibernateEclipseLink 등이 있다.

JPA Entity

JPA Entity 는 객체와 관계형 DB 의 상호작용을 위한 대표적인 수단으로, 실제로 DB 테이블에 대응하는 클래스를 일컫는다. 영속성 컨텍스트에 의해 관리가 이루어지며, 필요에 따라 데이터베이스 테이블에 맞게 변환하여 DB 에 저장되거나, 반대로 DB 쿼리 결과를 JPA Entity 인스턴스의 형태로 불러오기도 한다.

Entity Manager

JPA Entity 의 영속성을 제어하며, 데이터베이스와의 통신을 담당하는 JPA 의 핵심 기능이다.

JPA EntityEntity Manager 를 통해 영속성 컨텍스트에서 등록 및 관리가 이루어지며 되며, 트랜잭션 종료 시 JPA Entity 의 변경사항을 그대로 DB 에 반영하게 된다.

영속성 컨텍스트

JPA Entity 의 생명주기를 관리하는 기술로서, Entity 의 변경사항을 추적하여 이에 따른 결과를 관계형 DB 에 반영시키는 상호작용 역할을 한다.

더티 체킹 Dirty checking

영속성 컨텍스트는 Entity 등록 시 초기 스냅샷을 생성하여, 비교를 통해 향후 Entity 의 변경사항 및 상태를 추적하는 것이 가능하다. 최종적인 Entity 상태에 따라 관계형 DB 와의 상호작용이 달라지는 것이다.

예를들어 DB 데이터와 연관되지 않은 새로운 Entity 가 들어온 것이라면 데이티 생성을, DB 에 이미 존재하는 데이터를 가져온 것이라면 데이터 수정을,이미 존재하는 데이터를 영속성 컨텍스트에서 삭제하는 것이라면 데이터 삭제를 반영시키는 것이다.

캐싱 (1차 캐싱)

영속성 컨텍스트는 Entity 등록 시 이를 캐싱하여, 동일한 Entity 를 찾는 경우, DB 와 통신 없이 영속성 컨텍스트에 캐싱된 Entity 를 제공하는 기능을 가지고 있다. 단, 영속성 컨텍스트는 매 트랜잭션마다 새롭게 생성되기 때문에, 1차 캐싱을 통한 성능 향상은 그리 크지 않은 편이다.

트랜잭션 마다 영속성 컨텍스트가 새롭게 생성되는 것은 다수의 트랜잭션 발생 시 데이터베이스의 일관성을 보장하기 위해서이다. 다수의 트랜잭션이 하나의 영속성 컨텍스트에서 관리가 이루어진다면 트랜잭션 끼리 서로 영향을 미쳐 데이터베이스가 변질될 수 있는 위험이 있다.

프록시 객체를 통한 지연 로딩

영속성 컨텍스트는 JPA Entity 의 연관관계 설정에 따라, 즉시로딩 혹은 지연로딩을 실행할 수 있다. 지연로딩은 실질적으로 연관관계의 Entity 가 호출되는 경우에만 조회가 이루어지기 때문에 불필요한 통신을 줄여 서버 성능을 높일 수 있다.

엔티티 생명주기

  • 비영속 (new/transient) : 영속성 컨텍스트와 전혀 관계가 없는 상태를 의미한다. 단순히 JPA Entity 인스턴스를 생성만 한 상태이다.

  • 영속(managed) : 영속성 컨텍스트에 JPA Entity 가 등록되어 관리되는 상태를 의미한다. EntityManger.persist() 를 통해 JPA Entity 를 엔티티 매니저 내부의 영속성 컨텍스트에 등록할 수 있다. 트랜잭션 커밋 시 데이터베이스에 동기화가 이루어질 수 있으며, 반대로 데이터베이스 쿼리 결과를 JPA Entity 인스턴스로 생성하는 것이 가능한 상태이다.

  • 준영속 (detached) : 영속성 컨텍스트에 있던 JPA Entity 를 분리한 상태를 의미한다. 이는 더이상 영속성 컨텍스트에서 해당 Entity 를 관리하지 않음을 의미한다.

  • 삭제 (removed) : 영속성 컨텍스트에서 해당 JPA Entity 를 삭제한 상태를 의미한다. 삭제한 Entity 는 비영속 상태가 된다.

    준영속과 삭제는 모두 영속성 컨텍스트 내부의 Entity 를 지우는 역할을 하지만, 각 메서드 호출 시 데이터베이스의 반영 결과가 다르다. 준영속은 해당 Entity 에 대해 데이터베이스에 반영되는 것이 없으며, 삭제는 해당 Entity 와 연관된 데이터를 삭제시킨다.

commit() 과 flush()

JPACRUD 메서드는 메소드 호출 시 바로 쿼리를 실행하지 않는다. 영속성 컨텍스트를 통해 쓰기 지연 SQL 저장소에서 대기하게 되며, 실제 트랜잭션의 변경사항을 반영할 때, 쓰기 지연 SQL 저장소 에 쌓인 작업이 한번에 이루어진다.

바로 쿼리를 실행하지 않는 이유는, 배치작업을 통해 다수의 쿼리를 한번에 보내는 것이 통신에 효율적이기 때문이다. 더불어, 트랜잭션의 원자성 처리가 간편해진다. 트랜잭션이 실패하거나, 롤백이 이루어지는 경우 현재 DB 에 반영이 되지 않은 상태이기 때문에 DB 와 통신 없이 자체적으로 쉽게 취소가 가능하다.

commit()flush() 모두 트랜잭션의 변경사항을 반영시키는 메서드이지만 분명한 차이도 존재한다. commit() 은 현재 트랜잭션의 변경사항을 반영시키고 트랜잭션을 종료시키며, flush()는 현재 까지의 변경사항을 반영하되 트랜잭션을 종료시키지는 않는다. flush() 의 경우는 전송된 결과를 rollback() 을 통해 반영결과를 취소하는 것도 가능하다.

실제 commit() 호출은 내부에서 flush() 호출을 통해 DB 에 변경 결과를 반영시킨 후, 트랜잭션을 종료한다. 즉 flush() 는 변경사항을 반영하는 기능을 담당하며, commit() 은 트랜잭션을 종료하는 기능을 담당한다고 볼 수 있다. 참고로 JPQL 을 사용하는 쿼리 실행도 내부적으로 flush() 를 호출된다.

참고
Spring OXM를 이용한 JAXB HttpClient 연동 Example(샘플)
Spring Boot 에서 Redis 사용하기
[JPA] Entity(엔티티)와 EntityManger(엔티티 매니저)
[JPA] 엔티티(entity) 개념
[DB] ORM이란 - Heee's Development Blog
쓰기 지연 저장소
[JPA] commit, flush, Entity Manager의 clear()와 close()에서 궁금한 부분들 탐구 + 데이터 삭제 및 수정 시 1차 캐시에서 발생하는 현상 + 준영속과 비영속의 차이점

profile
새로운 것에 관심이 많고, 프로젝트 설계 및 최적화를 좋아합니다.

0개의 댓글