티스토리 뷰
OSIV이란?
JPA의 OSIV(Open Session In View) 는 웹 요청이 시작될 때 영속성 컨텍스트(EntityManager)를 생성하고, 응답이 끝날 때까지 유지하는 패턴이다.
OSIV 설정 방법
아래는 Spring Boot 환경에서 yaml 파일에 대한 설정 방법이고, Spring Boot에서는 기본적으로 OSIV가 활성화되어 있다.
spring:
jpa:
open-in-view: true
OSIV가 필요한 이유
JPA의 연관관계가 LAZY 로딩일 때 문제가 발생할 수 있다.
// 엔티티
@Entity
public class Order {
@ManyToOne(fetch = FetchType.LAZY)
private Member member;
}
// 서비스
@Transactional
public Order findOrder(Long id) {
return orderRepository.findById(id).get();
}
// 컨트롤러
@GetMapping("/orders/{id}")
public String order(@PathVariable Long id) {
Order order = orderService.findOrder(id);
String memberName = order.getMember().getName();
return memberName;
}
OSIV가 false일 경우
- 서비스 메서드 종료
- 트랜잭션 종료
- 영속성 컨텍스트 종료
- 컨트롤러에서 order.getMember() 호출
- Lazy Loading 불가
- LazyInitializationException 에러 발생
OSIV가 true일 경우
- 요청 시작 시 EntityManager 생성
- 서비스 트랜잭션 종료 후에도 유지
- 컨트롤러에서 Lazy Loading 가능
- 응답 완료 시 EntityManager 종료
OSIV 동작 구조
OSIV가 true인 경우

OSIV가 true인 경우 데이터베이스 커넥션 시작 시점부터 API 응답이 끝날 때 까지 영속성 컨텍스트 와 데이터베이스 커넥션을 유지한다. 그래서 View Template이나 API 컨트롤러에서 지연 로딩이 가능했던 것이다.
OSIV가 false인 경우

OSIV가 false인 경우 트랜잭션을 종료할 때 영속성 컨텍스트를 닫고, 데이터베이스 커넥션도 반환한다. 그리고 모든 지연로딩을 트랜잭션 안에서 처리해야 한다.
OSIV 장점
1. Lazy Loading이 편리
-> 별도 조회 없이 접근 가능
order.getMember().getName();
2. 개발 생산성 향상
-> 서비스 계층에서 필요한 데이터를 전부 조회해둘 필요가 없고, 컨트롤러에서 연관 객체 접근 가능하다.
OSIV 단점
1. 데이터베이스 커넥션을 오래 점유
-> OSIV true 상태에서는 영속성 컨텍스트가 요청 끝까지 유지된다. 상황에 따라 DB 커넥션이 예상보다 오래 사용될 수 있어 트래픽이 많아지면 문제가 될 수 있다.
2. N+1 문제를 숨긴다.
-> 컨트롤러에서 예상치 못한 추가 쿼리가 발생할 수 있다.
// 컨트롤러
orders.forEach(order -> {
System.out.println(order.getMember().getName());
});
select * from orders;
select * from member where id=?
select * from member where id=?
select * from member where id=?
...
3. 계층 분리가 흐려짐
-> 원칙적으로는 Controller->Service->Repository 인데 Controller에서 Lazy Loading이 발생하게 되면 조회 로직이 프레젠테이션 계층까지 발생하게 된다.
실무에서는?
실무에서는 OSIV를 끄는 경우가 많으며, 서비스 계층에서 Fetch Join과 DTO을 사용하여 조회한다.
spring:
jpa:
open-in-view: false
정리
OSIV는 요청 시작부터 응답 완료 시점까지 영속성 컨텍스트를 유지하여 트랜잭션 종료 이후에도 Lazy Loading을 가능하게 하는 기능이다. 다만 개발 편의성을 높여주지만 성능 문제를 숨길 수 있기 때문에, 실무에서는 OFF 후 Fetch Join·DTO 조회를 적극 활용하는 방식이 많이 사용된다.
본 포스팅은 “ 실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화/인프런”를 학습한 내용을 정리한 것
'Java > JPA' 카테고리의 다른 글
| <JPA> 일대다(1:N) 단방향 연관관계 맵핑 시 주의할 점 (0) | 2026.04.29 |
|---|---|
| <JPA> 페이징 처리 (3) | 2024.11.07 |
| <JPA> @Enumerated 사용 시 주의할 점 (0) | 2024.10.31 |
| <JPA> 벌크 연산시 주의할 점 (2) | 2024.10.03 |
| <JPA> 준영속 엔티티를 수정하는 2가지 방법 (0) | 2024.09.30 |