개발/Java & Kotlin

[Spring] OSIV(Open Session In View) 옵션

devhooney 2025. 6. 30. 10:16
728x90

 

 

✅ OSIV란?

Open Session In View (OSIV)는 JPA에서 HTTP 요청이 끝날 때까지 영속성 컨텍스트(EntityManager)를 열어두는 전략이다.
이 설정이 true(기본값)면, Controller나 View(Rendering) 단계에서도 Lazy Loading이 가능하다.

Spring Boot에서는 기본적으로 spring.jpa.open-in-view=true 로 켜져 있다.

 

 


 

 

 

✅ 왜 등장했을까?

JPA는 기본적으로 지연 로딩(Lazy Loading)을 많이 쓴다.
예를 들어,

@GetMapping("/users/{id}")
public UserDto getUser(@PathVariable Long id) {
    User user = userRepository.findById(id).orElseThrow();
    return new UserDto(user.getName(), user.getOrders()); // orders는 Lazy
}

 

user.getOrders()가 Lazy 로딩이라면 DB 조회가 이 시점에 발생한다.
그런데 만약 트랜잭션이 이미 끝났다면?

LazyInitializationException 이 터진다.

그래서 OSIV를 true로 켜두면, 트랜잭션 범위를 View 렌더링까지 넓혀서 Lazy 로딩이 가능하게 만든다.

 

 


 

✅ 장점과 단점

👍 장점
- Controller나 View 단에서도 지연 로딩이 가능
- 실수로 Lazy 객체를 늦게 접근해도 에러 안 남
- 빠르게 구현 가능

👎 단점
- 트랜잭션이 길어짐: DB 커넥션을 요청 종료까지 유지
- DB 커넥션 낭비: View 렌더링 중에도 커넥션 점유
- 성능 저하 가능성: 특히 트래픽 많거나 DB 자원이 부족할 때 치명적
- 계층 간 책임이 불분명해짐: Controller에서 도메인 로직이 발생할 수 있음

 

 


728x90

 

 

✅ 실무에서는 어떻게?

1. API 서버: 무조건 끄는 걸 추천
API는 JSON만 반환하므로, View 렌더링을 고려할 이유가 없다.

spring.jpa.open-in-view=false

 

- 대신 서비스 계층에서 모든 Lazy 로딩이 해결되도록 설계
- 필요한 관계는 명시적으로 join fetch 혹은 @EntityGraph 로 가져오도록 해야 한다.

 

2. 템플릿 엔진 기반 서버(MVC): 켜둘 수 있음
Thymeleaf나 JSP처럼 View 렌더링이 존재하고, 뷰 템플릿에서 Lazy 로딩 객체를 접근할 필요가 있다면 켜는 것도 나쁘지 않음. 하지만 성능은 신경 써야 함.

 

 

 

 


 

 

✅ Lazy 로딩 안전하게 처리하는 방법

OSIV를 끈 경우에는 Lazy 로딩을 다음 방식으로 미리 해결해야 한다:

✔ 방법 1: fetch join

@Query("SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id")
Optional<User> findByIdWithOrders(@Param("id") Long id);

 

✔ 방법 2: @EntityGraph

@EntityGraph(attributePaths = "orders")
Optional<User> findById(Long id);

 

✔ 방법 3: DTO Projection

@Query("SELECT new com.example.UserDto(u.name, o.name) FROM User u JOIN u.orders o")
List<UserDto> findUserDtos();

 

 

 


 

✅ 결론: 언제 끄고 언제 켜야 하나?

구분 권장 OSIV 설정
REST API 서버 ❌ 끄는 것이 안전
서버 템플릿 사용 ⭕ 상황에 따라 유지 가능
성능 중요 ❌ 끄는 것이 좋음
빠른 개발/PoC 목적 ⭕ 켜도 무방

 

 

 

728x90