Spring

[Spring Boot] PRG 패턴 ( Post - Redirect - Get )

HSRyuuu 2023. 4. 21. 21:31

PRG 패턴 (Post-Redirect-Get)

웹 개발 패턴 중 자주 쓰이는 패턴 중 하나이다.
HTTP Post 요청에 대한 응답을 다른 URL로의 GET방식으로 Redirect 하는 것이다.


PRG 패턴을 사용하지 않을 때 발생하는 문제

첫 번째로, Post 요청 처리 시 새로고침으로 인해 동일한 요청이 연속적으로 보내지는 오류가 발생할 수 있다.
Post 요청을 처리할 때, 변경이 일어나지 않는 로직이라면 상관없지만, Post로 값을 받아 무언가를 변경하는 로직이 있다면 새로고침 했을 때 그 로직이 반복 실행되는 문제가 발생할 수 있다.

 

두 번째로, Post 요청 처리 후 다른 페이지를 호출하는 경우 해당 페이지를 호출할 때 필요한 파라미터들을 넘겨주지 않아서 문제가 발생할 수 있다.

 

이런 문제들을 해결하고자 Post요청에 대한 응답으로 다른 URL에 갈 때,
GET 방식으로 redirect 하는 PRG 패턴을 사용한다.


PRG 패턴 적용

PRG 패턴 적용 전

  • PostMapping 로직 처리 후 success 뷰를 그대로 호출한다.

새로고침 시 로직이 반복처리될 수 있고,
success 뷰를 호출하는데 파라미터가 필요하다면 오류가 발생할 수 있다.

@Controller
public class TestController{

    @GetMapping
    public String home(Model model){
    //로직 처리 후 view에 memberList를 넘겨준다. 
    model.addAttribute("list" , memberList);
    return "home";
    }

    @PostMapping("/add")
    public String addMember(@ModelAttribute("member") Member member){
    //멤버를 추가하는 로직을 실행 후 success페이지로 이동한다.
    return "success";
    }
}

PRG 패턴 적용 후

  • PostMapping 로직 처리 후 success 뷰를 그대로 호출하는 대신, /success로 redirect 한다.

PostMapping 처리 후 뷰를 호출하는 것이 아닌, Get방식으로 /success를 호출하는 것이기 때문에
파라미터도 정상적으로 넘겨줄 수 있고, 새로고침시 오류도 발생하지 않는다.

@Controller
public class TestController{

    @GetMapping
    public String home(){
    return "home";
    }

    @PostMapping("/add")
    public String addMember(@ModelAttribute("member") Member member){
    //멤버를 추가하는 로직을 실행 후 success페이지로 이동한다.
    return "redirect:/success";
    }

    @GetMapping("/success")
    public String success(Model model){
    //view에 member객체를 넘겨준다.
    model.addAttribute("member" , member);
    }
}

RedirectAttributes

redirect시 경로변수(PathVariable)가 필요한 페이지로 이동시키려면 어떻게 해야 할까?

 

(잘못된 예시)

위의 예제를 조금 변형해 보자.
만약 /success가 아닌 /success/{memberId} 이동하고자 한다.
이때는 반환문에 해당 String을 추가해 줄 수 있다.

@PostMapping("/add")
public String addMember(@ModelAttribute("member") Member member){
	//멤버를 추가하는 로직을 실행

	return "redirect:/success/"+ member.getId();
}

위와 같이 URL에 변수를 더해서 사용하면 URL 인코딩이 되지 않기 때문에 위험하다.
이때, RedirectAttributes를 사용하면, PathVariable QueryParameterredirect URL에 담을 수 있다.


redirectAttributes.addAttribute() 사용

아래와 같이 redirect에 여러 값을 담을 수 있다.

@PostMapping("/add")
public String addMember(@ModelAttribute("member") Member member,
                            RedirectAttributes redirectAttributes){
    //멤버를 추가하는 로직을 실행
    
    //memberId = "hello" 
    redirectAttributes.addAttribute("memberId" , member.getId());
    redirectAttributes.addAttribute("add" , true);
    
    return "redirect:/success/{memberId}";
}
  • 결과 : /success/hello? add=true

반환문에 PathVariable 바인딩 시 경로변수로 사용된다. ex) {memberId}


나머지쿼리 파라미터로 사용된다. ex) add=true

반응형