1 분 소요

문제 발생 상황

회원탈퇴 기능 구현 중에 발생했는데, Controller 클래스에서 현재 이용중인 유저 정보를 알기 위해서 항상 파라미터로 @AuthenticationPrincipal PrincipalDetails principalDetails을 추가해왔다. 그렇게 유저 정보가 필요하면 principalDetails.getUser()를 써왔는데, 회원탈퇴 버튼을 눌렀을 때 Controller에 Delete request가 들어오면 매핑돼 있는 함수가 실행되면서 현재 유저를 principalDetails.getUser()로 받고 해당 유저에 @OneToMany로 연관돼있는 postsnotifications를 가져와야 했는데, 다 지연 로딩으로 설정돼 있다보니 실제 값이 넘어오질 않고 proxy만 있어서 에러가 발생했다. 당시에 아예 모든 관계를 지연 로딩으로 설정해준 뒤였기 때문에(사실 @OneToMany는 기본값이 지연로딩이지만) fetch join이 걸리지 않은게 있는지 열심히 찾아봤었던 기억이 난다. 현재 유저의 id 값만 받아와 UserRepository.findOneById()로 유저 정보를 가져오면 되지 않을까 싶어 시도 해봤지만 해결되지 않았다.

could not initialize proxy - no Session


해결

왜 no Session 에러가 뜨는걸까? 회원탈퇴처럼 회원 탈퇴 이전에 연관된 모든 정보를 지우는 작업(즉, 수정하는 작업)을 할 때는 반드시 영속성 컨텍스트 내부에서 진행해야 한다. Controller에서 어떤 유저에 대해 정보를 수정하는 작업을 하는 경우 해당 유저는 더 이상 영속성 컨텍스트 내에서 관리되지 않기 때문에 준영속 상태다. 수정 작업이 진행되는 Service 클래스 내 함수들은 모두 @Transactional을 설정해 두었는데, 해당 함수 내에서 어떤 entity의 값을 수정할 경우 굳이 DB로 직접 쿼리를 날리지 않아도 변경 감지를 통해 알아서 업데이트 쿼리를 날려주는걸 경험해봤을 것이다. 그 이유가 영속성 컨텍스트 내에서 관리되는, 영속 상태인 entity에 대해서 값을 수정했기 때문이다. 즉, @Transactional이 붙어있는 함수는 호출된 시점부터 끝날 때 까지의 내용이 모두 transaction 내부에서 처리되는 작업으로 간주한다.

그러니까 Controller 내에서 변경 작업이 필요한 내용들을 처리하지 말고, Service의 @Transactioal이 붙은 함수 내에서 처리해주면 해결된다.

카테고리:

업데이트:

댓글남기기