Spring boot 03. JPA 영속성 컨텍스트(Persistence Context)

Geun Nam Park·2026년 6월 9일

Spring Boot

목록 보기
4/5

JPA를 처음 배우면 이런 코드를 자주 보게 된다.

@Transactional
public void updateUser(Long id) {
    User user = userRepository.findById(id)
            .orElseThrow();

    user.setName("Kim");
}

신기한 점은 save()를 호출하지 않았는데도 데이터베이스의 값이 변경된다는 것이다.

처음에는 "JPA가 원래 그런가 보다" 하고 넘어갈 수 있지만, 사실 이 현상을 이해하지 못하면 JPA를 제대로 사용하기 어렵다.

이 동작의 중심에는 영속성 컨텍스트(Persistence Context) 가 있다.

이번 글에서는 영속성 컨텍스트가 무엇인지, 왜 존재하는지, 그리고 JPA가 어떻게 엔티티를 관리하는지 자세히 알아보자.


영속성 컨텍스트란

영속성 컨텍스트란 JPA가 엔터티를 관리하는 공간이다. JPA는 엔티티(객체)를 DB에 저장하기 이전에 꼭 이 영속성 컨텍스트라는 곳에 먼저 저장을 해야한다.
애플리케이션 ⇒ 영속성 컨텍스트 ⇒ Database
중간에 존재하는 캐시 공간같은 느낌이다.



영속성 컨텍스트의 장점

1. 성능 향상

같은 데이터를 여러 번 조회할 때 매번 DB에 접근하면 비효율적이다.

영속성 컨텍스트는 1차 캐시 역할을 수행한다.

2. 변경 감지

객체 값이 바뀌었는지 추적할 수 있다.

3. 객체 동일성 보장

같은 데이터를 조회하면 항상 같은 객체를 반환한다.



Entity 생명주기

JPA 엔터티는 4가지 상태를 가진다.

1. 비영속(Transient)
객체만 생성된 상태

User user = new User();

JPA는 해당 객체를 아직 모른다.


2. 영속(Persistent)
영속성 컨텍스트가 관리하는 상태

entityManager.persist(user);

JPA가 해당 객체를 관리하기 시작한다.
해당 상태에서 Dirty Checking, 1차 캐시 등이 동작한다.


3. 준영속(Detached)
관리 대상에서 제외

entityManager.detach(user);

이후 값을 변경해도 DB에 반영되지 않는다.


4. 삭제(Removed)
삭제 예정 상태

entityManager.remove(user);

트랜잭션이 종료되면 DELETE SQL이 실행된다.



영속성 컨텍스트의 이점

1차 캐시
내부에 엔터티를 저장할 수 있는 캐시들을 가지고 있다.

User user1 = em.find(User.class, 1L);
User user2 = em.find(User.class, 1L);


두 번째 조회는 DB에 접근하지 않는다.

DB조회 ⇒ 영속성 컨텍스트 저장 ⇒ 재사용

DB 접근을 줄여 성능을 향상시킨다.


동일성 보장

영속성 컨택스트는 같은 엔티티를 조회하면 같은 객체를 반환한다.

User user1 = em.find(User.class, 1L);
User user2 = em.find(User.class, 1L);

System.out.println(user1 == user2)

결과

true

메모리에 하나만 존재하기 때문에 true이다.


Dirty Checking (변경 감지)

@Transactional
public void updateUser(Long id) {
	User user = repository.findById(id).orElseThrow();
    
    user.setName("Kim");
}

save() 없음
update() 쿼리 없음
그래도 DB 값이 변경된다.

name = Park

이후

user.setName(Kim);

실행

name = Kim

트랜잭션 종료 시

Park ≠ Kim

확인

UPDATE user
SET name='Kim'

Flush

영속성 컨텍스트의 변경 내용을 DB에 반영

em.flush();

의 의미는

영속성 컨텍스트
∇
DB로 SQL 전송

※ 주의
flush ≠ commit
DB에 SQL만 보내고 트랜잭션은 유지된다.

0개의 댓글