목차
[TIL] Day 67 — JPA 영속성 컨텍스트 심화 (1/22)
날짜: 2026-01-22
기술 스택: Spring Boot JPA Hibernate 영속성 컨텍스트
한 줄 요약: JPA 영속성 컨텍스트의 핵심 개념 — 1차 캐시, 변경 감지(Dirty Checking), 지연 로딩 동작 원리 정리
JPA 영속성 컨텍스트 (Persistence Context)
엔티티를 저장하는 논리적 공간. EntityManager가 관리하는 1차 캐시 역할
엔티티 생명주기
비영속 (new)
↓ em.persist()
영속 (managed) ← 1차 캐시에 저장, 변경 감지 대상
↓ em.detach() / em.clear() / em.close()
준영속 (detached) ← 컨텍스트에서 분리, 변경 감지 안 됨
영속 (managed)
↓ em.remove()
삭제 (removed) ← DB 삭제 예약
1차 캐시 — 같은 트랜잭션 내 DB 조회 최소화
// 첫 번째 find() → DB 쿼리 발생
Member member1 = em.find(Member.class, 1L);
// 두 번째 find() → 1차 캐시에서 반환, DB 쿼리 없음
Member member2 = em.find(Member.class, 1L);
System.out.println(member1 == member2); // true (동일 인스턴스)
변경 감지 (Dirty Checking)
em.update() 같은 메서드 없이 필드만 바꿔도 트랜잭션 커밋 시 자동으로 UPDATE 쿼리 발생
@Transactional
public void changePrice(Long itemId, int newPrice) {
Item item = itemRepository.findById(itemId).orElseThrow();
item.setPrice(newPrice); // 별도 save() 호출 없이 자동 반영
}
원리: 영속성 컨텍스트는 엔티티를 처음 조회할 때 스냅샷을 저장
→ 커밋 시점에 현재 상태와 스냅샷 비교 → 다르면 UPDATE 쿼리 생성
지연 로딩 (Lazy Loading) 주의사항
@OneToMany(mappedBy = "order", fetch = FetchType.LAZY)
private List<OrderItem> orderItems; // 실제 접근 시 쿼리 발생
트랜잭션 밖에서 지연 로딩된 컬렉션에 접근하면 LazyInitializationException 발생
→ 해결책: @Transactional 범위 안에서 처리하거나 fetch join 사용
더 알아볼 것
-
@Transactional(readOnly = true)— 읽기 전용 트랜잭션에서 Dirty Checking 비활성화 효과 - OSIV (Open Session In View) 패턴과 그 문제점
- N+1 문제 해결 —
fetch joinvs@EntityGraph -
em.flush()와em.clear()를 명시적으로 사용하는 케이스
'⏳ Time Log > 1. One Day (Daily · TIL)' 카테고리의 다른 글
| [TIL] Day 71 — Spring Boot 핵심 개념 복습 (1/28) (0) | 2026.06.08 |
|---|---|
| [TIL] Day 69 — Querydsl 동적 쿼리 + 쇼핑몰 상품 관리 (1/26) (0) | 2026.06.08 |
| [TIL] Day 66 — JPA 엔티티 연관관계 매핑 + Dockerfile 커스텀 이미지 빌드 (1/21) (0) | 2026.06.08 |
| [TIL] Day 65 — Spring Boot Validation + Docker 이미지 커밋/푸시 (1/20) (0) | 2026.06.08 |