반응형
<문제가 일어날 수 있는 상황>
GET /add로 상품 등록 폼을 얻고, 데이터를 입력한 뒤 상품 저장 버튼을 누르면
POST /add로 데이터를 전송함. 이 상태에서 새로고침을 누른다면?
가장 최근 전송인 POST /add를 다시 보내게 되면서 동일 데이터(id만 다른)가 계속 쌓이게 됨
이것의 해결법으로 상품 저장 클릭 시 뷰 템플릿을 호출하는게 아니라
상품 상세 화면으로 리다이렉트를 호출해주면 된다.
v1. 리턴값으로 "redirect:/..."를 넘기면 된다.
@PostMapping("/add")
public String addItemV5(Item item) {
itemRepository.save(item);
return "redirect:/basic/items/" + item.getId();
}
근데 반환값을 잘 살펴보면 +item.getId() 처럼 URL에 변수를 더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험하다.
v2. RedirectAttributes 사용하기
RedirectAttributes를 사용하면 URL 인코딩도 해주고, pathVariable, 쿼리 파라미터까지 처리해준다.
redirect:/basic/items/{itemId}
- pathVariable 바인딩: {itemId}
- 나머지는 쿼리 파라미터로 처리: ?status=true
@PostMapping("/add")
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true); // 쿼리 파라미터로 들어감
return "redirect:/basic/items/{itemId}";
}
결론적으로 다음 주소가 된다. http://localhost:8080/basic/items/3?status=true
등록한 쿼리 파라미터는 아래와 같이 사용할 수 있다.
* 아래의 param은 관용어다. 쿼리 파라미터를 쉽게 조회할 수 있다.
<h2 th:if="${param.status}" th:text="'저장 완료!'"></h2>
-----------------------
참고 : 인프런 김영한님 강의(스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술)
댓글