카카오톡 Oauth2.0으로 로그인하는 누군가는 사진 파일이 무조건 존재한다.
하지만 기본 로컬 가입을 했을때 사진이 등록을 선택할 수 있고 이후에 회원 수정 페이지에서 사진을 등록할 수 있다.
사진을 넣지 않은 사람에게는 페이지 사용할 때 페이스북 같은 기본 사진을 보여주고 싶다.
첫번째 문제는, 처음에는 기본 사진을 모든 사람에게 넣어줄까 했다. 하지만 같은 사진에 대한 재사용성이 없기 때문에 새로운 방법을 알아보았다.
두번째 문제는, USER에 사진을 넣었다고 한들 USER 객체 Security 객체로 지연로딩이기 때문에 프록시 객체로 들어오게된다.
Member에 있는 profileImage 지연로딩이니 프록시 객체가 들어오게된다.
프록시 객체가 프록시 객체를 덮고있는 상태가 나와서 오류가 계속해서 발생하게 된다.
한마디로 프록시가 프록시를 감싸고 있는 형태가 나오게되어 안쪽 사진을 로딩이 불가능하다.
비슷한 구현을 하며 같은 오류를 겪는 사람을 찾았지만 이분은 여기서 포기하신 것 같다.
일단은 EAGER로 불러왔을때 안쪽 ProfileImage가 더이상 프록시가 아니기 때문에 이미지를 호출해도 정상적으로 호출이 되었다.
하지만 나는 EAGER로 이미지를 계속 함께 불러오는 것이 성능상 이슈가 있다고 생각한다. 그래서 최대한 EAGER를 지양한다.
LAZY Exception과 Hibernate.initalize()
다양한 쿼리들과 에러를 발생하고 초기화를 USER 객체에게 적용해봤다.
프록시 호출
결국 최종 목적지인 profileImage를 꺼내려면 if문이나 Optional 이 들어있는 다른 메소드를 사용해야했다.(프록시를 호출해서 초기화)
처음에 짠 코드와 다른게 없었다...
나는 Controller 단으로 해당 코드를 올리고 싶지 않다.
왜냐하면 디비에서 불러오는 것은 Repository의 업무지 Controller의 일이 아니라고 생각이 든다.
sql문에서 null일 경우를 처리하는 함수를 최근 sqld에서 본 것 같아서 검색을 해보니 sql에는 coalesce(IFNULL) 이라는 함수를 찾았다.
그러면 과연 jpql에도 있을까?(spring data jpa, querydsl 사용여부)
일단 jpql에는 존재하였고 편하게 이용하고 싶기 때문에 spring data jpa 인터페이스에 적용해보았다.
처음에 spring data jpa 로 @Query 문을 짜는데 interface라서 app.properites에 정의해놓은 값을 가져올 수가 없었다.
(지금 생각해보나 파라미터로 @Value를 받아와서 넣으면 가능하다. 왜 저 당시에는 직접 넣었을까...?)
어차피 조회는 querdsl로 했기때문에 QueryDsl 로 해보면된다!
@Value 로 app.properties에서 이미지url을 받아온 후 coalesce 적용!
이렇게 되면 사진이 없는 유저는 defaultImgUrl , 카카오톡처럼 사진이 있는 유저는 자신의 ImgUrl이 가능하다!
결국 첫번째 방법에서 찝찝하게 여겼던 EAGER를 쓰지 않고 LAZY로 해결하였다.
https://green-joo.tistory.com/22#coalesce-IFNULL-
https://steady-coding.tistory.com/550
https://feco.tistory.com/10
https://everydayyy.tistory.com/84
https://myvelop.tistory.com/69
https://stackoverflow.com/questions/23738869/org-hibernate-hql-internal-ast-querysyntaxexception-invalid-path-1-id
https://jiwondev.tistory.com/245