❒ Description
이번 주제는 HTTP 상태코드 중에서 리다이렉션에 관련된 300번대에 대해 자세히 알아볼 것이다.
주로 301 ~ 308에 대해서 알아볼 것이면 잘 사용되지 않는 300번은 제외 했다.
❒ Redirection 상태 코드 3xx
리다이렉션 상태코드는 요청을 완료하기 위해 클라이언트가의 추가 조치가 필요할 때 내려준다.
웹 브라우저는 리다이렉션 응답의 결과에 상태코드와 리다이렉션할 위치를 알려주는 Location 헤더가 있다.
일반적으로 리다이렉션 응답의 결과에 Location 헤더 정보를 포함시키는 것은 좋은 습관이라고 한다.
1. 영구 리다이렉션 (301, 308)
상태 코드 | 사유 구절 | 의미 |
301 | Moved Permanently | 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거(불확실) |
308 | Permanent Redirect | 리다이렉트시 요청 메서드와 본문 유지 |
- 영구 리다이렉션은 리소스의 URI가 영구적으로 이동하는 것을 말한다.
- 원래의 URL은 사용하지 않고,검색 엔진 등에서도 변경을 인지하게 된다.
- POST 요청의 경우에는 308 응답을 권장한다.
2. 일시 리다이렉션 (302, 303, 307)
상태 코드 | 사유 구절 | 의미 |
302 | Found | 리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거 불확실 |
303 | See Other | 리다이렉트 요청 메서드가 GET으로 변함 100% |
307 | Temporary Redirect | 리다이렉트시 요청 메서드와 본문 유지 100% |
- 302, 303, 307 모두 비슷한 기능을 한다.
3. 일시 리다이렉션과 영구 리다이렉션은 어떻게 구분하여 사용해야 할까?
일시 리다이렉션과 영구 리다이렉션을 구분하는 주체는 검색 엔진이라고 한다. 왜냐면 어떤 리다이렉션을 쓰는지에
따라 SEO에 미치는 영향이 크기 때문이다.
영구 리다이렉션은 기존 페이지는 검색 엔진 상 존재하지 않게 되며 영구적으로 다른 페이지로 대체되기 때문에
웹 사이트의 도메인을 변경하거나 사용하지 않는 페이지를 이동시킬 때 사용하면 적합하다.
반면에 일시 리다이렉션은 기존 페이지에 문제가 생겨서 페이지를 수정하거나, 상품이 품절 되었을 때,
주문 완료 페이지로 리다이렉션할 때 사용하면 적합하다.
❒ PRG : Post Redirect Get
PRG 패턴은 웹 애플리케이션에서 데이터의 중복 제출을 방지하기 위해 사용하는데, 예를 들면 결제 화면에서
클라이언트가 새로고침을 하게 된다면 중복 구매가 될 수도 있기 때문이다. 결과적으로 302(Found) 또는
303(See Other) 상태코드를 사용한 PRG 패턴을 적용하여 위 문제는 해결할 수 있게됐다.
❒ HTTP/1.0 과 HTTP/1.1의 리다이렉션 동작 차이
HTTP/1.0에서 리다이렉션 동작 명세는 302(Found) 상태코드를 받으면, 클라이언트는 Location 헤더에 있는
URL로 GET 요청을 보내야 한다. 즉, POST에서 GET으로 요청 방식이 바뀐다. 하지만 302의 경우 100% GET으로
변한다는 것이 보장되지 않는다. 왜냐면 클라이언트가 임의로 똑같은 메소드로 요청을 다시 보낼 수도 있기 때문이다.
반면 HTTP/1.1에서는 위와 같은 동작이 혼란을 줄 수 있기 때문에 보다 명확한 상태 코드인 303(See Other)을
추가했다. 303 상태코드는 클라이언트에게 Location 헤더에 명시된 URL로 GET 요청을 하라고 명시한다.
만약 이전 요청 메서드가 그대로 유지되어야 하는 경우, 307 상태코드를 사용하여 클라이언트가 같은 요청 메소드를
사용하도록 지시한다.
비록 명세에서는 303, 307을 권장하지만 현실적으로 이미 많은 애플리케이션 라이브러리들이 302을 기본값으로
사용하고 있다. 자동 리다이렉션시에 GET으로 변해도 상관없다면 그냥 302를 써도 큰 문제는 없다고 한다.
❒ Redirection 상태코드와 Cache
리다이렉션 상태코드 중 몇몇은 리소스에 대란 애플리케이션의 로컬 복사본이 원래 서버와 비교했을 때
유효한지, 즉 변경여부를 확인하기 위해서 사용하는데 그 중 하나가 304(Not Modified)이다.
클라이언트가 리소스를 요청했는데 서버로부터 304 응답이 오면, 클라이언트가 요청한 리소스가 수정되지 않은
최신 상태이니, 캐시에 가지고 있는 리소스를 그대로 사용해도 된다는 의미를 가진다. 따라서 클라이언트는 캐시에서
리소스를 재사용하게 되고 이를 통해 네트워크 트래픽을 줄일수 있게 된다.
1. Caching
캐싱을 하기 위해서는 HTTP/1.1 부터 도입된 일반 캐시 헤더 `Cache-Control`을 사용하면 된다.
- 클라이언트가 어떤 리소스를 요청한다.
- 서버는 Cache-Control: max-age=60과 같이 일반 헤더를 설정 후 응답을 한다.
- 클라이언트는 응답 결과를 바탕으로 브라우저 캐시에 해당 리소스를 저장한다.
- 똑같은 리소스를 재요청할 경우 브라우저 캐시에서 리소스를 받는다.
2. 엔티티 캐싱(검증) 헤더 & 조건부 헤더
위에 과정에서 캐시 유효 시간이 초과했을 때 서버에 요청을 보내야 한다. 하지만 캐시 유효기간이 만료되었더라도
리소스는 변경되지 않았을 수도 있다. 이때 서버의 데이터와 캐시 데이터가 동일한지 확인하는 절차가 필요하다.
1. 첫번째 요청
기존에는 응답할 때 일반 헤더에 Cache-Control 만 넣어줬다면, 이번에는 Last-Modified 헤더를 추가로
넣어줘야 한다. 참고로 Cache-Control, Last-Modified 두 헤더 모두 응답과 요청 타입의 메시지에 모두
나타낼 수 있다.
Last-Modified는 서버의 리소스의 최종 수정일을 나타낸다.
HTTP/1.1 200 OK |
Content-Type: image/jpeg |
cache-control: max-age=60 |
Last-Modified: 2024년08월10일 20:00:00 |
Content-Length: 99999 |
ajskldjvklavniqnjkvnalknsivajsldkjfklqjn3... |
위 응답을 바탕으로 브라우저는 해당 리소스를 캐싱한다.
2. 두 번째 요청(캐시 시간 초과)
`if-modified-since` 헤더를 넣어서 서버에 요청을 보낸다.
GET /xxx.jpeg |
if-modified-since: 2024년08월10일 20:00:00 |
만약에 서버의 리소스의 최종 수정일과 if-modified-since 값이 동일한 경우,
데이터가 수정되지 않은 것이다. 이때 서버는 다음 응답을 클라이언트에게 전달한다.
HTTP/1.1 304 Not Modified |
Content-Type: image/jpeg |
cache-control: max-age=60 |
Last-Modified: 2024년08월10일 20:00:00 |
Content-Length: 99999 |
Body는 없어야 한다. |
이 때 주의할 점은 HTTP Body 본문에는 어떠한 데이터도 넣어선 안된다. 왜냐면 클라이언트가
로컬에 있는 캐시에서 리소스를 가져와서 사용해야 하기 때문이다.
Last-Modified와 If-Modified-Since에도 단점은 있다.
- 1초 미만 단위로 캐시 조정이 불가능
- 날짜 기반의 로직 사용
- 데이터 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우
- 서버에서 별도의 캐시 로직을 관리하고 싶은 경우
3. 엔티티 캐싱(검증) 헤더 & 조건부 헤더 2
이번에는 검증 헤더로 `ETag`를, 조건부 헤더로 `If-None-Match`를 사용해 볼 것이다.
ETag 헤더는 메시지에 담겨있는 엔티티를 위한 태그를 제공한다. 이 엔티티 태그는 리소스를 식별할 수 있는 수단이다.
1. 응답 기반으로 캐시 적용
HTTP/1.1 200 OK |
Content-Type: image/jpeg |
cache-control: max-age=60 |
ETag: "gilbert" |
Content-Length: 99999 |
2. 검증 헤더 추가
GET /xxx.jpeg |
if-none-match: "gilbert" |
3. 응답 기반으로 캐시 적용
HTTP/1.1 304 Not Modified |
Content-Type: image/jpeg |
cache-control: max-age=60 |
ETag: "gilbert" |
Content-Length: 99999 |
Body는 없어야 한다. |
이 방식으로 캐시를 검증을 하면 캐시 제어 로직을 100% 서버에서 관리할 수 있다.
따라서 클라이언트는 캐시 로직에 대해 전혀 몰라도 되며 그냥 데이터를 가져가 쓰기만 하면 된다.
❒ 예상 면접 질문
1. 리다이렉션 코드에서 304는 어떤 의미를 나타내는 상태코드인가요?
304는 Not Modified로, 로컬 캐시의 데이터와 서버의 데이터가 동일한 상태인지를 알려주는 상태코드입니다.
Last-Modified나 ETag를 보고 변경 여부를 확인할 수 있습니다.
2. 302,303,307은 어떤 차이가 있나요?
우선 세 상태코드 모두 일시 리다이렉션을 나타내는 상태코드입니다.
HTTP1.0에서는 302가 나왔고, HTTP/1.1에 303, 307이 도입되었습니다.
302(Found)는 리다이렉션 시 GET으로 요청을 보내야하는데 100% 보장하지 않습니다.
303(See Other)은 리다이렉션 시 GET으로 요청을 보내야하는데 GET으로 요청을 변경하라고 명시되어있습니다.
307(Temporary Redirection) 리다이렉션 시 최초 요청 메소드와 동일하게 요청을 해야합니다.
2-1. 302와 303은 똑같은 거 같은데 왜 굳이 303을 쓰나요?
302는 Found로 일단 리다이렉트라는 의미를 찾아보기 힘듭니다. 따라서 클라이언트에게
혼선을 줄 수 있습니다. 이러한 혼선을 없애기 위해서 보다 더 직관적인 303(See Other)
상태코드가 도입되었고 이는 GET으로 요청을 변경하라고 명시가 되어있습니다.
근데 이미 많은 애플리케이션에서 302을 default로 사용하고 있기 때문에,
그냥 302를 써도 큰 문제는 없다고 알고 있습니다.
'CS > Network' 카테고리의 다른 글
HTTP Connection Management (0) | 2024.08.14 |
---|---|
TCP 제대로 이해하기 (0) | 2024.08.14 |
계층별 네트워크 기기 (0) | 2024.08.05 |
TCP/IP 4계층 모델 (0) | 2024.07.28 |
네트워크의 기초 (0) | 2024.07.27 |