Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

이지은님의 블로그

250312 - Java Spring JPA 영속성 컨텍스트와 트랜잭션의 설정(EntityManager, OSIV, @Transactional) 본문

TIL

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)

  1. 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것이다.
  2. 트랜잭션은 사람이 설계한논리적인 작업 단위로서, 일처리는 작업단위 별로 이루어 져야 사람이 다루는데 무리가 없다.
  3. 만약 트랜잭션 단위로 데이터가 처리되지 않는다면, 설계한 사람은 데이터 처리 시스템을 이해하기 힘들 뿐만 아니라, 오작동 했을시 원인을 찾기가 매우 힘들어질것이다.

 

2️⃣ 일관성 (Keeps Data Correct)

  1. 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것이다.
  2. 트랜잭션이 진행되는 동안에 데이터베이스가 변경 되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는것이 아니라,처음에 트랜잭션을 진행 하기 위해 참조한 데이터베이스로 진행된다.
  3. 이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있는 것이다.

 

3️⃣ 독립성 (Independent)

  1. 둘 이상의 트랜잭션이 동시에 실행되고 있을 경우 어떤 하나의 트랜잭션이라도, 다른 트랜잭션의 연산에 끼어들 수 없다는 점을 가리킨다.

 

 

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: 가장 엄격한 고립 수준으로, 트랜잭션을 직렬화 실행. 모든 문제는 방지되지만, 순차처리로 성능이 떨어짐