[Servlet&JSP] HttpServletRequest forward, 새로고침 문제

2022. 1. 19. 18:21문제해결

Servlet&JSP 기반으로 회원가입 서비스를 구현하던 중이였습니다. 

회원가입 서비스의 수행과정은 성명과 이메일, 비밀번호 등을 입력하고 회원가입을 요청합니다. 회원가입에 성공하면 홈 화면으로 이동합니다. 하지만 문제는 회원가입의 경우 중복된 이메일이나 비밀번호와 비밀번호 확인 서로 다르다면 회원가입에 실패하게 됩니다.

 

이때 회원가입에 실패하게 되면 다시 회원가입 페이지로 이동하게 되고 회원가입에 실패한 이유를 자바스크립트 언어의 alert 함수를 통하여 알려줍니다. 아래의 알림에서 확인을 클릭하면 회원가입 화면으로 다시 이동합니다.

 

하지만 문제는 회원가입에 한번 실패한 상태에서 새로고침을 누르게 되면 "회원가입 실패 사유 알림"이 다시 나온다는 점입니다.

 

회원가입 실패 사유를 알려주는 자바스크립트 코드는 다음과 같습니다. (signUp.jsp)

        <c:if test="${not empty signUpResult}">
        	<script>alert("${signUpResult}");</script>
        </c:if>

위와 같이 signUpResult이라는 request 속성에 회원가입 실패 사유를 저장하고 signUpResult이 비어있지 않다는 것은 회원가입이 실패했기 때문에 회원가입 실패 사유를 알려달라는 의미입니다.

 

다음 코드는 회원가입 서블릿 컨트롤러(SignUpServlet.java) 코드입니다.

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
		initLibrarys(request);
		request.getRequestDispatcher("/views/member/signUp.jsp").forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");

		initLibrarys(request);
		
		String mem_name = request.getParameter("name");
		String mem_email = request.getParameter("email");
		String mem_pwd = request.getParameter("password");
		String mem_confirm_pwd = request.getParameter("confirm_password");
		String lib_regi_name = request.getParameter("library_name");
		
		MemberSignUpVO member = new MemberSignUpVO(mem_name, mem_email, mem_pwd, mem_confirm_pwd, lib_regi_name);
		
		RequestDispatcher dispather = request.getRequestDispatcher("/views/member/signUp.jsp");
		try {
			if(mem_pwd.equals(mem_confirm_pwd))
			{
				int result = MemberDAO.signUp(member);
				if(result==-1)
				{
					request.setAttribute("signUpResult","중복된 이메일이 존재합니다.");
				}
				else
				{
					response.sendRedirect("/Library/home");
				}
			}
			else
			{
				request.setAttribute("signUpResult", "비밀번호가 불일치합니다.");
			}	
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			dispather.forward(request, response);
		}	
	}

회원가입에 성공하면 sendRedirect를 호출하여 홈화면으로 이동하고 회원가입 실패하면 signUpResult 속성에 회원가입 실패 사유를 저장하고 forward하는 흐름입니다.

 

회원가입에 한번 실패한 후 새로고침을 누르게 되면 회원가입 서블릿 컨틀롤러의 doPost가 다시 수행하게 되어 회원가입을 시도하게 됩니다. 그리고 알림이 발생합니다.

 

따라서 위 문제를 해결하기 위해 기존 signUpResult 속성을 request 저장소가 아닌 세션(HttpSession)에 저장하기로 하였고 forward 전송이 아닌 sendRedirect 전송으로 변경하였습니다.

 

sendRedirect 전송을 하게 되면 doGet으로 호출되기 때문에 회원가입에 실패를 한 후 새로고침을 하게되면 여전히 signUpResult 속성이 세션에 남아있기 때문에 플래그 변수를 하나더 저장하여 세션을 지우기로 하였습니다.

 

아래의 소스코드는 문제를 해결한 코드입니다.

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {	
		initLibrarys(request);

		// 기존 회원가입 시도 실패한 기록이 존재하면 삭제함
		HttpSession session = request.getSession();
		if(session.getAttribute("signUpResult")!=null && 
				!((Boolean) session.getAttribute("isFailSignUp")).booleanValue())
		{
			session.removeAttribute("signUpResult");
		}
		else
		{
			session.setAttribute("isFailSignUp", false);
		}
		
		request.getRequestDispatcher("/views/member/signUp.jsp").forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		
		initLibrarys(request);
		
		String mem_name = request.getParameter("name");
		String mem_email = request.getParameter("email");
		String mem_pwd = request.getParameter("password");
		String mem_confirm_pwd = request.getParameter("confirm_password");
		String lib_regi_name = request.getParameter("library_name");
		
		MemberSignUpVO member = new MemberSignUpVO(mem_name, mem_email, mem_pwd, mem_confirm_pwd, lib_regi_name);
		HttpSession session = request.getSession();
		
		try {
			if(mem_pwd.equals(mem_confirm_pwd))
			{
				int result = MemberDAO.signUp(member);
				if(result==-1)
				{
					session.setAttribute("signUpResult","중복된 이메일이 존재합니다.");					
				}
				else
				{
					response.sendRedirect("/Library/home");
				}
			}
			else
			{
				session.setAttribute("signUpResult", "비밀번호가 불일치합니다.");
			}	
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			session.setAttribute("isFailSignUp", true);	// 회원가입에 실패함
			response.sendRedirect("/Library/home/signUp");
		}	
	}

위와 같이 수정하여 새로고침을 하여도 더이상 알림이 오지 않게 되었습니다.

 

References

source code : https://github.com/yonghwankim-dev/library