-
[김영한 스프링] 34. 스프링 MVC 웹 페이지 만들기 - PRG Post/Redirect/GetSpring/스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 2023. 7. 24. 03:51
PRG Post/Redirect/Get
사실 지금까지 진행한 상품 등록 처리 컨트롤러는 심각한 문제가 있다. (addItemV1 ~ addItemV4)
상품 등록을 완료하고 웹 브라우저의 새로고침 버튼을 클릭해 보자.
상품이 계속해서 중복 등록되는 것을 확인할 수 있다.
testC 상품 등록
상품 등록 후 새로고침 하면 중복으로 데이터 생성 됨
전체 흐름
POST 등록 후 새로 고침
웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송한다.
상품 등록 폼에서 데이터를 입력하고 저장을 선택하면 POST /add + 상품 데이터를 서버로 전송한다.
이 상태에서 새로 고침을 또 선택하면 마지막에 전송한 POST /add + 상품 데이터를 서버로 다시 전송하게 된다.
그래서 내용은 같고, ID만 다른 상품 데이터가 계속 쌓이게 된다
POST, Redirect GET
웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송한다.
새로 고침 문제를 해결하려면 상품 저장 후에 뷰 템플릿으로 이동하는 것이 아니라, 상품 상세 화면으로 리다이렉트를 호출해 주면 된다.
웹 브라우저는 리다이렉트의 영향으로 상품 저장 후에 실제 상품 상세 화면으로 다시 이동한다. 따라서 마지막에 호출한 내용이 상품 상세 화면인 GET /items/{id}가 되는 것이다.
이후 새로고침을 해도 상품 상세 화면으로 이동하게 되므로 새로 고침 문제를 해결할 수 있다.
BasicItemController에 추가
@PostMapping("/add") public String addItemV5(Item item) { itemRepository.save(item); return "redirect:/basic/items/" + item.getId(); }
상품 등록 처리 이후에 뷰 템플릿이 아니라 상품 상세 화면으로 리다이렉트 하도록 코드를 작성해 보자.
이런 문제 해결 방식을 PRG Post/Redirect/Get라 한다.
주의
"redirect:/basic/items/" + item.getId() redirect에서 +item.getId()처럼 URL에 변수를 더해서 사용하는 것은 URL 인코딩이 안되기 때문에 위험하다. 다음에 설명하는 RedirectAttributes를 사용하자RedirectAttributes
상품을 저장하고 상품 상세 화면으로 리다이렉트 한 것 까지는 좋았다. 그런데 고객 입장에서 저장이 잘 된 것인지 안 된 것인지 확신이 들지 않는다. 그래서 저장이 잘 되었으면 상품 상세 화면에 "저장되었습니다"라는 메시지를 보여달라는 요구사항이 왔다. 간단하게 해결해 보자.
BasicItemController에 추가
@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}"; }
리다이렉트 할 때 간단히 status=true를 추가
RedirectAttributes
RedirectAttributes를 사용하면 URL 인코딩도 해주고, pathVarible, 쿼리 파라미터까지 처리해 준다.
- redirect:/basic/items/{itemId}
- pathVariable 바인딩 : {itemId}
- 나머지는 쿼리 파라미터로 처리 : ?status=true
실행해보면 다음과 같은 리다이렉트 결과가 나온다.
http://localhost:8080/basic/items/3?status=true
뷰 템플릿 메시지 추가
<h2 th:if="${param.status}" th:text="'저장 완료'"></h2>
- th:if : 해당 조건이 참이면 실행
- ${param.status} : 타임리프에서 쿼리 파라미터를 편리하게 조회하는 기능
- 원래는 컨트롤러에서 모델에 직접 담고 값을 꺼내야 한다. 그런데 쿼리 파라미터는 자주 사용해서 타임리프에서 직접 지원한다.
출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1
'Spring > 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술' 카테고리의 다른 글
[김영한 스프링] 33. 스프링 MVC 웹 페이지 만들기 - 상품 등록 처리 & 상품 수정 (0) 2023.07.24 [김영한 스프링] 32. 스프링 MVC 웹 페이지 만들기 - 상품 상세 & 상품 등록 폼 (0) 2023.07.24 [김영한 스프링] 31. 스프링 MVC 웹 페이지 만들기 - 상품 목록 타임리프 (0) 2023.07.23 [김영한 스프링] 30. 스프링 MVC 웹 페이지 만들기 - 상품 서비스 HTML (0) 2023.07.20 [김영한 스프링] 29. 스프링 MVC 웹 페이지 만들기 - 상품 도메인 개발 (0) 2023.07.19 - redirect:/basic/items/{itemId}