WEEK 6-12: Spring 영속성 컨텍스트

ensalada.de.pollo·2025년 5월 18일

be

목록 보기
34/44

영속성 컨텍스트(Persistence Context)

JPA에서 엔티티 객체를 영구적으로 저장하고 관리하는 논리적인 메모리 공간입니다. 쉽게 말하자면, application과 데이터베이스 사이에서 객체를 보관하는 가상의 데이터베이스의 역할을 합니다.

역할

엔티티를 저장, 조회, 삭제 하는 등의 모든 작업은 먼저 영속성 컨텍스트를 거칩니다. Entity Manager를 통해 접근하며, 같은 Transaction 내에서는 동일한 객체를 반환합니다.

Entity 상태

상태설명예시
비영속(new)영속성 컨텍스트와 전혀 관련이 없는, 새로 생성된 객체new Member()
영속(managed)영속성 컨텍스트에 저장되어 관리 중인 상태em.persist(member)
준영속(detached)한 번 영속되었다가 영속성 컨텍스트에서 분리된 상태em.detach(member)
삭제(removed)영속성 컨텍스트와 DB에서 삭제될 예정인 상태em.remove(member)

1차 캐시

엔티티를 영속성 컨텍스트에 저장할 때 생성되는 메모리 내의 캐시입니다. 엔티티는 먼저 1차 캐시에 저장이 되고, 같은 엔티티를 다시 요청하면 DB를 조회하지 않고 1차 캐시에서 반환합니다.

동작

em.persist(entity) 호출 시 1차 캐시에 저장
em.find()로 엔티티 조회 시 1차 캐시에서 먼저 찾고, 없으면 DB 조회 후 1차 캐시에 저장
transaction이 종료되면 1차 캐시도 함께 삭제

Tutor tutor = new Tutor(1L, "wonuk", 100); // 비영속
em.persist(tutor); // 영속, 1차 캐시에 저장
Tutor findTutor = em.find(Tutor.class, 1L); // 1차 캐시에서 조회

같은 트랜잭션 내에서 동일 엔티티를 조회할 시 SQL이 한 번만 실행된다는 효과를 가집니다. 이로 인해 성능이 최적화될 수 있고, 불필요한 DB에 접근을 방지할 수 있습니다.

동일성 보장

동일 트랜잭션 내에서 같은 엔티티를 여러 번 조회해도 항상 같은 객체 인스턴스를 반환합니다.

동작

1차 캐시 덕분에 중복 조회 시 항상 같은 객체 참조를 반환합니다. Java Collection에서 객체를 꺼내는 것처럼 일관성 있게 동작합니다.

Tutor findTutor1 = em.find(Tutor.class, 1L);
Tutor findTutor2 = em.find(Tutor.class, 1L);
System.out.println(findTutor1 == findTutor2); // true

Transaction 격리 수준 중 Repeatable Read를 Application 레벨에서 제공합니다.

쓰기 지연(Transactional Write-Behind)

엔티티 객체의 변경 사항을 DB에 바로 반영하지 않고, transaction의 commit 시점에 한 번에 반영하는 방식입니다.

동작

em.persist(entity) 호출 시 즉시 INSERT SQL을 실행하지 않고, 쓰기 지연 저장소에 쿼리를 모아둡니다. 그리고 transaction.commit() 시점에 모아둔 쿼리들을 한 번에 DB에 반영합니다.

em.persist(tutor1);
em.persist(tutor2);
transaction.commit(); // 이때 INSERT SQL이 실행됨

네트워크 및 DB의 부하가 감소되며, 성능이 최적화됩니다. 또한 JDBC batch 옵션을 활용하면, 여러 쿼리를 묶어 전송이 가능합니다.

변경 감지(Dirty Checking)

영속성 컨텍스트가 엔티티의 초기 상태(Sanpshot)를 저장하고, transaction commit 시점에 현재 상태와 비교해 변경 사항이 있으면 UPDATE SQL을 자동으로 생성하는 기능입니다.

동작

엔티티를 조회하고 필드를 변경하면, commit 시점에 JPA가 변경 여부를 감지합니다. 그리고 변경된 부분만 UPDATE 쿼리로 반영합니다.

Tutor tutor = em.find(Tutor.class, 1L);
tutor.setName("수정된 이름");
transaction.commit(); // UPDATE SQL 자동 실행

객체를 수정한 뒤 별도의 저장(persist) 호출 없이 DB에 반영합니다.

Flush

영속성 컨텍스트의 변경 내용을 데이터베이스에 반영하는 기능입니다.

동작

  • 자동 호출: transaction commit 시 자동으로 실행
  • 수동 호출: em.flush()로 원하는 시점에 직접 호출이 가능
em.persist(tutor);
em.flush(); // 이 시점에 SQL 실행
transaction.commit();

transaction 내에서 특정 시점에 DB 동기화가 필요할 때 활용할 수 있습니다.

자료 및 코드 출처: 스파르타 코딩클럽

0개의 댓글