JPA가 엔티티를 관리하는 힙 위의 작업 공간. 트랜잭션이 시작될 때 만들어지고 끝나면 사라진다.
무엇으로 이루어져 있나
영속성 컨텍스트 (트랜잭션 범위, 힙)
├── 1차 캐시 Map<타입#식별자, 엔티티 인스턴스>
├── 스냅샷 엔티티마다 조회 시점 값의 사본 Object[]
├── 쓰기 지연 저장소 아직 안 보낸 INSERT/UPDATE/DELETE 목록
└── 상태 정보 각 엔티티가 MANAGED / REMOVED 인지
애플리케이션과 DB 사이에 한 겹의 메모리 층을 두는 것이 핵심 아이디어다. 이 층이 있어서 아래 네 기능이 가능해진다.
4대 기능이 왜 성립하는가
| 기능 | 어느 구조에서 나오나 |
|---|---|
| 1차 캐시 | Map에서 바로 꺼내므로 SQL 생략 |
| 동일성 보장 | 같은 키면 같은 인스턴스 참조를 돌려줌 → == 성립 |
| 쓰기 지연 | SQL을 큐에 모았다가 flush에 한 번에 전송 |
| 변경 감지 | 스냅샷과 현재 값을 대조 |
엔티티 생명주기 — 메모리 관점
다이어그램 로딩 중…
managed 상태에서만 변경 감지와 지연 로딩이 동작한다. 이유는 단순하다 — 그 둘 다 영속성 컨텍스트가 있어야 하는 기능인데, detached는 컨텍스트 밖이기 때문이다.
트랜잭션이 끝나면
컨텍스트가 통째로 버려진다. 1차 캐시·스냅샷·큐가 모두 사라지고, 남은 엔티티 객체는
detached가 된다. 이때 초기화되지 않은 연관을 건드리면 LazyInitializationException이 난다.
실무 함정
- 한 트랜잭션에서 너무 많이 조회하지 마라. 엔티티 + 스냅샷이 전부 힙에 남는다.
10만 건 배치라면 주기적으로
flush()+clear()로 비워야 OOM을 피한다. - 긴 트랜잭션은 그 자체로 위험하다. 컨텍스트가 커지고 DB 커넥션도 오래 잡는다.