PRG (Post/Redirect/Get) 패턴 : 중복 데이터 제출을 막는 웹 개발의 필수 설계 패턴
웹 애플리케이션을 개발하다 보면 폼 데이터를 처리하는 과정에서 종종 발생하는 문제가 있습니다. 사용자가 폼을 제출한 후 새로고침(F5)을 누르면 동일한 요청이 다시 서버로 전송되어 중복 데이터가 생성되는 상황입니다.
이때 PRG (Post/Redirect/Get) 패턴은 이러한 문제를 효과적으로 해결할 수 있는 설계 패턴입니다. 이번 글에서는 PRG 패턴이 무엇인지, 왜 필요한지, 그리고 이를 어떻게 구현할 수 있는지에 대해 살펴보겠습니다!!
PRG 패턴이란?
PRG 패턴은 웹 애플리케이션에서 폼 제출 후 새로고침 시 중복 요청을 방지하기 위해 고안된 설계 패턴입니다. 기본적인 흐름은 다음과 같습니다.
- Post : 사용자가 웹 폼을 제출하면 클라이언트는 서버로 POST 요청을 전송합니다. 이때 서버는 요청된 데이터를 처리하고, 필요한 경우 데이터베이스에 저장합니다.
- Redirect : 서버는 POST 요청을 처리한 후, 사용자를 특정 URL로 리디렉션(HTTP 302 상태 코드) 시킵니다. 이 과정에서 클라이언트는 브라우저 주소창에 새로운 URL을 받게 됩니다.
- Get : 클라이언트는 리디렉션된 URL로 GET 요청을 전송하고, 서버는 해당 요청에 맞는 페이지를 반환하여 사용자에게 결과를 보여줍니다.
이러한 3단계 과정이 바로 PRG 패턴입니다.
PRG 패턴이 필요한 이유
PRG 패턴은 웹 개발에서 다양한 문제를 예방해 주는 중요한 역할을 합니다.
- 중복 폼 제출 방지
사용자가 폼을 제출하고 나서 브라우저를 새로고침하면 동일한 POST 요청이 서버로 다시 전송될 수 있습니다. 이로 인해 데이터가 중복 입력되거나, 결제가 두 번 이루어지는 등의 문제가 발생할 수 있습니다. PRG 패턴을 사용하면 POST 요청 후에는 리디렉션이 이루어지기 때문에, 새로고침 시에는 GET 요청만 전송됩니다. 이로써 중복 폼 제출을 방지할 수 있습니다. - 사용자 경험 향상
사용자가 폼을 제출한 후 브라우저의 새로고침 버튼을 누르면 경고 메시지가 나타나는 경우가 많습니다. "이 페이지에서 이전에 제출한 데이터를 다시 전송하겠습니까?"라는 메시지를 보게 되는데, 이는 사용자의 경험을 해치게 됩니다. PRG 패턴을 사용하면 이런 경고 메시지가 나타나지 않아 더 나은 사용자 경험을 제공할 수 있습니다. - RESTful 디자인과의 조화
웹 애플리케이션의 RESTful 설계 원칙에서는 POST 요청이 데이터 생성을 의미하고, GET 요청은 리소스를 가져오는 용도로 사용됩니다. PRG 패턴은 POST 요청이 끝난 후 GET 요청으로 이어지므로, RESTful한 아키텍처와 일관성을 유지할 수 있습니다.
PRG 패턴 구현 방법
PRG 패턴을 구현하는 방법은 비교적 간단합니다. 예시로 사용자가 블로그 글을 작성하는 폼을 제출하는 상황을 가정해 보겠습니다.
package com.example.prgexample.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
public class BlogController {
// 글 작성 폼을 보여주는 페이지
@GetMapping("/blog/new")
public String showForm() {
return "blogForm";
}
// 폼 데이터 제출을 처리하는 메서드 (POST 요청)
@PostMapping("/blog/new")
public String submitBlog(@RequestParam("content") String content, RedirectAttributes redirectAttributes) {
// 여기서 데이터를 저장하는 로직을 구현합니다 (예: DB에 저장)
// 예시로 간단하게 출력
System.out.println("Blog Content: " + content);
// 리디렉션 시에 플래시 속성으로 메시지 전달
redirectAttributes.addFlashAttribute("message", "블로그 글이 성공적으로 작성되었습니다!");
// 리디렉션을 통해 PRG 패턴 적용
return "redirect:/blog/confirmation";
}
// 리디렉션 후 확인 페이지를 보여주는 메서드 (GET 요청)
@GetMapping("/blog/confirmation")
public String confirmationPage(Model model) {
return "confirmation";
}
}
위의 예시에서 사용자가 /blog/new
경로로 POST 요청을 보내면 서버는 데이터를 처리한 후, /blog/confirmation
경로로 리디렉션합니다. 클라이언트는 이후 /confirmation
경로로 GET 요청을 보내고, 서버는 해당 페이지를 반환합니다. 이렇게 함으로써 사용자가 새로고침을 하더라도 POST 요청이 다시 전송되지 않도록 방지할 수 있습니다.
PRG 패턴의 한계
물론 PRG 패턴에도 한계는 존재합니다. 가장 큰 단점은 리디렉션이 추가됨에 따라 네트워크 요청이 한 번 더 발생한다는 점입니다.
이는 서버와 클라이언트 사이의 통신 비용을 증가시킬 수 있습니다.
하지만 대부분의 경우, 데이터 중복 문제를 방지하는 이점이 이러한 성능 손실을 상쇄하기 때문에 PRG 패턴이 널리 사용되고 있습니다.
결론
PRG 패턴은 폼 제출 후 발생할 수 있는 중복 데이터 문제를 해결하고, 더 나은 사용자 경험을 제공하는 데 중요한 역할을 하는 웹 개발의 필수적인 설계 패턴입니다. 이 패턴을 활용함으로써 RESTful 설계를 유지할 수 있고, 사용자가 새로고침을 하더라도 안전하게 데이터를 보호할 수 있습니다!
'Framework > Spring' 카테고리의 다른 글
Node.js와 Spring의 차이: 왜 Spring은 Tomcat 서버가 필요할까? (1) | 2024.09.11 |
---|---|
JPA에서 @GeneratedValue와 GenerationType에 대해 알아보자 (0) | 2024.08.19 |
[Spring] 제어의 역전(IoC)이란? (0) | 2024.03.22 |