Post

3XX 상태코드 - Redirection

리다이렉션(Redirection)이란?

3xx 번대의 상태 코드들은 리다이렉션을 의미하며, 이는 요청을 완료하려면 추가적인 작업(페이지 이동)이 필요함을 의미한다.

클라이언트가 관심 있어 하는 리소스에 대해 다른 위치를 사용하라고 말해주거나 그 리소스의 내용 대신 다른 대안 응답을 제공한다.

웹 브라우저는 3XX응답의 결과에 Location 헤더가 있으면, Location위치로 자동 이동한다.


기존 스크랩했던 url주소가 변경되었다고 가정했을 때의 예시를 살펴보자.

image


  1. 기존 경로로 요청

  2. 서버에서 3XX와 Location에 변경된 url 응답

  3. 웹 브라우저에서 자동으로 Location의 url로 요청

  4. 새로운 url에서 응답




리다이렉션 종류

리다이렉션(Redirection)은 클라이언트가 요청한 URL에 대해 다른 URL을 다시(re) 지시(direct)하여 다른 주소로 이동할 수 있게 하는 기술이다. HTTP 에 사용되는 리다이렉션은 크게 3가지 종류로 나눌 수 있다.


  • 영구 리다이렉션(Permanent) : 특정 리소스의 URL 이 영구적으로 이동

  • 일시 리다이렉션(Temporary) : 특정 리소스의 URL 이 일시적으로 이동

  • 특수 리다이렉션(Special) : 캐시를 활용할 것인지에 대한 여부


위의 어느 종류의 리다이렉션을 이용하느냐에 따라 HTTP Status Code가 달라지게 된다.


영구 리다이렉션

  • 리소스의 URI가 영구적으로 이동

  • 원래의 URL를 사용X, 검색 엔진 등에서도 변경 인지

  • 301 Moved Permanently

    • 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
  • 308 Permanent Redirect

    • 리다이렉트시 요청 메서드와 본문 유지(처음 POST를 보내면 리다이렉트도 POST 유지)


301(Moved Permanently)

  • Moved Permanently ⇢ 영구적으로 이동 (영구 리다이렉션)

  • 요청된 리소스가 Location 헤더가 지정한 URL로 이동되었음을 나타낸다.

  • 해당 URL로 리다이렉션 되면, 요청 메서드가 GET으로 변하고 본문이 제거될수 있다.

  • 따라서 301 코드는 GET 또는 HEAD 방법에 대한 응답으로만 사용하고, 대신 POST, PUT 같은 경우는 같은 영구

  • 리디렉션인 308 Permanent Redirect 을 사용하는 것이 좋다.


image

  1. 클라이언트는 ‘/event’ 라는 URL 을 웹서버에 전송하여 이벤트 페이지에 대한 GET 요청한다.

  2. 하지만, ‘/event’ 는 더 이상 사용하지 않는 URL 이며, 현재는 ‘/new-event’ 를 사용하고 있다고 하여 서버에서 301 리다이렉션 상태 코드와 함께 헤더의 Location 필드에 새로운 URL 인 ‘/new-event’ 를 담아 응답메시지를 전송한다.

  3. 응답메시지를 전달받은 클라이언트는 301 상태 코드와 Location 필드의 URL 을 참고하여, 새로운 URL 로 리다이렉션하라는 것을 인지한다.

  4. 클라이언트는 리다이렉션 하기 위해 ‘/new-event’ 라는 URL 을 웹서버에 전송하여 이벤트 페이지에 대한 GET 요청한다.

  5. 서버는 200 OK 와 함께 이벤트 페이지의 html 을 전송해주게 된다.


308(Permanent Redirect)

  • Permanent Redirect ⇢ 영구 리다이렉션

  • 301 Moved Permanently과 기능은 동일하지만, 영구 리다이렉트 시 요청 메서드와 본문을 유지한다.

  • 즉, 클라이언트가 처음에 POST 메서드와 함께 생성할 리소스 정보를 Body 에 담아 전송하였다면, 새로운 URL 로 리다이렉트하더라도 그 메서드와 Body 내용이 유지되는 것이다.

  • 다만 첫 요청에 POST가 사용되었다면, 두번째 요청도 반드시 POST를 사용해야 한다.

  • 클라이언트가 요청한 리소스가 다른 URI에 있으며, 이전 요청과 동일한 메소드를 사용하여 요청해야 할 때 응답으로 이용된다.


image

  1. 클라이언트는 ‘/event’ 의 이벤트 페이지에 ‘name’ 과 ‘age’ 바디 정보를 담은 POST 요청을 한다.

  2. 이 때 서버는 301 Moved Permanently 상태코드와 Location 필드를 활용하여 이벤트 페이지의 주소가 ‘/new-event’ 라는 새로운 주소로 영구적 변경되었다는 사실을 알리고 브라우저로 하여금 리다이렉트를 지시한다.

  3. 클라이언트는 해당 Location으로 자동 리다이렉트 된다.

  4. 여기까지 301과 동일하지만, 클라이언트가 처음 사용했던 POST 메서드가 유지되고, ‘name’ 과 ‘age’ 정보가 본문에 유지되어 있는 모습을 확인할 수 있다.



