@Transactional과 OSIV 설정 관계

별빛사막·2025년 1월 6일

@Transactional과 OSIV 설정 관계

스프링 부트에서 기본 설정으로 서비스 레이어에서 트랜잭션이 관리된다.
OSIV(Open Session In View) 설정이 활성화되어 있다면 컨트롤러와 뷰 레이어에서도 DB 커넥션이 유지된다.
그러나 테스트 레이어에서는 @Transactional을 사용해야 DB 커넥션이 열려 있는 상태가 유지된다.

OSIV란?

  • OSIV(Open Session In View)는 Hibernate를 사용할 때 데이터베이스 세션을 관리하는 패턴이다.
  • Lazy Loading(지연 로딩) 시 발생할 수 있는 LazyInitializationException 문제를 해결하기 위해 사용된다.
  • OSIV 설정은 application.properties 또는 application.yml 파일에서 설정할 수 있다.
spring.jpa.open-in-view=true  # OSIV 활성화
spring.jpa.open-in-view=false # OSIV 비활성화
  • OSIV 활성화: 컨트롤러와 뷰 레이어에서도 데이터베이스 세션이 열려 있어 Lazy 로딩 가능.
  • OSIV 비활성화: 서비스 레이어에서 모든 로직을 처리한 후 컨트롤러로 데이터를 반환해야 Lazy 로딩 문제가 발생하지 않음.

테스트 레이어에서 @Transactional 사용 이유

테스트 레이어에서는 OSIV 설정과 상관없이 @Transactional을 붙여야 DB 커넥션이 열려 있는 상태로 유지된다.
예를 들어, 아래와 같이 테스트 코드를 작성할 수 있다.

@SpringBootTest
class SbbApplicationTests {

    @Autowired
    private QuestionRepository questionRepository;

    @Transactional
    @Test
    void testJpa() {
        Optional<Question> oq = this.questionRepository.findById(2); // 트랜잭션이 열리고 닫힘
        assertTrue(oq.isPresent());
        Question q = oq.get();

        List<Answer> answerList = q.getAnswerList(); // Lazy 로딩에 의해 동작
        assertEquals(1, answerList.size());
        assertEquals("네 자동으로 생성됩니다.", answerList.get(0).getContent());
    }
}

OSIV 설정을 항상 켜야 할까?

OSIV 활성화 시 유용한 경우

  • JSP나 타임리프와 같은 템플릿 엔진을 사용할 경우 OSIV 설정을 활성화하는 것이 유용하다.
  • 컨트롤러와 뷰 레이어에서 Lazy 로딩을 활용할 수 있다.

OSIV 비활성화 추천 경우

  • REST API에서는 OSIV를 비활성화해도 무방하다.
  • OSIV 비활성화 시, 성능 최적화 및 불필요한 DB 세션 유지 방지가 가능하다.

컨트롤러에서 @Transactional 사용 여부에 따른 동작

  1. @Transactional 없음:
    OSIV 설정이 true일 때만 컨트롤러에서 Lazy 로딩이 가능하다.
    OSIV가 false일 경우 LazyInitializationException 발생.

  2. @Transactional 있음:
    컨트롤러에서도 DB 커넥션이 열려 있으므로 Lazy 로딩 가능.

OSIV 와 상관없이 JPA를 사용할때는 @Transactional을 컨트롤러 액션메서드에 거는게 좋다.


@Transactional 사용 가이드

  • 등록, 수정, 삭제: @Transactional
    • 트랜잭션이 필요하며, readOnly = true 옵션 사용 불가.
  • 조회: @Transactional(readOnly = true)
    • 읽기 전용 트랜잭션으로 성능 최적화 가능.

HikariCP와 auto-commit 설정

  • MySQL의 기본 설정: Auto-commit 모드 활성화.
  • 문제점: Query 실행 시마다 Auto-commit 설정 변경으로 성능 저하 발생.
    • 예: 100만 번의 Query 실행 → 200만 번의 Auto-commit 설정 변경 발생.
SET autocommit=0;  # Auto-commit 끄기
SET autocommit=1;  # Auto-commit 켜기
  • 해결 방법: HikariCP의 auto-commit 설정을 false로 설정.
spring:
  datasource:
    hikari:
      auto-commit: false
  • Auto-commit을 끄면 트랜잭션 범위 내에서 명시적으로 commit을 호출할 수 있어 성능 최적화가 가능하다.

set autocommit 개선을 통한 성능 최적화

profile
조금씩 매일 성장하자

0개의 댓글