✅ 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에서 도메인 로직이 발생할 수 있음
✅ 실무에서는 어떻게?
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 목적 | ⭕ 켜도 무방 |
'개발 > Java & Kotlin' 카테고리의 다른 글
[Spring] Spring에서 @Value 어노테이션 사용 시 주의할 점 정리 (80) | 2025.07.11 |
---|---|
[JPA] Spring Data JPA에서 새로운 Entity인지 판단하는 방법 (2) (73) | 2025.07.01 |
[Spring] Spring 프로젝트에서 레이어드 아키텍처 제대로 이해하기 (83) | 2025.06.23 |
[Gradle] Gradle을 알아보자! (78) | 2025.05.16 |
[Spring] 트랜잭션 롤백하는 예외 (76) | 2025.05.12 |