본문 바로가기
ORM/JPA

[JPA] 에러 could not initialize proxy - no Session

by 젊은오리 2022. 11. 19.
728x90

문제상황

시큐리티를 커스터마이징해서 로그인과정을 진행중에 could not initialize proxy - no Session http code 500 에러가 발생했다. UserDetailsService와 UserDetails에 대한 구현체를 작성하고, Controller에서 @AuthenticationPrincipal로 사용자 세션을 제대로 가져오나 확인하는 과정에서 문제발생.

@GetMapping("/user/{id}/update")
public String update(@PathVariable int id, @AuthenticationPrincipal PrincipalDetail principalDetail) {
   log.info("=======================");
   log.info(principalDetail.getUser().toString());
   return "user/update";

 

원인분석

오류내용을 살펴보면, User객체를 불러올때 image테이블 가져오는 과정에서 문제가 발생했다. 

Image테이블은 아래와 같이 User와 1:N관계로 fetchType은 Lazy loading으로 설정되어있다.

@OneToMany(mappedBy = "user",fetch = FetchType.LAZY)
@JsonIgnoreProperties({"user"}) //무한참조방지
private List<Image> images; //양방향매핑

 

User객체를 불러올 때 지연로딩 방식으로 로딩하기 때문에 User테이블만 가져오는 것은 문제가 없지만, Image테이블을 가져올 때 문제가 발생한 것이다.

더 정확히는, User를 가져올 때 User와 Lazy Loading으로 연관된 Image는 바로 초기화되지 않고 필요할 때 정보가 채워지는 프록시 객체로 채워지게 된다. 따라서 Controller의 principalDetail.getUser().toString(); <-이 코드를 실행하게 되면

User객체 ( User필드 + Image프록시객체 )

의 형태로 User가 생성되어서 이를 logging하면 사용자를 불러올 수 없어서 no session오류가 발생하는 것이다.

 

해결

Fetch 전략을 EAGER로 바꿔주어서 해결이 가능하다. User를 가져올 때 Image필드가 바로 채워지게 되므로 프록시객체가 아닌 실제값이므로 에러가 발생하지 않게 된다. 즉시 로딩으로 설정하면 성능 튜닝이 어려워 진다는 단점이 있기 때문에 User의 images를 지연 로딩으로 바꾼 다음, 서비스 계층에서 트랜잭션이 끝나기 전에 이미지에 대한 프록시 초기화를 진행해도 동일하게 해결할 수 있다.

로그가 잘 뜬 모습이다.

 

728x90

댓글