영구 리다이렉션은 리소스의 URI가 영구적으로 이동했으므로 원래의 URL을 사용하지 않아야 하며, 이를 검색 엔진 등에서도 인지하도록 한다.
위 예시를 보자.
/event
경로에서 사용자가 입력한 데이터를 서버로 보내기 위해 POST 요청 메세지를 보냈지만, 이는 더이상 사용하지 않는 경로이므로 서버는 301 Moved Permanently 응답을 하게 된다.
그 후 새로운 경로인 /new-event
경로로 자동 리다이렉트되며, 이때 클라이언트가 서버에 보내는 요청은 메세지 본문이 삭제된 GET 요청 메세지가 된다. 이 경우, 사용자가 기존 페이지에서 입력했던 데이터들은 날라가고 새로운 입력 폼 화면이 뜨는 등의 현상이 발생할 수 있다.
301 리다이렉션에서 발생하는 문제를 308이 해결해줄 수 있다❗️
301에서의 예시와 마찬가지로, /event
경로에서 사용자가 입력한 데이터를 서버로 보내기 위해 POST 요청 메세지를 보내면 서버는 308 Permanent Redirect를 응답하고 /new-event
경로로 자동 리다이렉트되며, 새로운 입력 폼 화면이 띄워지더라도 기존에 사용자가 입력했던 데이터는 그대로 유지된다. 따라서 새로운 POST 요청 메세지 내 메세지 바디도 그대로 유지된다.
일시 리다이렉션은 리소스의 URI가 일시적으로 변경되는 현상으로, 해당 경로로의 다음 접속 때도 바뀐 URL이 아닌 기존 URL로 접속 요청을 보내야 한다. 또한 검색 엔진 등에서도 URL을 변경하면 안된다.
POST로 주문 후에 웹 브라우저를 새로고침한다면 어떻게 될까? 새로고침은 요청을 다시 보내도록 하므로, 주문이 중복으로 이루어질 가능성이 있다.
이 경우 PRG: Post/Redirect/Get
이라는 일시 리다이렉션에서 많이 사용하는 패턴을 사용한다.
PRG: Post/Redirect/Get
- POST로 주문 후에 새로고침으로 인한 중복 주문을 방지한다.
- POST로 주문 후에 주문 결과 화면을 GET 메서드로 리다이렉트한다.
- 새로고침을 하더라도 결과 화면을 GET으로 조회한다.
- 중복 주문 대신, 결과 화면만 GET으로 다시 요청한다.
같은 예시에 대해 상황이 어떻게 바뀌었는지 살펴보자.
클라이언트의 주문을 통해 /order
경로에서 POST 요청 메세지를 보내면, 서버는 메세지 본문을 통해 들어온 주문 정보를 DB에 저장한 후 200 OK 가 아닌 302 Found 를 응답하며 리다이렉트 경로를 Location 헤더에 담아 응답 메세지를 전송한다.
메세지를 받은 클라이언트는 /order-result/19
로 리다이렉트하며, GET 메서드로 바꾼 후 경로에 해당하는 페이지를 요청한다. 요청을 받은 서버는 19번 주문에 해당하는 데이터를 DB에서 조회한 후 200 OK 와 함께 페이지를 클라이언트에게 응답한다.
이 경우 클라이언트가 새로고침 시 중복 주문이 요청될 수 있는 문제는 해결된다. 이미 URL이 주문 정보 페이지로 리다이렉트되었으며, 새로고침을 하더라도 GET 요청을 통해 주문 결과 화면만 조회하기 때문이다.
모호한 302를 사용하기보다는 명확한 307, 303을 권장하지만, 현실적으로는 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용하고 있다.
자동 리다이렉션 시에 GET으로 메서드가 변경되어도 괜찮다면, 302를 사용해도 큰 문제가 없을 것이다.
304 Not Modified
캐시를 목적으로 사용하며, 클라이언트에게 리소스가 수정되지 않았음을 알려줄 때 사용한다. 이 메세지를 받은 클라이언트는 캐시로 리다이렉트해서, 로컬 PC에 저장되어 있는 캐시를 사용한다.
304는 로컬 캐시를 사용해야 하는 것이 명확하기 때문에, 응답 메세지에 메세지 본문을 포함하면 안된다.