른록노트

[Spring] forward와 redirect란 그리고 RedirectAttributes란? 본문

Web/[Spring]

[Spring] forward와 redirect란 그리고 RedirectAttributes란?

른록 2021. 12. 28. 19:55

1. 문제상황

전자정부 프레임워크 3.10 버전에서 (Spring 4.3.25)
처음에 list.do를 요청하고 searchVO가 유지된 상태에서
test.do를 호출하여 searchVO값을 변경하고 list.do로 forward 할 시 [list:searchVO]에서 값을 확인하면
searchVO가 제대로 변경되지 않는다.

@RequestMapping("test.do")
public String test(@ModelAttribute("searchVO") SearchVO searchVO, Model model) throws Exception {
    searchVO.setText("변경");
    model.addAttribute("searchVO",searchVO);
    System.out.println("[test:searchVO]:"+searchVO.toString());
    result "forward: list.do";
}

@RequestMapping("list.do")
public String list(@ModelAttribute("searchVO") SearchVO searchVO, Model model) throws Exception {
    System.out.println("[list:searchVO]:"+searchVO.toString());
    result "test";
}

결과는 아래와 같다.

[list:searchVO]:{Text:변경안됌}
[test:searchVO]:{Text:변경}
[list:searchVO]:{Text:변경안됌}

어떻게 하면 forward시 @ModelAttribute를 넘겨 줄 수 있을까?

2. forward와 redirect의 차이

jsp 환경에서 현재 작업중인 페이지에서 다른 페이지로 이동하는 두가지 방식의 페이지 전환 기능.

2.1. forward란

The forward: prefix (spring doc)
UrlBasedViewResolver 및 하위 클래스에 의해 궁극적으로 확인되는 view name에 특수 forward: 접두사를 사용할 수도 있습니다.
이렇게 하면 URL로 간주되는 나머지 view name 주위에 InternalResourceView(궁극적으로 RequestDispatcher.forward()를 수행함)가 생성됩니다.
따라서 이 접두사는 InternalResourceViewResolver 및 InternalResourceView(예: JSP의 경우)에는 유용하지 않습니다. 그러나 접두사는 주로 다른 view 기술을 사용하지만 Servlet/JSP 엔진이 처리하도록 리소스를 강제로 전달하려는 경우에 유용할 수 있습니다.(대신 여러 뷰 리졸버를 연결할 수도 있습니다.)

redirect: 접두사와 마찬가지로 forward: 접두사가 있는 view name이 컨트롤러에 주입되면 컨트롤러는 응답 처리 측면에서 특별한 일이 발생하는 것을 감지하지 못합니다.


Forward란 (blog 글)
Web Container 차원에서 페이지 이동만 있다. 실제로 웹 브라우저는 다른 페이지로 이동했음을 알 수 없다. 그렇기 때문에, 웹 브라우저에는 최초에 호출한 URL이 표시되고 이동한 페이지의 URL 정보는 볼 수 없다. 동일한 웹 컨테이너에 있는 페이지로만 이동할 수 있다.

현재 실행중인 페이지와 forward에 의해 호출될 페이지는 request와 response 객체를 공유한다.

2.2. Redirect란

The redirect: prefix (spring doc)
RedirectView의 사용은 잘 작동하지만 컨트롤러 자체가 RedirectView를 생성하는 경우 컨트롤러가 리디렉션이 발생하고 있음을 인식한다는 사실을 피할 수 없습니다. 이것은 정말 차선책이며 너무 밀접하게 연결됩니다. 컨트롤러는 응답이 처리되는 방식에 대해 크게 신경 쓰지 않아야 합니다. 일반적으로 삽입된 뷰 이름에 대해서만 작동해야 합니다.

특수 redirect: 접두사를 사용하면 이를 수행할 수 있습니다. redirect: 접두사가 있는 view name이 반환되면 UrlBasedViewResolver(및 모든 하위 클래스)는 이를 리디렉션이 필요하다는 특별한 표시로 인식합니다. 나머지 view name은 리디렉션 URL로 처리됩니다.

순 효과는 컨트롤러가 RedirectView를 반환한 것과 같지만 이제 컨트롤러 자체는 논리적 view name으로 간단히 작동할 수 있습니다. redirect:/myapp/some/resource와 같은 논리적 보기 이름은 현재 서블릿 컨텍스트를 기준으로 리디렉션되는 반면, redirect:http://myhost.com/some/arbitrary/path와 같은 이름은 절대 URL로 리디렉션됩니다.


