SpringFramework/BASIC

스프링의 redirect 와 RedirectAttribute

유혁스쿨 2020. 8. 30. 03:45
728x90
반응형

redirect: 뷰리졸버에 보내는 방식은 기본적으로는 forwarding 처리가 되있습니다.

가끔 때로는 redirect처리를 해야할 때가 있습니다.
예를들어 글쓰기 요청이 끝난 후에 바로 글목록 페이지가 떠야합니다. 
바로 글목록페이지로 연결 해버리면 글목록을 띄우기위해서는 다시한번 DB에 접근해야합니다.
select문을 돌린 후 insert된 게시물목록을 포함한 새롭게 목록이 갱신된 게시물목록을 가져와야합닌다.
그렇다면 요청을 두번보내야 한다는것입니다.
첫번째 요청은 insert 요청으로 게시물을 추가하는 처리를 해야하는 메서드 이후에 
두번째 요청은 select 요청으로 insert요청으로 추가한 게시글을 포함한 
새로운 목록을 갱신하여 가져오도록 처리하는 메서드로 요청을 한번 더 보내주는 것 입니다.
 
글 삭제요청도 같습니다.
delete요청을 보낸다음 DB에서 게시글을 지워버리고 삭제가 완료된 이후에 다시 글목록을 보여줄 때는
삭제된 새로운 게시글 목록을 다시한번 DB를통해 수행해와야합니다.
이럴때 다시한번 sendRedirect로 자동 재 요청을 보낸후 삭제가 갱신된 목록을 들고와야합니다.

지금까지 배운 방식은 다 forwarding이므로 한번의 요청만 해결을 해 버리는것 이고
요청이 두번들어가야 할 때가 있다는것입니다.

입력후 목록요청
입력 후 입력된것을 적용한 목록 요청 
삭제후 목록요청
삭제 후 삭제된것을 적용한 목록 요청


SendRedirect : jsp서블릿에서는 response객체를 사용해서 response.sendRedirect()를 했다면
스프링에서도 그것을 똑같이 적용할 수 있습니다.
하지만 스프링은 스프링만의 조금 더 편한 방식의 API 기능이 내장되어있습니다.

 


리다이렉트할때 데이터를 화면쪽으로 옴겨주는법

 

요청폼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%-- ResponseController 사용 --%>
<form method="post">
<p>
	# ID : <input type="text" name="userId" size=10/> <br />
	# PW : <input type="password" name="userPw" size=10/> <br />
	# PChk : <input type="password" name="userPwChk" size=10/> <br />
	<input type="submit" value="확인" />
</p>
</form>
<p style="color:red;">${msg}</p>
</body>
</html>

응답폼

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	""로그인 성공" "(${user.userId}) 님 환영합니다"
</body>
</html>

VO클래스

public class UserVO {
	private String userId;
	private String userPw;

		public String getUserId() {
			return userId;
		}
		public void setUserId(String userId) {
			System.out.println("setUserId() 호출");
			this.userId = userId;
		}
		public String getUserPw() {
			return userPw;
		}
		public void setUserPw(String userPw) {
			System.out.println("setUserPw() 호출");
			this.userPw = userPw;
		}
	
}

 

Redirect 처리에서는 Model도 requset범위와 같습니다.
기본적으로 요청을 할때에는 request요청객체를 생성합니다.
redirect는 기본적으로 요청을 하고 응답을받으면 다시 한번 더 재요청을 하게되어 총 두번의 요청을 하게 됩니다.
즉, 첫번 요청객체를 만들고 응답을받게되면 재요청을할때 첫번째 요청객체는 
서버에서 삭제되고 새로운 재요청에대한 요청객체를 다시만들어 요청을합니다.

@Controller
public class RedirectController {
	@PostMapping("/login")
	public String login(@ModelAttribute("userId") String id	, @RequestParam("userPw") String pw
   		, @RequestParam("userPwChk") String pwChk , HttpServletResponse response , Model model
    		, HttpSession session, RedirectAttributes r) throws IOException {
		
		System.out.println("/login : POST요청 발생!");
		System.out.println("id:"+id);
		System.out.println("pw:"+pw);
		System.out.println("pw:"+pwChk);
        
		if(id.equals("")) {//아이디를 널문자로 받았다면
			model.addAttribute("msg","아이디는 필수값 입니다!");
			response.sendRedirect("login");//재요청을 해 줍니다.
		}else if(!pw.equals(pwChk)) {
			model.addAttribute("msg","비밀번호 확인 란을 체크하세요!");
			return "redirect:/response/login";//sendRedirect()와 같은 스프링 방식의 재요청 기능
		}else if(id.equals("abc123")&&pw.equals("1234")) {
			System.out.println("로그인 조건일치 로그인완료");
			return "response/res-quiz-success";
		}else {
			return null;
		}
		return null; // if문에서 response를 사용? 했기 때문에 오류가뜹니다
	}
}


