로그인 페이지에서 로그인 버튼을 누르면 다음과 같은 에러가 등장하였다.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Feb 14 22:03:50 KST 2023
There was an unexpected error (type=Internal Server Error, status=500).
Cannot call sendRedirect() after the response has been committed
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
@Controller
@RequiredArgsConstructor
@Slf4j
public class UserController {
...
// 로그인
@GetMapping("/users/login")
public String loginForm(Model model) {
model.addAttribute("userLoginReqDto", new UserLoginReqDto());
return "user/loginForm";
}
@PostMapping("/users/login")
public String login(@Valid @ModelAttribute UserLoginReqDto userLoginReqDto, BindingResult result,
HttpServletResponse response){
if (result.hasErrors()) {
return "user/loginForm";
}
try {
String token = userService.login(userLoginReqDto.getUserName(), userLoginReqDto.getPassword());
CookieGenerator cookieGenerator = new CookieGenerator();
cookieGenerator.setCookieName("token");
cookieGenerator.setCookieHttpOnly(true);
cookieGenerator.addCookie(response, token);
cookieGenerator.setCookieMaxAge(60 * 60 * 2);
} catch (AppException e) {
return "user/loginForm";
}
return "redirect:/";
}
...
}
로그인 할 때, 헤더에 토큰을 담아서 로그인 상태를 유지하려고 했었다. 헤더에 토큰 값을 포함하여 전달해야 하기 때문에 Post 방식의 로그인 메서드는 마지막에 "redirect:/"로 return 하도록 한 것이다.

response 객체에서 제공하는 sendRedirect() 메소드는 응답 객체가 가진 헤더 정보에 클라이언트가 다음번에 어디로 갈지를 지정해주는 것이지 포워딩처럼 제어 흐름을 다른 곳으로 넘기는 방식이 아닌 것이다. 따라서 sendRedirect() 메소드가 실행된 이후의 코드 또한 계속 실행시키게 된다.
즉, sendRedirect()는 바로 페이지를 넘기는 것이 아니라 모든 로직을 수행한 뒤 페이지가 넘어가도록 하는 것이다.
그래서 모든 로직이 시작된 후에 redirect:/”url”을 진행해야 한다.
if (조건절) {
...
return "redirect:/home";
} else {
...
return "redirect:/index"
}
위와같이 할경우 실제로 코드는 그대로 수행되면서 리턴 후 서블릿으로 제어권이 돌아오기 때문에 리다이렉트를 두 번 중복으로 수행하는 셈이 되버리는 것이다.
위처럼 if/else 구문으로 return "redirect"한 것도 아닌데 왜 나는 redirect가 1번이 아니라 2번 혹은 그 이상이 호출되어 저런 오류가 뜬 것일까?
해결 방안은 바로 페이지를 두번 호출한다.. 에 있었다.
스프링 시큐리티에서 필터체인에서 확인 후에 오류가 있다면 return해서 메서드를 종료시켜야하는데, return을 안해주어서 페이지가 두번 호출이 되는 것이다.
즉, 한 페이지에 같은 내용의 html이 2개가 되었고, 이는 컨트롤러가 2번 호출된다는 것이다. 로그인 버튼 1번을 클릭해도 2번의 클릭으로 인식하게 되었고, redirect가 2번 호출되어 나타나는 에러였다.