Spring 3주차. Lv.4 과제를 진행중이다. 기존의 프로젝트에 Spring Security를 적용하는 과제중인데 예상치 못한 곳에서 에러가 떠서 막혔다. 기존에는 없었던 에러인데 Security 적용을 하니 에러가 발생했다. 이에 대해 정리해보겠다.
문제점 : 글, 댓글 작성시 failed to lazily initialize a collection of role: com.sparta.blogpostspring.entity.User.commentList, could not initialize proxy - no Session 에러가 뜬다.
시도 : @OneToMany로 설정된 Entity의 컬럼들을 지연로딩에서 Fetch Type EAGER로 바꾸니 해결 되었다. 하지만 이 방법은 근본적인 해결방법이 아니고, 성능을 위해 LAZY가 더 합리적이니, 다른 방법으로 고치는 것을 생각해보자.
해결 : 테스트해보니 연관관계의 주인에서 발생할 수 있는 문제를 잡기위해 양쪽으로 값을 넣어주려던 것이 @Transactional때문에 lazy상태에서 실행되어 발생한 문제였다.
public Post(PostRequestDto postRequestDto, User user) {
this.title = postRequestDto.getTitle();
this.content = postRequestDto.getContent();
this.user = user;
user.getPostList().add(this); // 여기가 문제
}
어차피 Post는 연관관계의 주인이니 양쪽에 넣을 필요까지는 없다. 그래서 아직 딱히 사용처가 없는 @OneToMany들을 지우던가, 아니면 문제가 생긴 양쪽에 값을 넣는 코드를 지우면 해결된다.
if (!user.equals(post.getUser())) {
throw new IllegalArgumentException("작성자만 수정할 수 있습니다.");
}
하지만 Security Filter를 통해 불러온 User가 제대로 인식되지 않아 일치 여부를 제대로 판별하지 못하고 있다. 막상 System.out으로 찍어보면 둘이 같게 나오는데 왜 equals로 비교하면 다르게 나오는지 아직 모르겠다.
시도 : !.equals를 !=로 바꿔서 시도해봤으나 실패.
일단은 찍어보면 둘이 같게 나오니 객체끼리 직접 비교가 아니라 객체의 id를 뽑아서 비교하게 해봤다.
해결 :
if (!user.getId().equals(post.getUser().getId())) {
throw new IllegalArgumentException("작성자만 수정할 수 있습니다.");
}
이렇게 하니 정상적으로 작동 되었다.
그런데 Spring Security를 적용하기 전엔 User객체끼리 비교해도 비교가 잘 되었는데, Security적용 후 UserDetails에서 .getUser()로 User를 Service에 넣어주는 방식으로 하니 갑자기 비교가 안되었다. 같은 객체인데 왜그러지? 이 부분은 좀 더 공부해봐야겠다.
TIL #33에 정리해두었다.