본문 바로가기

웹 프로그래밍/Spring Framework

[Hibernate / JPA ] LazyLoading | No Session 에러에 대해서

"No Session 에러는 개발자의 실수!"


 보통 하이버네이트/JPA 기반의 프로젝트에서 주로 발생하는 에러는 No Session에러이다. 해당 에러는 영속성(편하게 말하자면 영혼을 가진, 데이터베이스와 바인딩 된 등으로 이해하면 편하다.)을 가진 객체(인스턴스)가 프로젝트의 트랜잭션 범위를 벗어나 추가적인 Lazy 로딩을 걸 때, DB와 연결된 Connection이 없어서 나는 에러이다(정확히는 커넥션이 없기보다. 이미 커넥션에 커밋을 날리고 트랜젝션이 닫힌 상태를 의미).


따라서 해당 에러를 처리하기 위해 아래 방법들이 있다.


 1. 아키텍쳐에게 트랜잭션이 걸린 범위를 질의하여 해당 프로젝트 정책에 맞게 개발한다. (필수)

 2. 화면에 전달되는 객체중 Lazy Proxy를 가지고 있는 객체를 Null 처리한다. [ 이경우 반드시 해당 객체가 영속성을 벗어난 상태여야함, 따라서 서비스까지 트랜잭션이 걸려있다면 컨트롤러에서 null처리를 하거나 RESTFUL Service라면 클라이언트에 줄 DTO객체에 옮길떄 프록시가 걸린 객체만제거하거나..]

 3. Entity에서 관계가 걸린 부분의 @JsonIgnore 처리한다.

 4. 2번의 설명과 같이 영속성이 완전히 제거된 객체로 데이터를 옮긴다. (영속성을 가지고 있는 객체는 수정하면 안됨!) << 추천.



 생각할 수 있는 방법은 위 4개가 전부인데 해당 방법중 가장 추천하는 방법은 Entity에서 영속성에 없는 객체로 완전히 데이터만 옮기는 것이다. 이 방법을 추천하는 이유는 엔티티를 DTO와 같은 영속성이 제거된 객체에 옮기지않고 그대로 클라이언트까지 접근하게된다면, Restful 서비스의 경우 객체안의 모든 프로퍼티에 접근하므로 LazyLoading을 시키게되고 이는 Nosession에러를 유발시킨다. 그렇다고 해당 관계만 JsonIgnore처리하게 된다면 혹시 나중에 프로젝트의 ERD가 바뀌게 되면서 해당 테이블들의 관계가 수정되면 해당 테이블들과 매핑된 모든 엔티티가 쓰인 BIZ, SVC, CTRL를 수정해야한다. 이는 의존성이 너무나도 강하게 묶인 측면 때문에 추천하지 않는다.


 따라서 최종적으로 추천하는 방법은 Entity와 DTO(또는 VO 등등.. 여간 POJO 객체)에 데이터를 옮겨 의존성을 강제적으로 때어내는 방법이 가장 적합하다고 생각한다.



PS : 위와같은 에러를 해소하기 위해서 컨트롤러에 @TRANSACTIONAL 따위의 어노테이션을 붙혀 강제적으로 해결하려고하지 말자. 이는 아키텍쳐와 모두가 준수하는 개발정의서 위반이다.