오봉이와 함께하는 개발 블로그
스프링 MVC 1 - PRG(Post/Redirect/Get), RedirectAttribute 본문
PRG Post/Redirect/Get
/**
* @ModelAttribute 자체 생략 가능
* model.addAttribute(item) 자동 추가
* */
@PostMapping("/add")
public String addItemV4(Item item) {
itemRepository.save(item);
return "basic/item";
}
해당 컨트롤러는 심각한 문제가 있다.
등록을 완료하고 새로고침을 클릭하면 계속해서 중복 등록되는 것을 확인할 수 있다.
전체 흐름
- 상품 목록에서 상품 등록 폼으로 이동
- 등록 폼에서 저장을 누르면 저장이 되며 상품 저장 컨트롤러가 상품 상세 뷰를 호출
- URL은 상품 저장 URL이 남아 있다.
- 새로고침 하면 상품 저장 URL이 그대로 입력됨
- 중복 등록
POST 등록 후 새로 고침
- 클라이언트가 상품 등록 폼 요청
- 서버는 응답해서 상품 등록 폼을 보여줌
- 폼에 값 입력
- 상품 등록 버튼 클릭
- POST로 서버에 넘어가서 상품 저장 컨트롤러가 받아서 로직 처리
- 컨트롤러의 로직이 상품 상세를 반환하기 때문에 상품 상세를 보여줌
- 하지만 URL은 상품 저장 URL 그대로기 때문에 새로고침을 누르면 전에 3번 4번이 생략되며 값은 유지되고, 5번 6번이 그대로 다시 요청됨
이 문제를 어떻게 해결할 수 있을까?
POST, Redirect GET
웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송한다.
상품 저장이 이뤄지면 반환 값을 Redirect를 통해 브라우저 입장에서 서버에 뷰를 새로 요청하도록 하는 방법을 통해 해결할 수 있다.
마지막에 서버에 뷰를 새로 요청해서 받은 것이 상품 상세에 대한 뷰이기 때문에 새로고침을 해도 상품 상세에 대한 뷰를 요청하게 된다.
@PostMapping("/add")
public String addItemV5(@ModelAttribute("item") Item item,
Model model) {
itemRepository.save(item);
model.addAttribute("item", item);
return "redirect:/basic/items/" + item.getId();
}
주의
"redirect:/basic/items/" + item.getId()
redirect에서 +item.getId()
처럼 URL에 변수를 더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험하다.RedirectAttributes
를 사용하자.
RedirectAttributes
BasicItemController에 추가
/**
* RedirectAttributes
*/
@PostMapping("/add")
public String addItemV6(@ModelAttribute("item") Item item, Model model, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
model.addAttribute("item", item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
redirectAttributes.addAttribute("itemId", savedItem.getId());
를 통해서 반환할 때 값을 사용할 수 있게 되었다.return "redirect:/basic/items/{itemId}";
savedItem.getId()
를 문자열 itemId
라고 명시하고 반환값에서 {itemId}
라고 사용했다. 결과적으로 보면 PathVariable
의 효과를 얻었다.
redirectAttributes.addAttribute("status", true);
는 해당 컨트롤러에서 사용하지 않았기 때문에 쿼리 파라미터로 처리된다.
실제 값을 추가하고 redirect된 링크를 보면 아래와 같다.http://localhost:8080/basic/items/3?status=true
출처 : 인프런 김영한 지식 공유자님 강의 - 스프링 MVC 1편 백엔드 웹 개발 핵심 기술
'BE > Spring' 카테고리의 다른 글
스프링 MVC 2 - 스프링 메시지 소스 설정 (0) | 2022.08.18 |
---|---|
스프링 MVC 2 - 메시지, 국제화 (0) | 2022.08.18 |
스프링 MVC 1 - @ModelAttribute (0) | 2022.08.15 |
스프링 MVC 1 - 요청 매핑 핸들러 어탭터 구조 (0) | 2022.08.15 |
스프링 MVC 1 - HTTP 메시지 컨버터 (0) | 2022.08.15 |