본문 바로가기
Frameworks/Springboot

[Springboot] PRG패턴 정리

by 젊은오리 2022. 8. 26.
728x90

[김영한님의 스프링 MVC 1편-백엔드 웹 개발 핵심 기술을 학습 후 정리한 내용입니다.]

상품등록, 조회에 관한 간단한 웹페이지를 만드는 과정이었지만, 기본기부터 다지자는 마음에서 더 꼼꼼하게 강의를 들었던 것 같다. 뷰 템플릿으로 JSP가 아닌 Thymeleaf을 사용하게 되서,, 그 문법을 새롭게 배웠고, 강의 마지막 부분에서 PRG패턴과 RedirectAttributes을 사용해서 상품등록의 중복을 막고 사용자친화적인 message를 제공하는 것을 보고 정리를 하게 되었다.

● 현재상황

/add로 되있는 url은 상품등록폼으로 연결된 주소이고, 컨트롤러에서는 아래와 같이 상품명, 가격, 수량을 받아서 Item에 저장하고, 해당 basic/item이라는 뷰 템플릿으로 이동하게 된다.

@PostMapping("/add")
public String save(@ModelAttribute Item item){
    itemRepository.save(item);
    return "basic/item";
}

 

basic/item으로 이동하게 되면, 아래와 같은 상품상세페이지가 나온다. 여기서 문제가 발생하는데, 지금 이 페이지에서 새로고침을 클릭했을 때, id만 하나씩 증가하면서, 같은 상품데이터가 게속 쌓이게 된다.

새로고침 전

 

새로고침 후

 

이유는, 웹 브라우저의 새로고침은 마지막에 서버에 전송한 데이터를 다시 전송하는 특징이 있다. 따라서 상품데이터를 서버로 전송했던 마지막 작업을 다시 반복하게 되어 같은 상품이 계속 서버로 가게 되는 것이다. 

이 문제를 해결하려면, 상품 저장 후에 뷰템플릿으로 이동하는 것이 아닌, 상품 상세화면으로 리다이렉트해주면 된다. 리다이렉트를 해주면, 상품을 저장한 후에 상품 상세화면으로 이동하기 때문에,, 마지막 호출이 GET방식이 되어서 새로고침을 해도 그 페이지만 나올 뿐, 서버에 POST요청이 가지 않게 된다. 

따라서 아래와 같이 컨트롤러를 수정해준다.

@PostMapping("/add")
public String save2(@ModelAttribute Item item){
    Item savedItem = itemRepository.save(item);
    return "redirect:/basic/items/"+item.getId();
}

이런식으로 뷰 템플릿이 아닌 해당 화면으로 리다이렉트하도록 코드를 작성하는 방식을 PRG(Post/Redirect/Get)이라고 한다. 근데 여기서 item.getId()처럼 URL에 변수를 더해서 사용하는 것은 URL 인코딩이 안되기에 위험할 수 있다. 이것을 RedirectAttributes로 해결해보자. 더해서, 고객입장에서 상품등록이 잘 됐는지 알기가 어렵기 때문에 저장이 잘 되었다면 저장됐다는 메시지를 보여주도록 하자.

@PostMapping("/add")
public String save2(@ModelAttribute Item item, RedirectAttributes redirectAttributes){
    Item savedItem = itemRepository.save(item);
    redirectAttributes.addAttribute("itemId", savedItem.getId());
    redirectAttributes.addAttribute("status",true);
    return "redirect:/basic/items/{itemId}";
}

컨트롤러를 RedirectAttributes를 이용해서 위와 같이 바꾸게 되면, +연산을 쓰지 않고 {itemId}로 받게 되어 URL인코딩을 할 수 있게 했다. 또한 나머지는 ?status=true형식의 쿼리 파라미터로 처리를 했다.

 상품 상세 페이지에서 아래와 같이 ${param.status}로 받아주게 하고 밑에 alert처리해주면,,,

<h2 th:if="${param.status}" th:text="'저장 완료!'"></h2>

 

아래와 같이 메세지가 잘 나온 것을 확인할 수 있다. 

 

 

728x90

댓글