Persistence

ChoiDevv·2022년 12월 13일
0

영속성

영속성이란 의미는 프로그램이 종료되더라도 사라지지 않는 속성을 의미한다. 물론 데이터베이스가 사라지거나 해당 테이블이 사라지는 극단적인 케이스를 제외하고 말이다. 사전적인 의미보다는 코드로써 어떤 부분이 영속성이 주어지는지 확인해보겠다.

Code Review

public void update(String newPassword) {
    this.password = newPassword;
}

비밀번호를 바꾸는 엔티티의 메소드이다. 해당 메소드는 서비스 코드에서 다음과 같이 쓰여진다.

user.update(new BCryptPasswordEncoder().encode(newPassword));

하지만 해당 메소드에서는 JPA의 save 메소드를 실행시키지 않는다. 그렇다면 저장이 되지 않을까? 그렇지 않다. 스프링의 영속성 컨텍스트로 인해 save 메소드를 실행시키지 않아도 저장이 된다. 그 말은 즉슨, 영속성 컨텍스트라는 것이 애플리케이션과 데이터베이스 사이에 가상의 DB 역할을 수행해내는 것이다.

Persistence Context

영속성 컨텍스트를 이해하기 위해서는 JPA가 요청이 들어오면 어떻게 처리하는지를 알아야 한다.

요청이 들어오면 스레드가 발생하고 EntityMangerFactory에서 EntityManger를 생성한다. EntityManager는 커넥션 풀을 사용해 DB에 접근하게 된다. 이런 과정에서 EntityManager는 엔티티를 DB에 저장하는 것이다.

정확히는 저장한다는 표현보다는 영속화한다는 표현이 맞을 것이다. 정리하자면 스레드가 생기면 그에 대해 EntityManagerFactory에서 EntityManager가 호출되고 이 EntityManager에 접근한 엔티티를 영속화시킨다. 이후 DB에 저장하는 것은 이 이후이다. 이런 환경을 영속성 컨텍스트라고 한다.

다시 코드로 돌아와보자.

User user = new User();
user.setId(1L);
user.setUsername("Choi");

User 엔티티가 있다고 가정한다. lombok의 setter를 사용했기에 코드에 대해서는 크게 좋지 않지만 단순한 이해를 위함이기에 넘어가도록 하겠다. 이런 식으로 객체를 생성만 한 상태는 비영속 상태이다.

여기서 EntityManager 클래스를 선언하고 persist하게 되면 영속성 컨텍스트에 담겨져 있는 상태가 된다. 참고로 아까도 이야기했지만 영속성 컨텍스트에 담긴 상황은 DB 쿼리가 발생하지 않은 상태이므로 저장된 상태가 아니다.

트랜잭션의 커밋이 발생하면 그 때 커넥션 풀로 인해서 DB에 접근해 세이브가 일어나게 되는 것이다.

왜 영속성 컨텍스트가 존재해야 할까?

영속성 컨텍스트는 1차적으로 캐시가 존재한다. 엔티티가 영속성 컨텍스트에 저장이 되면 필드 값들이 저장이 된다. 1차 캐시로 인해서 조회할 때 이점이 생긴다. 조회를 할 때 1차 캐시에 엔티티에 해당하는 값이 있으면 DB까지 가지 않고 1차 캐시에서 리턴해주기 때문이다.

트랜잭션에서 persist가 일어나고 1차 캐시를 저장한다음 쓰기 지연 SQL 저장소에 INSERT 쿼리들을 생성해서 쌓아둔다. 이후 커밋이 발생하면 flush가 발생하는데 flush의 의미는 이런 쿼리들을 DB에 보내는 동작을 말한다.

여기에서 이제 맨 처음에 얘기했던 update 메소드에 대한 이야기를 하겠다. 영속성 컨텍스트에 persist가 일어나면서 기존 유저에 대한 데이터가 1차 캐시에 있고 그와 동시에 스냅샷 필드도 저장하게 된다. 이로 인해서 변경 감지가 일어나고 엔티티와 스냅샷을 비교해서 Update 쿼리를 알아서 생성해주는 것이다. 이 변경 감지를 더티 체킹이라고 한다.

Summary

  1. 클라이언트로부터 요구사항이 발생하면(스레드가 발생하면) EntityManagerFactory에서 EntityManager를 할당해준다.
  2. EntityManager에 persist(영속화)가 발생하면 1차적으로 캐시에 Id를 비롯한 데이터 필드를 저장한다. 그와 동시에 스냅샷 필드도 저장한다.
  3. EntityManager에서 영속성 컨텍스트를 확인하게 되는데 기존에 존재하는 데이터라면 엔티티와 스냅샷 필드를 비교해 Update 쿼리를 자동적으로 생성해준다.
  4. 존재하지 않고 새로운 데이터라면 persist에 담아 영속화를 진행하고 쓰기 지연 SQL 저장소에 INSERT를 담고 커밋이 발생할 때 커넥션 풀을 통해 DB에 접근해 저장한다.

Reference Blog

https://ict-nroo.tistory.com/130

profile
기억보단 기록을

0개의 댓글