복잡한뇌구조마냥

[JPA] OSIV ( Open Session In View ) 본문

BE/Spring

[JPA] OSIV ( Open Session In View )

지금해냥 2025. 11. 25. 02:14

1️⃣ OSIV(Open Session In View) 개념 잡기

✔ OSIV / OEIV 용어 정리

용어 설명
OSIV (Open Session In View) Hibernate 환경에서 Session을 요청–응답 전 범위에서 열어두는 패턴
OEIV (Open EntityManager In View) JPA 환경에서 EntityManager를 요청–응답 범위에서 유지하는 패턴

둘은 실질적으로 동일하며, 관례적으로 OSIV라고 부른다.

👉 핵심 개념

요청(Request) 시작부터 응답(Response)까지 영속성 컨텍스트를 열어둔다.
→ 트랜잭션이 끝난 뒤에도 Lazy Loading이 가능해진다.


2️⃣ OSIV의 동작 방식

OSIV가 true일 때 JPA의 동작 흐름은 다음과 같다:

 
[요청(Request) 시작]
      ↓
OSIV Filter가 영속성 컨텍스트(EntityManager) 생성
      ↓
Service 계층(@Transactional) 수행 후 트랜잭션 종료
(하지만 EntityManager는 닫히지 않음)
      ↓
Controller / View / JSON 직렬화 과정에서도 Lazy 로딩 가능
      ↓
응답(Response) 직전에 EntityManager 종료

✔ 스프링 설정

 
spring:
  jpa:
    open-in-view: false  # 기본값 true, OSIV 활성화

3️⃣ OSIV를 사용하면 좋은 이유 (장점)

✔ 1) Lazy Loading을 마음껏 사용할 수 있다

OSIV = true일 경우:

  • Service layer에서 트랜잭션이 끝났더라도
  • Controller/JSON 변환 과정에서 .getOrders()처럼 LAZY 필드를 접근하면
  • Hibernate가 즉시 DB 쿼리를 날려 데이터를 가져온다

→ 개발할 때 매우 “편하다”.

✔ 2) DTO 변환 없이 엔티티를 반환하는 코드 스타일이 가능

OSIV가 켜져 있으면:

  • 엔티티를 Controller까지 그대로 넘겨도 문제 없음
  • Jackson 직렬화 과정에서 Lazy 필드를 호출해 쿼리가 나간다
  • 개발 난이도 ↓, 코드 간결

즉, 개발 속도가 빨라지는 구조이다.


4️⃣ OSIV가 갖는 치명적인 단점 — 성능 폭탄

OSIV가 true일 때 가장 위험한 점은 다음이다.

❌ “트랜잭션은 끝났는데, DB 커넥션은 계속 점유한다”

즉:

  • OSIV는 영속성 컨텍스트를 Request 전체에 걸쳐 유지한다
  • 영속성 컨텍스트는 내부적으로 DB Connection을 붙잡고 있는 경우가 많다

→ 외부 API 호출, 연산, 랜더링 등 JPA와 무관한 시간에도
DB 커넥션을 계속 유지한다.

영상에서 나온 사례:

🔥 예시 — 외부 API 호출이 15초 걸리는 경우

OSIV = true OSIV = false
15초 동안 DB 커넥션 점유 트랜잭션 종료 → 커넥션 반환
Connection Pool 고갈 가능 외부 API 시간 동안 DB 부하 없음
트래픽 많은 서비스에서 장애 유발 안정적 운영 가능

즉, OSIV는 개발자가 생각하는 것보다 훨씬 위험하다.


5️⃣ OSIV ON/OFF 비교

항목 OSIV = true OSIV = false
Lazy Loading 시점 Controller/Response까지 가능 오직 트랜잭션 내부에서만 가능
LazyInitializationException 거의 없음 서비스 밖에서 Lazy 접근 시 즉시 발생
개발 난이도 쉽고 빠름 DTO/FetchJoin 필요
DB Connection 점유 길어짐 (심각) 짧음
성능 이슈 발생 확률 높음 안정적
구조적 장점 Layered Architecture 흐트러짐 계층 분리 명확
운영 적합성 ❌ 낮음 ⭕ 높음

6️⃣ 많은 전문가들이 OSIV를 "안티 패턴"이라고 부르는 이유 

  • 성능 이슈가 발생하기 쉽고
  • 계층 구조가 깨지고
  • 엔티티가 Controller/JSON 변환에 노출된다는 점 때문에

Hibernate Community에서도 여러 차례 경고가 있었고
국내·해외 개발자들 대부분은 운영 환경에서는 OSIV를 끌 것을 권장한다.

→ 즉, OSIV는 “편한 기능이지만 위험한 기능”.


7️⃣ 결론 — OSIV는 언제 켜야 하고, 언제 꺼야 할까?

✔ OSIV = true (허용되는 경우)

  • 트래픽 적은 내부 어드민
  • Lazy 로딩을 템플릿 기반 웹 뷰에서 많이 활용할 때
  • 개발 속도를 중요시하는 초기 단계

→ 성능보다는 편의성을 우선하는 환경

✔ OSIV = false (권장)

  • 트래픽이 많은 B2C 서비스
  • API 서버 (특히 REST API)
  • 외부 연동이 많은 서비스
  • 대량 처리/배치가 있는 시스템
  • 장애 발생 시 피해 규모가 큰 서비스

→ 대부분의 현대 서비스 구조에서는 false가 정석


8️⃣ OSIV = false일 때 필요한 전략

OSIV를 끄면 Lazy Loading이 트랜잭션 밖에서 동작하지 않기 때문에
다양한 설계 전략이 필요하다.

🔹 1) Fetch Join 적극 활용

Lazy 필드를 미리 한번에 가져오기

🔹 2) DTO 변환을 Service 계층에서 수행

Controller까지 엔티티가 노출되지 않게 하기

🔹 3) QueryDSL 또는 JOOQ 사용

복잡한 조회는 전용 Query layer에서 해결

🔹 4) CQRS 구조 적용

Command(JPA) / Query(QueryDSL·JOOQ) 분리

→ OSIV를 끄는 순간 구조가 “올바른 방향”으로 강제되는 효과가 있다.


📌 최종 요약

OSIV는 개발 속도를 높이기 위해 만들어진 기능이지만,
운영 환경에서 성능 문제(DB 커넥션 고갈)를 야기할 수 있기 때문에
대부분의 서비스에서는 OSIV = false로 설정하는 것이 정답에 가깝다.

 

참고자료:

https://www.youtube.com/watch?v=Q2n9I86mav4

 

LIST