loadByUsername에서의 트러블 슈팅
JWT와 Redis를 이용한 클라이언트의 로그아웃 로직을 구현하던 도중 발생한 트러블이다.
간단하게 클라이언트가 로그아웃 요청을 보낼 경우 해당 클라이언트의 Header에서 AccessToken을 받아와 토큰을 이용해 RefreshToken을 블랙리스트에 등록하는 로직이다.
로그아웃 로직이 완성됐다고 생각하고 포스트맨으로 실행시켰을때
위의 사진에서 볼 수 있듯 500 서버에러가 발생하였다. 왜 이런 이유가 발생할까?
에러 로그를 슥 살펴보던 도중 "Member가 UserDetails로 cast 될 수 없다"는 로그를 발견함과 동시에 "loadByUser"쪽에서 문제가 발생한걸 확인해 볼 수 있었다.
이게 그 문제의 loadByUsername 메서드이다.
코드를 쓱 봤을때는 마지막에 (UserDetails)를 이용하여 캐스팅 해주는거로 보여서 구현시에는 별 문제 없어보였다.
하지만 잘 생각해보니 findByEmail의 경우 Return type이 Optional인걸 생각하지 못했다.
Optional은 객체를 감싸는 래퍼 클래스이므로 캐스팅 자체가 안된다. 더군다나 나는 PrincipalDetails를 사용하여 UserDetails를 구현한걸 간과하고 있었다. (아무생각 없이 코딩하면 안된다.)
따라서 위와 같이 stream을 이용하여 findByEmail의 리턴값이 존재하는 경우 UserDetails의 구현체인 PrincipalDetails를 리턴하게 해주었고 로그아웃 로직이 성공적으로 동작하는걸 볼 수 있었다.
아무리봐도 stream과 lambda는 너무 편하다 👍
정신차리고 코딩하자 🧑💻