이지은님의 블로그
250312 - Java Spring JPA 영속성 컨텍스트와 트랜잭션의 설정(EntityManager, OSIV, @Transactional) 본문
250312 - Java Spring JPA 영속성 컨텍스트와 트랜잭션의 설정(EntityManager, OSIV, @Transactional)
queenriwon3 2025. 3. 12. 20:21▷ 오늘 배운 것
세션에서 배운 영속성 컨텍스트, Transaction 그리고 강의에서 배운 DB에서의 트랜젝션 사용에 대해 정리해보려고 한다.
<<목차>>
1. 영속성 컨텍스트와 설정
1) Spring Data JPA
2) JPA에서 Entity LifeCycle와 Entity Manager
3) OSIV(Open Session in View)
2. Transaction
1) 트랜잭션
2) 트랜잭션 관리와 보안 (DCL)
3) @Transactional
1. 영속성 컨텍스트와 설정
1) Spring Data JPA
- Spring Data JPA는 개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와주는 Spring에서 제공하는 모듈 중 하나
- JPA를 한 단계 더 추상화시킨 JpaRepository 라는 인터페이스를 제공
2) JPA에서 Entity LifeCycle와 Entity Manager
이 과정을 코드로 작성해보자 (저장)
private final EntityManagerFactory emf;
public void saveMovie(MovieRequest movieRequest) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
Movie movie = new Movie(movieRequest.getName(), movieRequest.getProductionYear());
em.persist(movie); // 영속화 -> JPA 영속성 컨텍스트에서 상태를 관리
em.flush(); // db에 저장
tx.commit();
} catch (Exception ex) {
tx.rollback();
}
em.close();
}
이를 간소화 한 것이 아래 코드이다.
@Transactional
public void saveMovie(MovieRequest movieRequest) {
Movie movie = new Movie(movieRequest.getName(), movieRequest.getProductionYear());
movieRepository.save(movie);
}
그럼 EntityManager는 무엇일까?
1️⃣ Entity Manager Factory
- JPA에서 EntityManager를 생성하고 관리하는 팩토리 객체
- 애플리케이션 실행 시 한 번만 생성되며, 애플리케이션 전체에서 공유되며, thread-safe 함.
- EntityManager 생성, 데이터베이스 연결, 트랜잭션 관리 등의 역할 수행
2️⃣ Entity Manager
- 데이터베이스와 상호작용하는 객체로, 엔티티의 생명 주기를 관리하며, thread-safe 하지 못함.
- 엔티티 객체의 라이프 사이클 및 영속성 관리 (영속성 ↔ 비영속성)
- 엔티티 객체에 대해 데이터베이스에서 CRUD 연산 수행
- Entity에서 관리하기 때문에 스프링에서 지원하는 @Transactional을 함께 사용할 수 없음
3) OSIV(Open Session in View)
: OSIV는 영속성 컨텍스트를 View 렌더링이 끝날 때까지 개방된 상태로 유지하는 방식
장점
- 편리한 지연 로딩: Controller나 View에서도 지연 로딩 사용 가능
- 유연한 설계: 복잡한 화면 구성에서도 필요한 시점에 데이터 로딩 가능
- 개발 생산성: LazyInitializationException 걱정 없이 개발 가능
단점
- 데이터베이스 커넥션 점유: 컨트롤러와 뷰 렌더링이 끝날 때까지 DB 커넥션을 유지
- 실시간 트래픽: 커넥션 보유 시간이 길어져 서버 자원을 많이 사용
- 성능 이슈: 과도한 DB 커넥션 사용으로 인한 성능 저하 가능성
![]() |
![]() |
Osiv = true(default) —> 영속성 컨텍스트 생존범위가 controller와 view바깥까지 영향을 줌 |
Osiv = false —> 영속성 컨텍스트 생존범위를 service까지로 한정한다. 성능관점에서는 false로 설정하는 것이 권장된다. |
OSIV 설정
spring:
jpa:
open-in-view: false
2. Transaction
1) 트랜잭션
: 데이터베이스에서 일어나는 하나의 논리적 작업 단위
트랜잭션의 3가지 특징 (원자성, 일관성, 독립성)
1️⃣ 원자성 (All or Nothing)
- 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것이다.
- 트랜잭션은 사람이 설계한논리적인 작업 단위로서, 일처리는 작업단위 별로 이루어 져야 사람이 다루는데 무리가 없다.
- 만약 트랜잭션 단위로 데이터가 처리되지 않는다면, 설계한 사람은 데이터 처리 시스템을 이해하기 힘들 뿐만 아니라, 오작동 했을시 원인을 찾기가 매우 힘들어질것이다.
2️⃣ 일관성 (Keeps Data Correct)
- 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것이다.
- 트랜잭션이 진행되는 동안에 데이터베이스가 변경 되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는것이 아니라,처음에 트랜잭션을 진행 하기 위해 참조한 데이터베이스로 진행된다.
- 이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있는 것이다.
3️⃣ 독립성 (Independent)
- 둘 이상의 트랜잭션이 동시에 실행되고 있을 경우 어떤 하나의 트랜잭션이라도, 다른 트랜잭션의 연산에 끼어들 수 없다는 점을 가리킨다.
2) 트랜잭션 관리와 보안 (DCL)
1️⃣ BEGIN 이란?
- START TRANSACTION 과 동일하며 새로운 트랜잭션을 생성 및 시작하는 연산이다.
2️⃣ COMMIT 이란?
- 하나의 트랜잭션이 성공적으로 끝났고, 데이터베이스가 일관성있는 상태에 있을 때, 하나의 트랜잭션이 끝났다라는 것을알려주기위해 사용하는 연산이다. 이 연산을 사용하면 수행했던 트랜잭션이 로그에 저장되며, 후에 Rollback 연산을 수행했었던 트랜잭션단위로 하는것을 도와준다.
3️⃣ ROLLBACK 이란?
- 하나의 트랜잭션 처리가 비정상적으로 종료되어 트랜잭션의 원자성이 깨진경우, 트랜잭션을 처음부터 다시 시작하거나, 트랜잭션의 부분적으로만 연산된 결과를 다시 취소시킨다.
3) @Transactional
: Spring에서 메서드 또는 클래스에 적용하여 트랜잭션을 선언적으로 관리하는 방법
트랜잭션 범위에 대해 Proxy 패턴을 사용하여 트랜잭션 관리
1️⃣ readOnly = true
: 성능상 이점을 가짐. 읽기 전용이라 더티체킹을 생략할 수 있어 성능이 향상됨.
저장소에 건드는 코드를 접근하지 않음.
2️⃣ Propagation
: 트랜잭션이 다른 트랜잭션과 어떻게 상호작용할지를 결정하는 방식
종류
- REQUIRED (기본값): 이미 진행 중인 트랜잭션이 있으면 그 트랜잭션을 사용하고, 없으면 새 트랜잭션을 시작
- REQUIRES_NEW: 항상 새 트랜잭션을 시작하며, 진행 중인 트랜잭션은 잠시 중단(로그를 작성할 때 주로 사용. 에러가 발생해도 로그를 작성할 수 있음)
- SUPPORTS: 트랜잭션이 이미 존재하면 그 트랜잭션 내에서 실행하고, 없으면 비트랜잭션 실행
- MANDATORY: 현재 트랜잭션이 반드시 있어야 하며, 없으면 예외가 발생
- NEVER: 트랜잭션 없이 실행되어야 하며, 트랜잭션이 존재하면 예외가 발생
- NESTED: 진행 중인 트랜잭션 내부에 또 다른 트랜잭션을 중첩시켜 실행할 수 있으며, 이 경우 Savepoint를 이용
3️⃣ Isolation
: 동시에 실행되는 트랜잭션들이 서로에게 얼마나 영향을 미칠지를 정의하는 방법
- DEFAULT: 데이터베이스의 기본 고립성 수준을 따름. MySQL의 경우 REPEATABLE READ가 기본
- READ_UNCOMMITTED: 다른 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있음. 가장 낮은 고립 수준으로, Dirty Read 허용
- READ_COMMITTED: 커밋된 데이터만 읽을 수 있음, Dirty Read는 방지하지만 Non-Repeatable Read, Phantom Read 허용
- REPEATABLE_READ(기본): 트랜잭션 내에서 동일한 데이터를 반복해서 읽을 때 항상 동일한 결과를 보장. Non-Repeatable Read는 방지하지만 Phantom Read는 허용
- SERIALIZABLE: 가장 엄격한 고립 수준으로, 트랜잭션을 직렬화 실행. 모든 문제는 방지되지만, 순차처리로 성능이 떨어짐