우클릭방지

글 목록

2017년 8월 17일 목요일

[HTTP 프로토콜 강좌]#19 HTTP 일반 헤더 I - Cache-Control, Connection, Date, Pragma, User-Agent


이번 주 광복절을 끼고 수요일까지 여름 휴가를 다녀왔다. 때문에 새 글에 대한 포스팅이 늦었다.

오늘은 HTTP 일반 헤더(General Header) 에 대한 내용이다. 일반 헤더는 요청과 응답 모두 사용될 수 있는 헤더이다.

그 목적과 의미가 각각 다르니, 아래 내용을 잘 참고해서 숙지하도록 하자.
특히 Cache-Control 헤더는 HTTP 프로토콜에서 매우 중요한 부분이니 잘 알아두면 좋다.


1. Cache-Control

Cache-Control 헤더는 캐시(Cache) 동작과 관련된 아주 중요한 헤더이다. HTTP 프로토콜에서 캐시의 중요성이 쾌 큰편이므로 아주 잘 알아둘 필요가 있다.
값으로 여러 항목이 존재하며, 항목마다 의미와 목적이 다르다. 여러 항목이 존재하는 경우에는 콤마(,)로 각각의 항목을 구분한다.

다음은 Cache-Control에 사용될 수 있는 각각의 항목을 정리해 놓은 것이다.

항목 파라미터 요청 응답
max-age 필요 O O
max-stale 옵션 O
min-fresh 필요 O
must-revalidate 없음 O
no-cache 옵션 O O
no-store 없음 O O
no-transform 없음 O O
only-if-cached 없음 O
private 옵션 O
proxy-revalidate 없음 O
public 없음 O
s-maxage 필요 O



max-age
max-age는 요청과 응답에서 모두 사용할 수 있다.
max-age 를 서버에서 사용하게 되면, 캐시서버에서 캐싱하고 있는 컨텐츠의 유효기간을 정의하는 것이다. 서버로 다시 확인하지 않고 클라이언트에게 제공할 수 있는 최대 시간이다.
Expires 헤더와 비슷하지만, 두 헤더가 모두 존재하는 경우 캐시서버는 Expires 헤더를 무시한다.

참고: HTTP 1.0 에서는 Cache-Control의 max-age 헤더가 무시된다. 따라서 캐시서버가 HTTP 1.0 또는 1.1 두 버젼 중 지원하는 버젼을 모를경우 Expires 와 Cache-Control의 max-age를 같이 사용하면 좋다. 

max-age 값이 클라이언트에게서 사용되는 경우에는 클라이언트가 캐싱된 이미지를 사용하는 기준을 정하게 되는 것이다.
예를 들어 캐시서버에 저장된 컨텐츠가 실제 서버에 있는 컨텐츠와 같다고 하더라도.. 클라이언트가 정의한 max-age 값보다 크다면,  캐시서버는 자신이 가지고 있는 컨텐츠를 직접 제공하지 못한다.
극단적으로 클라이언트가 max-age 값을 '0' 으로 정하게 되면, 캐시서버는 항상 실제서버로 요청을 전달하여 유효성을 매번 확인해야 한다.
캐시서버의 목적이 유효한 컨텐츠의 경우 서버로 요청을 전달하지 않게 하여 웹서버의 성능 향상을 도모하는것이 주인데 이러한 경우 효과를 기대할 수 없게 된다.

max-stale
max-stale 은 요청에서 사용되는 헤더 정보이다.
max-stale 은 만료된 컨텐츠라 하더라도 캐싱된 컨텐츠가 있다면 사용하겠다는 뜻이다. 클라이언트는 또한 만료된 컨텐츠의 재활용 가능 시간을 정할 수가 있는데 다음과 같은 형식으로 사용한다.

Cache-Control: max-stale=600

위와 같이 max-stale 의 값으로 600 을 명시한 경우, 만료된 컨텐츠는 이후 10분까지 재사용할 수 있다는 것을 의미한다.

min-fresh
min-fresh 도 요청에서 사용되는 정보이다.
클라이언트가 요청하는 컨텐츠가 현재도 유효해야 겠지만, 이후 수초 동안에도 변경되지 않았으면 하는 경우.. min-fresh 에 값을 정의하여 사용하면 된다.  다음 예를 보자.

Cache-Control: min-fresh=60

현재 요청하는 컨텐츠가 지금을 기준으로 이후 60초 동안 변경되지 않을 것이라면 캐싱된 컨텐츠를 직접 제공하라.. 라는 의미인것이다.