일시 리다이렉션

  • 리소스의 URI가 일시적으로 변경

  • 따라서 검색 엔진 등에서 URL을 변경하면 안됨

  • 302 Found

    • 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음(MAY)
  • 307 Temporary Redirect

    • 리다이렉트시 요청 메서드와 본문 유지(요청 메서드를 변경하면 안된다. MUST NOT)
  • 303 See Other

    • 리다이렉트시 요청 메서드가 GET으로 변경


PRG (Post - Redirect - Get) 패턴

위에서의 3XX 코드 중 리다이렉션 뒤 요청 메서드를 GET으로 바뀌는 패턴을 보이는 코드가 있다. 왜 이런식으로 설계되었을까?

이를 쉽게 이해하기 위해 쇼핑몰 사이트에서 POST를 통해 주문을 요청하고, 브라우저를 새로고침(refresh) 하였다고 가정해보자. refresh는 이전의 요청을 재전송 하기 때문에 POST 요청을 다시하게 되고 따라서 서버에 중복 주문이 들어가게 될 가능성이 있다.


image

  1. 클라이언트는 주문창에서 mouse 제품과 수량은 1개로 선택하고 POST 메서드로 주문 요청을 서버에 전송한다.

  2. 서버에서는 주문 요청을 데이터베이스에 저장한다.

  3. 그리고 200 OK 를 반환한다.

  4. 사용자가 브라우저를 새로고침(refresh) 하였다.

  5. 이때 refresh 되면서 이전 POST 요청이 그대로 재전송되고, 같은 주문이 중복되어 생성되는 문제가 발생하게 된다.


따라서 이러한 문제 때문에 이전 POST 메서드를 GET 메서드로 변환 시켜줌으로써 중복 주문을 방지하자는 취지에서 설계된 것으로 보면된다.

본론으로 넘어와서, PRG 패턴은 위처럼 일시적인 리다이렉션에서 중복 요청의 전송을 방지하기 위해 사용하는 일종의 HTTP 패턴이다.

배달 이나 쇼핑 어플리케이션에서 주문이 끝난 후 자동으로 주문이 완료되었음을 알리는 결과 화면으로 이동하게 되는 동작들이 PRG 패턴의 사례이다.

위의 사례에서 PRG 패턴이 적용된 302 상태 코드를 적용하면 다음과 같이 된다.


image

  1. 클라이언트는 주문창에서 mouse 제품과 수량은 1개로 선택하고 POST 메서드로 주문 요청을 서버에 전송한다.

  2. 서버에서는 주문 요청을 데이터베이스에 저장한다.

  3. 그리고 리다이렉트할 Location 헤더와 함께 302 Found를 반환한다.

  4. 클라이언트는 헤더 메세지를 읽고 주문 결과 화면인 ‘/order-result/19’ 로 리다이렉트 준비를 한다.

  5. 클라이언트는 ‘/order-result/19’ 로 요청을 한다. 이때 메서드를 GET으로 변경하고 body를 제거한다. 따라서 클라이언트는 문 결과 화면에 대해 단순 조회 요청을 전송하게 된다.

  6. 서버는 데이터베이스에서 해당 주문을 조회한다.

  7. 그리고 200 OK 를 반환한다.

  8. 주문 결과 화면으로 이동하게 된 클라이언트는, 새로고침를 반복하더라도 주문 결과 화면에 대한 조회 요청만을 반복적으로 전송하게 된다. (5번으로 이동됨)


정리하자면 PRG 패턴이 적용된 적절한 상태코드를 사용함으로써 중복 주문 요청을 방지한 것이다.


302(Found)

  • Found ⇢다른 URL에서 리소스를 찾음 (일시 리다이렉션)

  • 요청된 리소스가 Location 헤더가 지정한 URL로 일시적으로 이동되었음을 나타낸다. (말이 일시이지 새 URL로 리다이렉트 되는건 같음)

  • 302는 리다이렉트 시 301과 같이 요청 메서드가 GET으로 변하고 본문이 제거 될수있지만, 무조건적으로 변경하지 않기 때문에 브라우저에 따라 작업 수행이 달라지는 불확실성을 가질 수 있다는 특징이 있다.

  • 이러한 불확실성 때문에 303, 307 상태 코드가 추가되었다. 그래서 만일 사용된 메서드를 GET로 변경하려는 경우 대신 303 See Other를 사용하는게 좋다.


