로컬에서 테스트 할 때 전혀 문제없던 로그인 기능이 AWS에 배포하고 나서는 작동하지 않았다. 클라이언트에서는 404도 아닌 아예 응답이 오지않는다는 에러 로그를 확인했고 Postman으로 테스트 시 신기하게 요청 도메인이 127.0.0.1, 로컬 호스트와 연결할 수 없다는 에러가 발생했다. 로컬에서 서버를 실행하고 Postman으로 요청을 보내면 로컬로 요청이 와서 에러가 발생하지 않았다.
Redis가 문제인가 싶어 테스트용 컨트롤러를 만들어서 테스트해봤더니 잘되었다. 로그인 수행은 정상적으로 되는것을 로그를 통해 확인했으니 어딘가 로컬 환경으로 요청을 보내는 부분이 있을 거라 생각하고 스프링 시큐리티의 로그인 과정을 다시 살펴보면서 수상적은 부분을 발견했다. 바로 response.sendRedirect()이다
// 문제의 코드
@Component
class CustomAuthenticationFailureHandler : AuthenticationFailureHandler{
override fun onAuthenticationFailure(
request: HttpServletRequest?,
response: HttpServletResponse?,
exception: AuthenticationException?
) {
println(exception?.message)
response?.sendRedirect("http://localhost:8080/api/login/fail")
}
}
로그인을 구현하면서 스프링 시큐리티가 제공하는 로그인 전략을 사용하다보니 필터 레벨에서 요청을 JWT 토큰을 담아 클라이언트에 전달했어야 했는데 서블릿 Req, Res는 잘 알지 않아, 토큰을 반환하는 컨트롤러를 만들고 response.sendRedirect() 를 통해 생성된 토큰을 쿼리에 담아 컨트롤러로 리다이렉트했다. 문제는 sendRedirect 메소드는 클라이언트에 리다이렉트 주소를 전달한 다음 다시 서버에 요청하는 방식으로 동작한다는 것이였다.
즉, 바로 서버내 요청 처리 컨트롤러로 전달되는 것이 아니라 클라이언트에서 해당 요청을 받고 다시 전달하기 때문에 localhost는 EC2 서버가 아닌 클라이언트의 도메인을 의미하게 되어 로컬로 요청이 전달된 것이다.
결국 localhost로 되어 있는 부분을 EC2 서버의 IP 주소로 변경하는 것으로 문제를 해결하였다. 이 문제로 여러가지 많은 방법을 시도해봤으나 결국 어느정도 서블릿에 대한 공부가 좀 더 필요하다고 생각되었다.