must-revalidate
must-revalidate 는 응답헤더에 사용되는 정보인데, 컨텐츠의 유효성을 최대한 보장하기 위한 것이다. 이후 요청에서 캐싱된 컨텐츠라 하더라도 반드시 웹서버로부터 유효성 체크를 받아야 한다는 뜻이다.

또한, 클라이언트가 max-stale 을 이용하면 유효하지 않은 컨텐츠라도 캐싱된 것을 이용할 수 있다. 이 경우 유효하지 않은 컨텐츠가 클라이언트에게 제공될 수 있는데 must-revalidate은 이것을 방지하기 위해 사용되는 정보이다.

Cache-Control: must-revalidate

응답헤더에 위 정보가 포함되게 되면, 캐시서버는 이후 동일한 컨텐츠에 max-stale 정보가 있다고 하더라도 이를 무시한다. 즉, 만료된 컨텐츠는 사용하지 않게 한다

no-cache
no-cache는 요청과 응답 모두 사용된다.
클라이언트의 요청에 no-cache 정보가 포함되어 있다면, 말 그대로 캐시서버에게 캐싱된 컨텐츠가 있다고 하더라도 실제 웹서버에게서 컨텐츠를 제공받고 싶다는 의미이다.
no-cache는 'max-age=0' 과 어찌 보면 동작면에서 비슷하지만 약간의 차이가 있긴 하다. no-cache의 경우는 컨텐츠 자체를 웹서버에게서 받겠다는 것인 반면, max-age=0 은 캐싱된 컨텐츠의 유효성을 웹서버에게서 확인받겠다는 뜻이다.
다시 말하면.... no-cache는 컨텐츠를 웹서버에게서 받아 오는 것이고, max-age=0 은 캐시서버가 가지고 있는 컨텐츠의 유효성을 웹서버에게서 체크해서 유효하다면 캐시서버로부터 컨텐츠를 받아 오는 것이다.

서버의 응답에 no-cache가 존재하는 경우 웹서버는 캐시서버에게 다음을 요구한다.
'다음번 요청에 유효성 확인을 하지 않고 캐싱된 컨텐츠를 사용하지 말아 달라'
이는 웹서버가 강제로 캐시서버에게 유효성 확인을 주문하고자 할때 사용하는 것이다.

Cache-Control: no-cache="Accept-Ranges"

위와 헤더 정보가 응답에 포함된 경우, Accept-Ranges 가 응답헤더에 포함되지 않은 경우에만 캐싱된 컨텐츠를 사용하고, 포함된 경우에는 유효성 체크를 해야 한다는 의미이다.

no-store
요청과 응답에 모두 사용될 수 있는 정보이며, 말그대로 캐시서버에게 컨텐츠를 저장하지 말라고 하는 것이다. 스토리지에 저장되지 않으면 캐시서버로써의 역할을 할 수 없음을 우리는 연결해서 생각해 볼 수 있다.

매우 민감한 정보(예를 들어 주민번호와 같은 개인정보)가 포함된 컨텐츠인 경우 보안을 이유로 다른 매체에 저장되는 것을 방지하고 싶을 수 있다. 이 경우 해당 컨텐츠에 대해 no-store 를 정의하게 되면 캐시서버는 자신의 스토리지에 저장하지 않게 된다.

no-transform
이것도 요청과 응답에 모두 사용될 수 있는 정보이다. no-transform은 웹서버가 제공한 컨텐츠를 어떤 형태로도 변형하면 안된다는 것을 요구할 때 사용한다.
예를 들어 이미지 파일의 경우 해상도등을 캐시서버의 저장공간의 효율성을 위해 해상도를 낮추어 저장할 수도 있는데.. 이러한 행위를 하지 말라는 뜻이다.

only-if-cached
요청에만 사용되는 정보이다. 말 그대로 캐시서버에게 만약 캐싱하고 있는 컨텐츠라면 응답해달라는 뜻이다.
그렇다면 캐싱하지 않은 컨텐츠라면.. .??
그렇다. 웹서버에게 가지 않고.. 그냥 에러 메시지를 반환하게 된다.
이때의 에러 메시지는 "504 Gateway Timeout" 이다 .

네트워크 환경이 너무 열악하여, 캐시서버까지는 빠른 반면, 실제 웹서버까지는 지연(Delay)이 너무 심한 경우 캐시서버가 캐싱하고 있는 컨텐츠에 한해서 제공받겠다는 의미이다.
사실 이런 상황이 없다고 봐도 되기에  사용되지 않는 정보로 봐도 될것 같다.