Model에 Data를 Attribute 해놓으면 이것은 request영역 에서만 작동합니 됩니다.
재요청을하면 이 데이터가 없어진다는것입니다.

redirect할때만 어떤 데이터를 페이지쪽으로 보내줄 수는 없을까? 

Session과 RedirectAttribute 

 

Session

@Controller
public class RedirectController {
	@PostMapping("/login")
	public String login(@ModelAttribute("userId") String id	, @RequestParam("userPw") String pw
   		, @RequestParam("userPwChk") String pwChk , HttpServletResponse response , Model model
    		, HttpSession session, RedirectAttributes r) throws IOException {
		
		System.out.println("/login : POST요청 발생!");
		System.out.println("id:"+id);
		System.out.println("pw:"+pw);
		System.out.println("pw:"+pwChk);
        
		if(id.equals("")) {
			session.setAttribute("msg","아이디는 필수값 입니다!");
			return "redirect:/response/login";
		}else if(!pw.equals(pwChk)) {
			session.setAttribute("msg","비밀번호 확인 란을 체크하세요!");
			return "redirect:/response/login";
		}else if(id.equals("abc123")&&pw.equals("1234")) {
			System.out.println("로그인 조건일치 로그인완료");
			return "response/res-quiz-success";
		}else {
			return null;
		}
	}
}


Session은 redirect해주면 서버의 브라우저 쿠키에 세션객체만을 담을수 있는 어떤 영역이 존재하고 
그 영역 안에서 객체를 저장하고 있는거죠 그래서 값을 담고있는 객체가 살아있게 됩니다. 
또, 기존의 값이 있더라도 새로운 값을 넣었을때는 새로운 요청을 했기 때문에 
그 새로운 요청에 대한 값으로 바뀌어서 해당 요청으로 넘어가게 되는겁니다.  
session객체는 값을 끝까지 유지합니다.

invalidate를 해서 객체를 통으로 비활성화시킨다거나? 아니면 새로운 값을 객체에 넣기 전까지는말이에요. 
세션은 값이 들어올때마다 초기화가 될수도 있다는 말 입니다. (여기까지는 실험안해봤습니다.)

 

RedirectAttribute

@Controller
public class RedirectController {
	@PostMapping("/login")
	public String login(@ModelAttribute("userId") String id	, @RequestParam("userPw") String pw
   		, @RequestParam("userPwChk") String pwChk , HttpServletResponse response , Model model
    		, HttpSession session, RedirectAttributes r) throws IOException {
		
		System.out.println("/login : POST요청 발생!");
		System.out.println("id:"+id);
		System.out.println("pw:"+pw);
		System.out.println("pw:"+pwChk);
        
		if(id.equals("")) {
			r.addFlashAttribute("msg","아이디는 필수값 입니다!");
			return "redirect:/response/login";
		}else if(!pw.equals(pwChk)) {
			r.addFlashAttribute("msg","비밀번호 확인 란을 체크하세요!");
			return "redirect:/response/login";
		}else if(id.equals("abc123")&&pw.equals("1234")) {
			System.out.println("로그인 조건일치 로그인완료");
			return "response/res-quiz-success";
		}else {
			return null;
		}
	}
}


그리고 RedirectAttribute는 1회성 즉, 한번redirect로 전송하고 
세션과 비슷하게 서버의 브라우저 쿠키에 저장은 되지만 세션처럼 전용영역은 아닐거에요. 
그리고 아마 그래서 이건 저장되어 있다가 넘겨받고 사용하는 순간 서버로부터 자동으로 삭제가됩니다!

session의 setAttribute는 새로고침을해도 넘겨받은 메시지가 그대로 남아있게되지만
redirectAttribute의 addFlashAttribute는 새로고침하면 값이 바로 사라집니다.
그래서 이런 새로고침이 각각 다른현상으로 적용되죠

입력갑 검증같은 경우에는 프론트엔드 쪽에서 우리가 자바스크립트를 사용하기도 하지만
추가적으로 서버쪽에  데이터를 순간적으로 담아줄수있다는것이죠.

그리고 리다이렉트어트리뷰트는 게시판을 생성할때 상당히 사용할 일들이 많게됩니다.

 

 

 

SendRedirect와 forward의 개념정리 참조!

https://u-it.tistory.com/21

 

페이지출력, 페이지전환 및 특정 url로 재 요청 을 해주는 RequestDispatcher 의 request.getRequestDispatcher()

# RequestDispatcher서블릿 forward(request, response)메서드 먼저 forward()와 sendRedirect의 개념차이를 아주 쉽게 구분하겠습니다. forward() : 페이지 출력, 페이지 전환 sendRedirect() : 특정 url로 재..

u-it.tistory.com

 

 

 

728x90
반응형