Redirect란 (blog 글)
Web Container는 Redirect 명령이 들어오면 웹 브라우저에게 다른 페이지로 이동하라고 명령을 내린다. 그러면 웹 브라우저는 URL을 지시된 주소로 바꾸고 그 주소로 이동한다. 다른 웹 컨테이너에있는 주소로 이동이 가능하다.

새로운 페이지에서는 request와 response객체가 새롭게 생성된다.

2.3 정리

forward를 사용하면 처음 사용자가 request 요청을 그대로 사용한다. 그래서 forward를 하기전에 request에 있는 ModelAttribute를 변경해줘도 forward를 받는 list 함수는 처음 사용자가 요청한 request를 이용한다. 결국 나는 다른 request 객체를 사용하고 싶으니 redirect를 써야겠다고 생각했다. 그리고 redirect 해줄때 ModelAttribute 값을 넘겨주고 싶어서 RedirectAttributes를 사용하였다.

3. RedirectAttributes

RedirectAttributes란 (spring doc)
컨트롤러가 리디렉션 시나리오의 속성을 선택하는 데 사용할 수 있는 모델 인터페이스의 전문화입니다. 리디렉션 속성을 추가하려는 의도는 매우 명시적입니다. 즉, 리디렉션 URL에 사용하기 위해 속성 값을 문자열로 형식화하고 그런 방식으로 저장하여 쿼리 문자열에 추가하거나 조직에서 URI 변수로 확장할 수 있습니다. org.springframework.web.servlet.view.RedirectView.

이 인터페이스는 플래시 속성을 추가하는 방법도 제공합니다. 플래시 속성에 대한 일반적인 개요는 FlashMap을 참조하십시오. RedirectAttributes를 사용하여 플래시 속성을 저장할 수 있으며 현재 요청의 "output" FlashMap에 자동으로 전파됩니다.

RedirectAttributes 모델은 메서드가 호출될 때 비어 있으며 메서드가 리디렉션 view name 또는 RedirectView를 반환하지 않는 한 사용되지 않습니다. 리디렉션 후 플래시 속성은 대상 URL을 제공하는 컨트롤러 모델에 자동으로 추가됩니다.


RedirectAttributes란 (blog)
폼 형식의 문서를 작성 후, 서버로 보내면(POST 방식) 곧이어 다른 페이지로 리다이렉트한다.
문제는 이러한 리다이렉트 방식이 GET 방식이라 데이터 전송에는 적절하지 않다. 위에 명시적이라고 한 이유가 url에 ? 뒤에 파라미터를 붙혀서 전달하기 때문이다.
이때 스프링은 RedirectAttributes로 세션에 Flash 속성을 복사한다. 리다이렉션 이후에 저장된 플레시 속성을 세션에서 모델로 이동시킨다. 헤더에 파라미터를 붛이지 않기 때문에 URL에 노출되지 않는다. addFlashAttribute() 는 리다이렉트 직전 플래시에 저장하는 메소드다. 리다이렉트 이후에는 소멸한다.

3.1. FlashMap 이란

FlashMap은 한 요청이 다른 요청에서 사용할 속성을 저장하는 방법을 제공합니다. 이것은 한 URL에서 다른 URL로 리디렉션할 때 가장 일반적으로 필요합니다. Post/Redirect/Get 패턴. FlashMap은 리디렉션 전에(일반적으로 세션에) 저장되고 리디렉션 후에 사용할 수 있게 되며 즉시 제거됩니다.

4. 코드 변경

@RequestMapping("test.do")
public String test(RedirectAttributes rttr,@ModelAttribute("searchVO") SearchVO searchVO, Model model) throws Exception {
    searchVO.setText("변경");
    rttr.addFlashAttribute("searchVO",searchVO);
    System.out.println("[test:searchVO]:"+searchVO.toString());
    result "redirect: list.do";
}

@RequestMapping("list.do")
public String list(@ModelAttribute("searchVO") SearchVO searchVO, Model model) throws Exception {
    System.out.println("[list:searchVO]:"+searchVO.toString());
    result "test";
}

참고사이트

Spring 4 document
redirect와 forward의 차이
Spring RedirectAttributes doc
RedirectAttributes란

반응형
Comments