📌 영속성 컨텍스트는 Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간이다.
영속성 컨텍스트가 어떻게 Entity 객체를 효율적으로 관리하고 있는지 살펴보자.
1차 캐시
💡영속성 컨텍스트 내부

- 영속성 컨텍스트는 내부적으로 캐시 저장소를 가지고 있다.
- Java의 @Entity 클래스의 객체들이 1차 캐시 즉, 캐시 저장소에 저장된다.
- 이 캐시 저장소는 Map 자료 구조 형태로 되어있다.
- key에는 @Id로 매핑한 기본키 즉, 식별자 값을 저장한다.
- value에는 해당 Entity 클래스의 객체를 저장한다.
캐시 저장소 활용
영속성 컨텍스트가 이 캐시 저장소를 어떻게 활용하고 있는지 예시를 통해 살펴보자
1️⃣ Entity 저장

- em.persist(memo); 메서드가 호출되면 memo Entity 객체를 캐시 저장소에 저장한다.
✅ memo 저장 Test 코드
@Test
@DisplayName("1차 캐시 : Entity 저장")
void test1() {
EntityTransaction et = em.getTransaction();
et.begin();
try {
Memo memo = new Memo();
memo.setId(1L);
memo.setUsername("Robbie");
memo.setContents("1차 캐시 Entity 저장");
em.persist(memo);
et.commit();
} catch (Exception ex) {
ex.printStackTrace();
et.rollback();
} finally {
em.close();
}
emf.close();
}
- em > persistenceContext > entitiesBykey

- key-value 형태로 정보가 저장되어있음을 확인할 수 있다.
2️⃣ Entity 조회
🔎 캐시 저장소에 조회하는 Id가 존재하지 않은 경우
1. 캐시 저장소 조회

2. DB SELECT 조회 후 캐시 저장소에 저장

- em.find(Memo.class, 1); 호출 시 캐시 저장소를 확인 한 후 해당 값이 없다면?
- DB에 SELECT 조회 후 해당 값을 캐시 저장소에 저장하고 반환한다.
✅ memo 조회 Test 코드
@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하지 않은 경우")
void test2() {
try {
Memo memo = em.find(Memo.class, 1);
System.out.println("memo.getId() = " + memo.getId());
System.out.println("memo.getUsername() = " + memo.getUsername());
System.out.println("memo.getContents() = " + memo.getContents());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
em.close();
}
emf.close();
}
- DB에서 데이터를 조회만 하는 경우에는 데이터의 변경이 발생하는 것이 아니기 때문에 트랜잭션이 없어도 조회가 가능하다.
- Memo memo = em.find(Memo.class, 1); 호출 시 캐시 저장소에 해당 값이 존재하지 않기 때문에 DB에 SELECT 조회하여 캐시 저장소에 저장한 후 반환한다.
🔎 캐시 저장소에 조회하는 Id가 존재하는 경우

- em.find(Memo.class, 1); 호출 시 캐시 저장소에 식별자 값이 1이면서 Memo Entity 타입인 값이 있는지 조회한다.
- 값이 있다면 해당 Entity 객체를 반환한다.
✅ memo 조회 Test 코드
@Test
@DisplayName("Entity 조회 : 캐시 저장소에 해당하는 Id가 존재하는 경우")
void test3() {
try {
Memo memo1 = em.find(Memo.class, 1);
System.out.println("memo1 조회 후 캐시 저장소에 저장\n");
Memo memo2 = em.find(Memo.class, 1);
System.out.println("memo2.getId() = " + memo2.getId());
System.out.println("memo2.getUsername() = " + memo2.getUsername());
System.out.println("memo2.getContents() = " + memo2.getContents());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
em.close();
}
emf.close();
}
- Memo memo1 = em.find(Memo.class, 1); 호출 때는 캐시 저장소에 존재하지 않기 때문에 DB에 SELECT 조회하여 캐시 저장소에 저장한다.
- Memo memo2 = em.find(Memo.class, 1); 를 호출 했을 때는 이미 캐시 저장소에 해당 값이 존재하기 때문에 DB에 조회하지 않고 캐시 저장소에서 해당 값을 반환한다.
3️⃣ Entity 삭제
출처
https://teamsparta.notion.site/2-9-2252dc3ef514813a93cbcc98fd367b74
챕터2-9 : 영속성 컨텍스트의 기능 | Notion
영속성 컨텍스트는 Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간입니다.
teamsparta.notion.site
'심화 > Spring' 카테고리의 다른 글
| [Gemini AI] Spring Boot와 Gemini API 활용한 AI 상품 설명 기능 구현 (4) | 2025.10.15 |
|---|---|
| [Lombok] @AllArgsConstructor 사용을 지양하는 이유 (0) | 2025.10.07 |
| [Spring] JPA와 영속성 컨텍스트 (0) | 2025.10.06 |
| [Spring] JPA란 무엇일까? (0) | 2025.10.03 |
| [Spring] IoC Container와 Bean (0) | 2025.10.02 |