💡301 vs 302 차이점 (일시 vs 영구 리다이렉션)

  • 301은 요청한 정보가 새로운 주소로 영구적으로 옮겨갔다는것을 말해주며, 302는 일시적으로 옮겨갔다는것을 말해준다.
  • 이 ‘영구적’ 과 ‘일시적’ 차이가 애매모호할 수 있을 것이다. 왜냐하면 둘이 동작 형태를 확인해보면 표면상으로는 둘다 자동으로 리다이렉션 하니 사람의 육안으로는 구별할수 없기 때문이다.
  • 사실 이 둘을 구별하는 주체 대상은 사람이 아닌 검색 엔진, 검색 봇이다. 그리고 어떤 리다이렉션을 쓰느냐에 따라 검색엔진 최적화에 미치는 영향은 꽤 크다.


307(Temporary Redirect)

  • Temporary Redirect ⇢ 일시 리다이렉션

  • 302 Found 과 기능은 동일하지만, 일시 리다이렉트 시 요청 메서드와 본문을 유지한다

  • 즉, 클라이언트가 처음에 POST 메서드와 함께 생성할 리소스 정보를 Body 에 담아 전송하였다면, 새로운 URL 로 리다이렉트하더라도 그 메서드와 Body 내용이 유지되는 것이다.

  • 다만 첫 요청에 POST가 사용되었다면, 두번째 요청도 반드시 POST를 사용해야 한다.

  • 클라이언트가 요청한 리소스가 다른 URI에 있으며, 이전 요청과 동일한 메소드를 사용하여 요청해야 할 때 응답으로 이용된다.


303(See Other)

  • See Other ⇢다른 URL에서 리소스를 찾음 (일시 리다이렉션)

  • 302 Found 과 기능은 동일하게 일시 리다이렉트 시 요청 메서드가 GET로 고정되고 본문을 제거한다.

  • 다만 302 Found 와 다르게 요청 메서드의 변경과 본문 제거 행위를 무조건적으로 보장한다.

  • 따라서 클라이언트가 요청한 리소스를 다른 URI에서 GET 요청을 통해 얻어야 할 때, 서버가 클라이언트로 보내는 응답으로 이용된다.

  • 보통 PUT 또는 POST의 결과로서 요청에 대한 응답으로 클라에게 리소스의 위치를 알려주는 용도로 쓰인다.



특수 리다이렉션

300(Multiple Choices)

  • Multiple Choices ⇢ 요청에 대해서 둘 이상의 가능한 응답이 있음을 나타낸다.

  • 클라이언트가 동시에 여러 리소스를 가리키는 URL을 요청한 경우, 그 리소스의 목록과 함께 반환된다.

  • 어떤 서버가 하나의 HTML 문서를 영어와 프랑스어 모두로 제공하는 경우 등에 사용할 수 있다.

  • 그러나 응답 중 하나를 선택하는 표준화된 방법이 없기 때문에, 이 응답 코드는 실무에선 거의 사용되지 않는다.


304

  • Not Modified ⇢ 수정되지 않은 최신 리소스이니 캐시 이용하라

  • 리소스 복사본 상태가 수정 되지 않아 최신 상태이므로 캐시를 이용하라는 특수 리다이렉션

  • 즉, 클라이언트가 리소스를 요청했는데 서버로부터 304 응답이 오면, 클라이언트가 요청한 리소스가 수정되지 않은 최신 상태이니, 캐시에 가지고 있는 리소스를 그대로 사용해도 된다는 의미를 가진다. 따라서 클라이언트는 캐시에서 리소스를 재사용하게 되고 이를 통해 네트워크 트래픽을 줄일수 있게 된다.

  • 주의할 점은 304 응답 메시지는 Body 본문에 어떠한 데이터도 포함해서는 안된다. (클라이언트가 로컬에 있는 캐시에서 리소스를 가져와 사용하여야 하기 때문)

  • 304 응답 코드를 반환받기 위해선, 클라이언트는 If-Modified-Since 헤더 혹은 If-None-Match 헤더를 포함한 조건부 요청을 전송해야 한다.

  • 304 응답은 GET 과 HEAD 메소드에만 동작한다.


💡캐시(Cache) 와 리다이렉션(Redirection) 관계

304 상태 코드는 다른 URL을 전이하는게 아닌 캐시를 이용한 상태 코드인데 이것이 왜 3XX 리다이렉션과 무슨 관련이 있는 것일까?우선, 리다이렉션을 단순히 다른 URL로 전이시키는 것으로 이해하고만 있을텐데, 정확한 기술 의미는 페이지 단위의 실제 리소스, 폼 혹은 전체 웹 애플리케이션이 다른 URL에 위치하고 있는 상태에서 링크를 존속시키는 기술을 말한다.

따라서 로컬 캐시라고 할지라도 클라이언트 입장에선 멀리 떨어져있든 바로 옆에 있든 어쨋든 리소스 제공자 역할을 하는 서버(Server)로 치부하기 때문에 캐시를 다른 URL로 보아 캐시에 링크를 존속시키니까 리다이렉트라는 표현을 쓰는 것이다.




📑 참고 자료

인프런: 모든 개발자를 위한 HTTP웹 기본 지식

3XX (Redirection) 상태 코드 - 총정리 모음

This post is licensed under CC BY 4.0 by the author.