JPA에서 Entity Manager가 관리하는 엔티티 객체들이 존재하는 메모리상의 작업 공간을 말한다.
→ 다르게 말하면, 데이터베이스와 애플리케이션 사이의 객체 상태를 효율적으로 관리하는 1차 캐시이자 변경 감지 매커니즘.
→ 또 다르게 말하면, DB와의 직접 통신 없이도 엔티티의 상태를 관리할 수 있게 해주는 캐시이자 트래킹 영역.

User u1 = em.find(User.class, 1L); // → DB 조회
User u2 = em.find(User.class, 1L); // → 1차 캐시에서 반환 (쿼리 없음)
System.out.println(u1 == u2); // true
== 비교 가능)update를 실행한다.@Transactional
public void updateUserName(Long id) {
User user = em.find(User.class, id); // 1차 캐시에 로딩됨
user.setName("NewName"); // setter로 변경
// → 별도 update 호출 없이 트랜잭션 커밋 시 자동 update 쿼리 실행
}
persist() 등으로 엔티티를 저장해도 즉시 DB에 insert 쿼리 보내지 않고, 트랜잭션 커밋 직전에 쿼리 모아서 한 번에 처리 (Flush) 한다.em.flush();)@Transactional 안에서 EntityManager가 생성되고, 해당 트랜잭션이 끝나면 clear() 되며 엔티티들은 더 이상 영속 상태가 아니게 된다.트랜잭션 내에서 객체처럼 다뤘는데, 자동으로 DB에 반영된다 → 생산성↑
성능 최적화 → 1치 캐시, 지연 쓰기, 지연 로딩
상태 추적 기능 → Dirty Checking
DB 중심이 아닌 객체 중심으로 개발 가능 → JPA 핵심 철학
하나의 쿼리를 실행해 하나의 데이터를 가져올 때, 연관된 엔티티를 가져오기 위해 추가로 N개의 쿼리를 실행하는 문제를 말한다.
예를 들어, 여러 Order를 조회한 뒤에 각 Order에 연결된 Member의 이름을 출력하고 싶을 때 :
Member 엔티티 구조@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
}
Order 엔티티 구조@Entity
public class Order {
@Id
@GeneratedValue
private Long id;
private String product;
@ManyToOne(fetch = FetchType.LAZY)
private Member member;
}
public void showOrders() {
List<Order> orders = orderRepository.findAll(); // 📌 쿼리 1번
for (Order order : orders) {
System.out.println("상품: " + order.getProduct());
System.out.println("주문자: " + order.getMember().getName()); // 📌 쿼리 N번 추가 발생!
}
}
orderRepository.findAll()
→ SELECT * FROM orders로 쿼리 1번 실행
getMember() 호출 시마다
→ SELECT * FROM member WHERE id = ?로 쿼리 N번 실행
@Query("SELECT o FROM Order o JOIN FETCH o.member")
List<Order> findAllWithMember();
→ Order와 Member를 하나의 SQL로 조인해서 가져온다
@EntityGraph(attributePaths = "member")
@Query("SELECT o FROM Order o")
List<Order> findAllWithMember();
→ 특정 쿼리 실행 시점에만 임시로 즉시 로딩을 적용하는 도구
→ fetch join의 대안(JPQL 복잡하게 작성하지 않아도 되는)으로 생각하기
IN 쿼리로 줄여 성능을 개선하는 방법spring.jpa.properties.hibernate.default_batch_fetch_size=100
→ SELECT * FROM member WHERE id IN (?, ?, ?, ...)와 같은 방식으로 N -> 1 쿼리로 줄여준다.
영속성 컨텍스트는 JPA에서 엔티티를 관리하는 1차 캐시로, 엔티티의 동일성 유지, 변경 감지, 성능 최적화 등을 가능하게 해주는 핵심 매커니즘이다.
➡️ JPA가 객체 중심 개발을 가능하게 하는 핵심 기반이라고 생각한다.
또한, 성능 최적화 과정에서 JPA의 연관관계는 기본적으로 Lazy Loading으로 설정되는 경우가 많아 연관된 엔티티는 필요한 시점에 쿼리를 날리게 되는데,
➡️ 이게 루프 안에서 발생할 경우 N개의 추가 쿼리가 실행되는 N+1 문제가 생길 수 있다.
이에 대한 해결책으로
1. Fetch Join
2. Entity Graph
3, Batch Size 설정
등의 방법으로 쿼리 수를 줄이고 성능을 개선할 수 있다.
영속성 컨텍스트 이걸로 마스터 하신것같습니다 대단하십니다