230315 TIL #33 fetchType=EAGER 문제 / UserDetails와 영속성 컨텍스트

김춘복·2023년 3월 15일
0

TIL : Today I Learned

목록 보기
33/543
post-custom-banner

230315 Today I Learned

Spring 3주차. Lv.5과제에 추가기능을 구현했다. 회원탈퇴, 대댓글 기능을 구현했는데 일단은 무한 대댓글이 아닌 글-댓글-대댓글 정도의 계층까지만 구현했다. 구현까지는 쉬웠지만 그후 순환에러가 다시 발생했다. 해당 문제에 대해 정리해보려 한다.


fetchType=EAGER

  • 문제 : 대댓글 기능을 구현한 후, 대댓글을 달면 대댓글의 갯수만큼 댓글이 PostResponseDto에서 늘어난다. 물리적 DB 테이블에서는 문제가 없었지만 로그로 찍어보니
    @OneToMany로 달아둔 Post의 List<Comment> 에서 대댓글의 갯수만큼 댓글이 늘어나는 현상이 있었다.

  • 시도 : 일단 댓글작성이나 대댓글 작성시 생성자에 양방향으로 값을 주는 것 때문이라 판단하여 양방향으로 주는 코드를 없에 봤지만 해결되지 않았다.
    양방향 연관관계를 끊고 단방향으로 시도해보려 했으나 Dto에서 Repository를 불러와 다시 정렬하는 것은 원하던 구현 방향이 아니라 시도하지 않았다.

  • 해결 : 여러 방법을 시도하던 중 Post에서 @OneToMany로 받은 리스트의 fetchtype을 EAGER에서 LAZY로 바꿨더니 해결되었다.

    @OneToMany(mappedBy = "post", fetch = FetchType.LAZY)
    private List<Comment> commentList = new ArrayList<>();
  • 알게된 점 : 무턱대고 fetchtype=EAGER로 설정하는 것은 위와같은 문제가 발생할 수 있다.

UserDetails

  • Spring Security를 적용하고 프로젝트 내에서 여러 문제가 터졌었다. TIL #31에 터진 문제들이다. 오늘 UserDetails에 대해 좀 더 공부하면서 진짜 원인을 찾았다.


그림 출처

  • UserDetails는 영속성 컨텍스트 밖에 존재한다. Filter단에서 Authentication 인증 객체를 만드는 과정에서 생성된다. 반면 영속성 컨텍스트는 컨트롤러의 안쪽, 즉 서비스부터 서비스까지가 범위인데 UserDetails는 컨트롤러의 밖, 필터에서 나온 객체이다.

  • 지연로딩 문제는 컨트롤러에서 UserDetails.getUser()로 서비스에 User 값을 넣어줬기 때문에 발생한 문제이다. 영속성 컨텍스트는 여기서 User를 뽑아 내면 지연로딩으로 처리 된 상태에서는 진짜 객체를 불러오지 못하고 proxy객체만 줄 수 있다. 그러므로 양쪽에 넣는 값을 지우던가, 아니면 UserDetails.getUser().getId()로 User를 Repository에서 새로 찾아서 넣어주면 된다.

  • 동일한 유저로 인식불가문제는 UserDetails.getUser()와 User가 내부에 담고있는 값은 같더라도 실제로는 주소값이 다른 객체이기 때문이다.
    .equals()는 @Override로 재정의 하지 않으면 오직 자기자신만 같다고 인식한다. 그래서 .equals()와 .hashcode()를 재정의해서 쓰던가(참고사이트), id끼리 비교하면 된다. 후자로 해도 검증절차에는 이상이 없다.

  • 그리고 지금까지 User로 객체를 만들어써왔기때문에 너무 당연시하게 썼었는데, User 객체는 만들어 쓴거지 자바나 스프링에서 기본제공하는 개념이 아니다. UserDetails는 아래와 같이 User 말고 다른방식으로도 구현이 가능하다.

public class CustomUserDetails implements UserDetails {
    
    private String ID;
    private String PASSWORD;
    private String AUTHORITY;
    private boolean ENABLED;
    private String NAME;
profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글