본문 바로가기
스프링/스프링 웹

[Spring] PRG 패턴 - Post/Redirect/Get

by drCode 2023. 6. 15.
728x90
반응형

사실 지금까지 진행한 상품 등록 처리 컨트롤러는 심각한 문제가 있다.

(addItemV1 ~ addItemV4) 상품 등록을 완료하고 웹 브라우저의 새로고침 버튼을 클릭해보자.

 

상품이 계속해서 중복 등록되는 것을 확인할 수 있다.

 

http://localhost:8080/basic/items/add
http://localhost:8080/basic/items/add
http://localhost:8080/basic/items/add

 

전체 흐름

전체 흐름

그 이유는 다음 그림을 통해서 확인할 수 있다.

 

POST 등록 후 새로 고침

 

새로고침

웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송한다.

 

Referer : http://localhost:8080/basic/items/add

 

상품 등록 폼에서 데이터를 입력하고 저장을 선택하면 POST /add + 상품 데이터를 서버로 전송한다.

이 상태에서 새로 고침을 또 선택하면 마지막에 전송한 POST /add + 상품 데이터를 서버로 다시 전송하게 된다.

그래서 내용은 같고, ID만 다른 상품 데이터가 계속 쌓이게 된다.

 

이 문제를 어떻게 해결할 수 있을까? 다음 그림을 보자.

 

POST, Redirect GET

웹 브라우저의 새로 고침은 마지막에 서버에 전송한 데이터를 다시 전송한다.

새로 고침 문제를 해결하려면 상품 저장 후에 뷰 템플릿으로 이동하는 것이 아니라,

상품 상세 화면으로 리다이렉트를 호출해주면 된다.

 

웹 브라우저는 리다이렉트의 영향으로 상품 저장 후에 실제 상품 상세 화면으로 다시 이동한다.

따라서 마지막에 호출한 내용이 상품 상세 화면인 GET /items/{id} 가 되는 것이다.

이후 새로고침을 해도 상품 상세 화면으로 이동하게 되므로 새로 고침 문제를 해결할 수 있다.

 

 

BasicItemController에 추가

/**
 * PRG - Post/Redirect/Get
 */
@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 를 사용하자.

728x90
반응형

댓글