private
응답에 사용되는 정보이며, 특정 사용자만을 위한 헤더 정보라 보면 된다.
캐시서버가 캐싱하고 있는 컨텐츠를 최초 요청했던 사용자에게만 제공해야 하는 경우 사용된다.
이 경우 다른 사용자에게는 캐싱하고 있는 컨텐츠라 하더라도 절대 제공되지 않는다.

proxy-revalidate
응답에 사용되는 정보이다.
중간에 있는 프록시 서버(캐시서버)들은 자신이 캐싱하고 있는 컨텐츠라 할지라도 웹서버로부터 컨텐츠 유효성 체크를 받아야 한다는 것을 뜻한다.
must-revalidate 과 거의 비슷하지만, proxy-revalidate 은 클라이언트 자신의 캐싱 컨텐츠에 대해서는 유효성 체크 없이 그대로 사용할 수 있다는 차이가 있다.
must-revalidate 은 웹브라우저가 캐싱하고 있는 컨텐츠에 대해서도 직접 사용하지 못하고 유효성을 체크 받아야 하나 proxy-revalidate 은 프록시 서버(캐시서버)들만 유효성 체크를 받으면 된다는 뜻이다.

public
이것은 private 과 반대되는 의미이다.
private 은 특정 사용자에 한해서 캐싱된 컨턴츠를 이용할 수 있었다면, public은 그렇지 않다. 모든 사용자가 이용할 수 있다. 클라이언트가 인증정보를 제공한다고 하더라도 캐시서버는 private user 처럼 처리한다. 인증정보에 상관없이 캐싱된 컨텐츠를 제공한다는 뜻이다.

s-maxage 
이는 max-age와 사용 목적에서는 같다. 응답에서만 사용되는 정보이다.
max-age 와 다른 점은 다수의 사용자들에게 컨텐츠를 제공하는 형태의 공용 캐시서버에게만 유효 하다는 것이다.
웹브라우저와 같은 클라이언트의 로컬 캐시에는 적용되지 않는다.




2. Connection

Connection 헤더는 두가지 기능이 있다.

그중 첫번째..
Connection 헤더는 중간에 위치한 프록시 서버에게 실제 서버로 전달하지 말아야 할 헤더를 알려주는 역할을 한다.

다음 그림처럼 프록시서버를 통해 실제 웹서버로 전달되지 말아야 할 헤더 정보(Upgrade 헤더 정보)를 Connection에 명시하면, 프록시 서버는 명시된 헤더는 실제 웹서버로 전달하지 않는다.


그런데 사실 실제에서 활용되는 사례를 찾기가 좀 힘들긴 했다.
그래도 내용에 있으니 이 기능에 대해서는 알고 넘어가는게 좋을것 같다.

다음 두번째..
HTTP는 Connection 헤더를 통해 연결 유지 기능(Persist Connection)을 관리한다.
Connection 헤더를 통해 연결을 즉시 끊을 수도 있고, 또는 연결 유지를 지속적으로 할 수 있기도 하다.

연결 유지에 대해서는 이전 강좌에서 자세히 알아 본적이 있다.
(자세한 내용은 여기 를 통해 확인이 가능하다.)

연결 유지(Persist Connection)는 HTTP 1.1 의 기본 동작이다.
하나의 TCP 연결을 통해 동일한 웹서버에 여러개의 HTTP 트랜잭션을 수행할 수 있는 것.. 이것이 바로 연결 유지를 통해 가능한 것이다.

연결 유지 기능을 사용하지 않고자 하는 경우에는 아래처럼 Connection 헤더에 close 값을 명시하면 된다.

Connection: close

웹서버는 해당 요청을 받게 되면 요청한 컨텐츠에 대해 응답하고 바로 세션을 끊게 된다.
Connection: close 는 요청 또는 응답 모두 사용될 수 있다.

반대로 연결 유지 기능을 사용하고자 하는 경우에는 아래처럼 Connection 헤더에 내용을 담으면 된다.

GET / HTTP /1.1
Connection: Keep-Alive
Keep-Alive: timeout=10

Connection: Keep-Alive 를 통해 연결 유지 기능을 사용할 것을 알리는 것이고, Keep-Alive 헤더는 옵션이다. Keep-Alive 헤더를 통해서는 연결 유지를 얼마나 할것인지 초단위로 정의가 가능하다.

웹서버가 연결 유지를 지원하는 경우 아래와 같은 응답헤더 내용을 볼 수 있다.

HTTP /1.1 200 OK
Connection: Keep-Alive
Keep-Alive: timeout=10, max=120
Content-Type: text/html
                                 
....                               

응답 헤더에서도 역시 Connection: Keep-Alive 를 통해 연결 유지 기능을 사용할 수 있음을 확인 할 수 있다. 마찬가지로 Keep-Alive 헤더는 연결 유지에 대한 옵션 정보 이다.

