본문 바로가기
트러블슈팅

PRG 패턴, 303 상태코드로 양식 다시 제출 방지하기

by eess 2024. 6. 27.

문제 & 원인

  • 위와 같이 양식을 제출하고 나서 새로고침을 할 때마다 계속 '양식 다시 제출 확인' 알림창이 뜹니다.
  • 처음에 GET /add URL에서 웹 양식을 제출하면 POST /add로 전송됩니다.
  • 서버에서는 POST /add로 요청이 들어오면, 양식 데이터를 적절히 처리 후 308 상태 코드와 함께 홈화면으로 리다이렉션을 해주었습니다.
  • 리다이렉션을 해주었음에도 POST 요청이 발생하는 것을 보아, 308 상태 코드가 문제라는 생각이 들었습니다.

 

 

우선, 리다이렉트와 PRG 패턴의 개념에 대해 정리하고 해결 방법을 선택해보겠습니다.

리다이렉트(Redirect)

  • 리다이렉트는 사용자(브라우저)가 처음 요청한 URL이 아닌, 다른 URL로 보내는 과정입니다.
  • HTTP 리다이렉트는 서버에서 3XX 코드로 응답할 때 발생합니다. 3XX 코드를 받은 클라이언트(브라우저)는 응답으로 받는 URL로 이동합니다.
  • 리다이렉트를 통해 웹에서 SEO(검색 엔진 최적화)를 강화하고 사용자 경험을 향상시킬 수 있습니다.

리다이렉트 용도

  • 페이지 이동 : 웹사이트 구조가 변경되거나 페이지가 이동된 경우 사용자와 검색 엔진이 올바른 URL을 찾도록 안내합니다.
  • URL 정리 : 사용자가 입력한 잘못된 URL을 올바른 형식으로 정리하여 재요청하게 합니다.
  • 세션 관리 : 로그인 후 사용자에게 적절한 페이지로 리다이렉트합니다.
  • PRG 패턴 : POST 요청 후 새로고침 문제를 방지하기 위해 사용됩니다.

리다이렉트 유형

영속적인 리다이렉션

  • 특정 리소스의 URL로 영구적으로 이동합니다.
  • 301 (Moved Permanently)
    • 최초 요청의 HTTP 메서드가 GET으로 변할 수 있고, 본문이 제거될 수 있습니다.
    • 브라우저가 301 응답을 어떻게 구현했는지에 따라 다를 수 있지만, 거의 대부분 브라우저는 위와 같이 수행합니다.
    • 영구적으로 변경된 URL로 페이지 이동시킬 때 사용할 수 있습니다.
  • 308 (Permanent Redirect)
    • 최초 요청의 HTTP 메서드와 본문이 변하지 않습니다.
    • 영구적으로 변경된 URL로 페이지 이동시킬 때 사용할 수 있다는 점은 301과 같지만, GET 요청이 아니면서 본문이 있는 요청에 대해 308을 사용하는 것이 좋습니다.

일시적인 리다이렉션

  • 특정 리소스의 URL로 일시적으로 이동합니다.
  • 302 (Found)
    • 최초 요청의 HTTP 메서드가 GET으로 변할 수 있고, 본문이 제거될 수 있습니다.
    • 301과 원리는 같지만, 검색 엔진이 링크를 갱신하지 않습니다.
  • 303 (See Other)
    • 최초 요청의 HTTP 메서드가 GET으로 바뀌고 본문이 제거됩니다.
    • PRG 패턴과 관련하여, PUT이나 POST 요청 후에 새로고침 시 중복 요청을 방지할 때 사용할 수 있습니다.
  • 307 (Temporary Redirect)
    • 최초 요청의 HTTP 메서드와 본문을 유지합니다.
    • 요청한 리소스가 일시적으로 다른 URL에 있음을 나타내고, 이전 요청과 동일할 메소드와 본문으로 요청해야할 때 사용할 수 있습니다.
    • 307, 308은 일시적이냐, 영구적이냐의 차이고, 308의 경우 검색엔진이 새로운 URL을 영구적으로 기억해야 합니다.

특수 리다이렉션

  • 캐시를 활용하는 것과 관련된 리다이렉션입니다.
  • 300 (Multiple Choices)
    • 요청된 리소스에 대한 여러 가지 가능한 응답이 있으며, 클라이언트가 선택할 수 있습니다.
    • 요청에 2개 이상의 응답이 가능할 때 사용됩니다. (하나의 리소스에 대해 여러 언어 버전을 제공하는 경우, 동일한 컨텐츠에 대해 여러 포맷을 제공하는 경우)
    • Location 헤더에 가능한 여러 URL을 담을 수 있습니다.
  • 304 (Not Modified)
    • 클라이언트가 요청한 리소스가 이전 요청 이후로 수정되지 않았음을 나타냅니다.
    • 클라이언트는 If-Modified-Since 헤더를 사용하여 조건부 요청을 보냅니다.
    • 서버는 If-Modified-Since 헤더가 있는 요청이 들어오면, 서버는 브라우저가 마지막으로 액세스한 이후 파일이 업데이트 됐는지 확인하고 200 또는 304로 응답합니다.
    • 304로 응답이 오면 클라이언트는 캐시된 버전을 사용해야 합니다.
    • 서버는 리소스를 다시 전송하지 않으므로 네트워크 대역폭을 절약할 수 있습니다.

 

PRG(Post/Redirect/Get) 패턴

출처 : GeekforGeeks

  • 양식 제출 후 동일한 웹 페이지를 다시 로드하여 양식을 다시 제출하는 것을 방지하기 위해 사용합니다.
  • POST 요청 후 사용자를 GET 요청으로 리디렉션하여, 새로고침을 해도 POST 요청이 다시 제출되지 않도록 합니다.

 

해결방법

  •  새로고침을 방지하기 위해 필요한 것은 다음과 같습니다
    1. POST 요청 후 루트 Base URL로 이동
    2. 새로고침으로 인한 POST 요청 방지
  • 이전에는 308 상태코드를 쓰고 있어 POST /add 요청 후에 새로고침 시 POST / 요청을 보내고 있는 것입니다.
  • 즉, PRG 패턴을 활용하여 일시적인 리다이렉션 중 303 상태코드로 응답한 후 GET / 으로 리다이렉트 해야 할 것입니다.
    • 아래와 같이 303 See Other로 응답 코드를 변경했습니다.

결과

  • 새로고침 시 더이상 POST 요청이 반복되지 않습니다.

참고

 

'트러블슈팅' 카테고리의 다른 글

[Go] command not found: xxx 해결 방법  (0) 2024.07.03