OSIV(Open Session In View)는 영속성 컨텍스트를 뷰까지 열어둔다는 뜻이다. 이렇게 되면 뷰에서도 지연 로딩을 사용할 수 있게 된다.
과거 OSIV: 요청 당 트랜잭션
요청 당 트랜잭션 방식의 OSIV는 클라이언트의 요청이 들어오자마자 서블릿 필터나 스프링 인터셉터에서 트랜잭션을 시작하고 요청이 끝날 때 트랜잭션도 끝내는 방식이다.
요청 당 트랜잭션 방식의 OSIV 문제점
문제는 컨트롤러나 뷰 같은 프리젠테이션 계층이 엔티티를 변경할 수 있다는 점이다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
public String viewMemberName(Long id) {
Member member = memberService.findOne(id);
member.setName("XXX");
return member.getName();
}
}
위 코드의 의도는 고객 이름을 그냥 "XXX"로 뷰에만 노출하려는 의도였는데, 변경 감지로 인해 데이터베이스도 함께 변경돼버린 참사가 일어났다. (실제로 실무에서 이런 식으로 하는 작업했던 동료 덕에 많은 것을 배웠다...^^). 서비스 계층이 아닌 프리젠테이션 계층에서 데이터 변경은 유지보수하기 힘들어진다. 프리젠테이션에서 엔티티를 수정하지 못하게 막는 방법은 다음과 같다.
- 엔티티를 읽기 전용 인터페이스로 제공
- 엔티티 레핑
- DTO만 반환
요즘은 위 문제들로 인해 트랜잭션 범위를 프리젠테이션 계층까지 열어두지 않는다. 스프링 프레임워크가 제공하는 OSIV는 위 문제를 보완해 비즈니스 계층에서만 트랜잭션을 유지하는 방식의 OSIV를 사용한다.
(현업에선 Spring Boot를 사용하고 있는데, 스프링 부트는 OISV를 OpenEntityManagerInViewInterceptor로 기본으로 하고 있기 때문에 프리젠테이션까지 트랜잭션이 살아 있는 듯 하다.)
'개발 이야기 > JPA' 카테고리의 다른 글
[개발이야기 - JPA] 준영속 상태와 지연 로딩 (0) | 2020.05.12 |
---|---|
[개발이야기 - JPA] 병합 - merge() (0) | 2020.05.02 |