아래는 실제 다음(www.daum.net) 과 보배드림의 메인 페이지를 접속한 헤더 정보이다.
먼저 다음의 메인페이지...


클라이언트는 연결유지를 사용하기 위해 Connection: Keep-Alive 정보를 같이 보냈다.
하지만, 서버는 연결유지를 사용하지 않고 응답과 함께 세션을 끊어버린다.
아마도.. HTTP 요청에 대해 HTTPS 접속으로 리다이렉트 하기 위한 것으로 보인다.
(HTTP 요청에 대해서는 끊어버리고, 새로 HTTPS 접속을 해야 하기 때문에....)

두번째는 보배드림 메인페이지..



이 경우는 클라이언트와 서버에서 모두 연결 유지를 사용한다. 단, 서버에서 연결 유지를 얼만큼 할것인지에 대해 추가적인 정보를 Keep-alive 헤더를 통해 전달하는 경우이다.








3. Date

Date 헤더는 웹서버가 클라이언트의 요청에 응답한 시간을 표시한다.
간혹 Date 헤더 값을 컨텐츠 자체의 생성/수정된 시간으로 알고 있을 수 있는데 이는 잘못된 정보이다.
컨텐츠 자체의 생성/수정된 시간은 Last-Modified 라는 헤더에서 표시하고 있다. (Last-Modified 헤더는 이후 강좌에서 다시 이야기 하기로 한다.)

HTTP 1.1에서는 아래 형식으로 시간 정보를 표시하고 있다.  아래 형식은 RFC 1123에 정의되어 있다.

Date: Thu, 17 Aug 2017 05:52:23 GMT

HTTP 1.1 이전 버젼에서 사용되었던 시간 포맷인 다음과 같은 두가지 형태도 HTTP 1.1에서는 처리할 수 있다.

먼저, RFC 850에 정의된 바와 같은..
Date: Thursday, 17-Aug-17 05:52:23 GMT

C-Language 라이브러리 표준 형태인..
Date: Thu Aug 17 05:52:23 2017

위 두가지 형태는 참고삼아 알아두자.

HTTP에서는 Date 정보를 웹서버에서 응답할 때 반드시 포함하도록 하고 있다. 다만, 다음과 같은 경우는 포함하지 않을 수 있는데..

상태 코드가 "100 Continue" 와 "101 Switching Protocols" 인 경우가 그렇다.
또한, 서버 에러인 (예를 들면, 500 Internal Server Error) 경우와 웹서버가 유효한 date 정보를 생성하지 못하는 경우에도 마찬가지로 포함하지 않을 수 있다.




4. Pragma

Pragma 헤더는 HTTP 1.1 이전 버젼에서 사용되었던 것이었는데, HTTP 1.1로 넘어오면서 삭제되지 않고 남은 잔존물 같은 존재이다.
HTTP 1.1에서는 Pragma에 대해서는 다음 한가지 경우만이 사용되고 있다.

Pragma: no-cache

위 예의 의미는 Cache-Control에서 다룬것과 같이 중간에 캐시서버가 캐싱하고 있는 컨텐츠를 제공하지 말라는 의미이다.

서버에서 사용되는 경우는 중간의 캐시서버가 응답한 컨텐츠를 저장하지 말것을 요구하는 내용이다.

즉, 위 Pragma: no-cache 가 요청이건 응답이건 포함되어 있는 경우에는 캐시서버의 캐싱 동작 자체를 거부하는 뜻이 된다.

앞서 내용에서 다뤘지만, 캐시서버의 동작을 거부하려면, Expires 헤더와, Cache-Control 을 이용하는게 HTTP 1.1에서는 더욱 바람직한 방법이다.


5. User-Agent

우리가 이전 강좌를 통해 Server 헤더에 대해 알아본 적이 있다.
(Server 헤더의 제사한 내용은 여기 를 클릭하여 확인할 수 있음)

Server 헤더가 응답하는 웹서버의 종류를 표시하는 것이었다면, User-Agent는 요청하는 클라이언트의 웹 브라우저 종류를 표시한다.

우리가 IE를 사용하는지 또는 크롬, 파이어폭스, 사파리 등 어떤 웹브라우저를 사용하는지 User-Agent 에 정보를 담아 전송한다.

다음은 실제 User-Agent 의 사용 예이다. 참고하면 좋겠다.


최근에는 User-Agent 를 이용하여 모바일 디바이스를 구분하기도 하고, 접근을 제어하기도 한다.

이상 끝!~

댓글 없음:

댓글 쓰기