영속성 컨텍스트

도람·2025년 7월 15일
post-thumbnail

영속성 컨텍스트

  • 엔티티 매니저는 엔티티를 영속성 컨텍스트에 저장한다.

    영속성 컨텍스트: JPA의 중요한 특징 중 하나로, 엔티티를 관리하는 가상의 공간.
    -> 이것을 통해 데이터베이스에서 효과적으로 데이터를 가져올 수 있고, 엔티티를 편하게 사용할 수 있다.

영속성 컨텍스트의 특징

  • 영속성 컨텍스트의 특징들인 1차캐시, 쓰기 지연, 변경 감지, 지연 로딩은 공통적으로
    데이터베이스에 접근을 최소화해 성능을 높인다.

1차 캐시

  • 영속성 컨텍스트는 내부에 1차 캐시를 갖고 있다, 엔티티를 조회하면 1차 캐시에서 데이터를 조회하고, 값이 있으면 반환한다.
  • 값이 없으면 데이터베이스에서 조회해 1차 캐시에 저장한 다음 반환한다.
    => 캐시된 데이터를 조회할 때에는 데이터베이스를 거치지 않아도돼서 매우 빠르게 데이터를 조회할 수 있다.

(캐시의 키는 엔티티의 @Id 애너테이션이 달린, 기본키 역할을 하는 식별자. 값은 엔티티)


쓰기 지연

  • 쓰기 지연은 트랜잭션을 커밋하기 전까지는 데이터베이스에 실제로 질의문을 보내지 않고, 쿼리를 모아놨다가 트랜잭션을 커밋하면 모았던 쿼리를 한 번에 실행하는 것.
ex) 
INSERT INTO ... VALUES (1)
INSERT INTO ... VALUES (2)
INSERT INTO ... VALUES (3)

이 쿼리는 데이터 추가 쿼리가 3개인데, 영속성 컨텍스트는 쿼리를 3번 실행하지 않고 트랜잭션을 커밋하는 시점에 3개의 쿼리를 한꺼번에 전송한다.
-> 적당한 묶음으로 쿼리를 요청할 수 있어 데이터베이스 시스템의 부하를 줄일 수 있다.


변경 감지

  • 트랜잭션을 커밋하면, 1차 캐시에 저장되어 있는 엔티티의 값과 현재 엔티티의 값을 비교한다.
  • 변경된 값이 있으면 변경 사항을 감지하여 변경된 값을 데이터베이스에 자동으로 반영
    -> 쓰기 지연과 마찬가지로 적당한 묶음으로 쿼리를 요청할 수 있고, 데이터베이스의 부하를 줄인다.

지연 로딩

  • 지연로딩은 쿼리로 요청한 데이터를 애플리케이션에 바로 로딩하는 것이 아니라, 필요할 때 날려 데이터를 조회하는 것이다.

지연로딩의 필요한 순간이란?

지연로딩을 공부하며 "필요한 순간"이란 언제고, 어떻게 판별하는지 궁금했는데 이는
프록시 객체를 통해 실제 데이터에 접근하는 순간을 의미한다.

쉽게말해, 해당 엔티티의 연관된 데이터를 사용할 때 이다.

@Entity
public class Member {
    @Id
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    private Team team;
}

위 코드에서 member.getTeam()을 호출하기 전에는 Team객체를 프록시로 가지고 있다.
member.getTeam().getName()처럼 실제로 team의 "속성"에 접근하는 순간에 영속성 컨텍스트가 해당 team을 로딩할 필요성을 느끼고 쿼리를 보낸다.

참고: How does a JPA Proxy work and how to unproxy it with Hibernate
참고: How proxy loads the lazy property in Hibernate/JPA
참고: Eager/Lazy Loading in Hibernate : 스프링 공식문서

이와 반대로 즉시 로딩이라는 개념도 있다. 이는 쿼리를 보내 연과된 엔티티도 함께 조회하는 방식이다.

또한 스프링 공식문서에서는 "Hibernate에서는 프록시를 비활성화하거나 지연 로딩을 끄고 모든 데이터를 한 번에 불러오는 것을 좋지 않은 관행으로 간주됩니다. 필요 여부와 관계없이 많은 양의 데이터를 가져오고 저장하게 될 수 있습니다." 라는 말도 있다.


해당 글은 다음 도서의 내용을 정리하고 참고한 글임을 밝힙니다.
신선영, ⌜스프링 부트 3 벡엔드 개발자 되기 - 자바 편⌟, 골든래빗(주), 2023, 384쪽

profile
정도를 걷는 엔지니어

0개의 댓글