[Spring] PRG 패턴

HSRyuuu dev blog·2023년 4월 14일
0

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를 사용하면, PathVariableQueryParameter
    redirect 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

반환문에 {memberId}로 PathVariable 바인딩시 경로변수로 사용되고,
나머지는 쿼리 파라미터로 사용된다.

profile
Exciting dev life / 댓글, 피드백, 질문 환영합니다 !!!

0개의 댓글