
JPA 영속성 컨텍스트는 JPA를 배우는 초반에 가장 자주 막히는 개념입니다. SQL을 직접 쓰는 방식과 다르게, JPA는 객체를 조회하고 수정하는 동안 중간 작업 공간을 둡니다.
핵심은 영속성 컨텍스트가 Entity의 상태를 기억하고, 필요한 시점에 DB와 맞춘다는 점입니다. 이 기준을 잡으면 1차 캐시, 변경 감지, flush가 한 흐름으로 이어집니다.
JPA 영속성 컨텍스트를 이해하는 4단계

영속성 컨텍스트는 Entity를 관리하는 공간이다
JPA에서 EntityManager를 통해 조회하거나 저장한 Entity는 영속성 컨텍스트 안에서 관리될 수 있습니다. Hibernate User Guide도 persistence context를 entity instance를 관리하는 맥락으로 설명합니다.
이 말은 단순히 객체를 메모리에 올린다는 뜻만은 아닙니다. JPA가 그 객체의 식별자, 초기 상태, 변경 여부를 추적할 수 있다는 뜻입니다.
1차 캐시는 같은 객체를 다시 쓰게 만든다
같은 영속성 컨텍스트 안에서 같은 ID의 Entity를 다시 조회하면, JPA는 이미 관리 중인 객체를 돌려줄 수 있습니다. 이를 흔히 1차 캐시라고 부릅니다.
Member a = entityManager.find(Member.class, 1L);
Member b = entityManager.find(Member.class, 1L);
System.out.println(a == b); // 같은 영속성 컨텍스트라면 true일 수 있다이 덕분에 같은 트랜잭션 안에서 동일한 Entity가 서로 다른 객체로 흩어지는 일을 줄일 수 있습니다. 하지만 이것은 영속성 컨텍스트 범위 안에서의 이야기입니다.
변경 감지는 setter 호출이 SQL이라는 뜻이 아니다
JPA에서 관리 중인 Entity의 값을 바꾸면, 트랜잭션이 끝나거나 flush가 일어날 때 변경 내용을 SQL로 반영할 수 있습니다. 이것을 변경 감지 또는 dirty checking이라고 부릅니다.
@Transactional
public void changeName(Long memberId, String name) {
Member member = entityManager.find(Member.class, memberId);
member.changeName(name);
// 명시적으로 update 쿼리를 호출하지 않아도 변경 감지 대상이 될 수 있다.
}중요한 점은 값을 바꾸는 순간 바로 UPDATE SQL이 나간다는 뜻은 아니라는 것입니다. JPA는 변경을 추적하고 있다가 flush 시점에 SQL을 만들 수 있습니다.
flush와 commit을 구분해야 한다
flush는 영속성 컨텍스트의 변경 내용을 DB에 반영하는 과정입니다. commit은 트랜잭션을 확정하는 과정입니다. 보통 commit 전에 flush가 일어나지만, 두 단어를 완전히 같은 뜻으로 쓰면 문제가 생깁니다.
flush가 일어나면 SQL이 DB로 전달될 수 있지만, 트랜잭션이 아직 commit되지 않았다면 최종 확정 전일 수 있습니다. 그래서 테스트나 디버깅에서 SQL 로그가 보인다고 해서 트랜잭션이 이미 끝났다고 생각하면 안 됩니다.
헷갈리는 이유는 객체와 DB 사이에 시간이 있기 때문이다
JPA는 객체 상태 변경과 SQL 실행을 분리합니다. 이 분리 덕분에 편리하지만, 동시에 헷갈립니다. 객체는 이미 바뀐 것처럼 보이는데 DB에는 아직 반영되지 않았을 수 있고, 같은 ID를 다시 조회했는데 DB를 다시 조회하지 않을 수도 있습니다.
- 같은 트랜잭션 안에서는 1차 캐시가 먼저 보일 수 있다.
- 변경 감지는 영속 상태 Entity에 의미가 있다.
- 준영속 상태나 detached 객체는 자동 변경 감지 대상이 아닐 수 있다.
- flush 시점과 commit 시점은 구분해서 봐야 한다.
- N+1 문제는 영속성 컨텍스트와 별개로 연관 조회 전략도 함께 봐야 한다.
N+1 문제와 연결해서 보면 더 쉽다
영속성 컨텍스트가 있다고 해서 모든 조회 문제가 사라지는 것은 아닙니다. 연관 관계를 어떻게 조회하느냐에 따라 N+1 문제가 생길 수 있습니다. 이 흐름은 JPA N+1 문제 글에서 SQL 흐름 중심으로 다뤘습니다.
정리
JPA 영속성 컨텍스트는 Entity를 관리하고 상태 변화를 추적하는 공간입니다. 1차 캐시는 같은 객체를 재사용하게 만들고, 변경 감지는 Entity의 값 변화를 flush 시점에 SQL로 반영할 수 있게 합니다. JPA가 어려운 이유는 객체 변경과 SQL 실행 사이에 시간이 있기 때문입니다.