우클릭방지

글 목록

레이블이 HTTP인 게시물을 표시합니다. 모든 게시물 표시
레이블이 HTTP인 게시물을 표시합니다. 모든 게시물 표시

2017년 10월 31일 화요일

[HTTP 프로토콜 강좌]#30 Proxy 와 사용자 IP - x-forwarded-for 헤더

오늘은 HTTP 프로토콜 강좌의 마지막 시간이다. 
6월 말부터 지금까지 약 4개월 정도를 "HTTP 프로토콜 강좌"에 대해 포스팅한 것 같다. 

여러가지 내용이 있었으나, 웹프록시(Proxy)는 HTTP 프로토콜 강좌의 많은 부분을 차지 한다. 웹프록시 기반의 캐시라는 녀석이 있으니.. 당연한게 아니겠는가?
더욱이 최근 시장에 소개되는 웹가속기, SSL 가속기, 웹방화벽, ADC 스위치의 L7 스위칭 기능들이 모두 웹 프록시를 기반으로 하고 있다. 

클라이언트와 웹서버사이에서 동작하는 웹프록시는 특히 웹서비스 측면에서 이점을 주는데 제약사항이 없을까?

당연히 존재한다. 오늘은 이에 대한 이야기를 해 보려한다. 

웹프록시 동작에서의 사용자 IP 변환

웹프록시가 클라이언트와 웹서버 사이에 존재하게 되면, 클라이언트에게는 웹서버인것처럼... 웹서버에게는 클라이언트인것 처럼 동작을 하게 된다. 

다시 또 이야기 하지만, 아래 그림과 같이 웹프록시를 기준으로 TCP 세션이 구분된다.

  • 1~3번 과정 : TCP 세션 수립
    • 클라이언트는 웹서버와 세션을 맺으려고 시도하나, 실제로는 웹프록시와 TCP 세션을 맺게 된다. 
  • 4번 과정 : HTTP 요청 전달
  • 5~7번 과정 : TCP 세션 수립
    • 웹서버는 클라이언트와 세션을 수립하는게 아니고 웹프록시와 TCP 세션을 맺는다.
  • 8번 과정 : 클라이언트로부터 받은 HTTP 요청 전달
위와 같은 일련의 과정을 "Delayed Binding (지연 바인딩)" 이라 부르기도 한다. 

바로 이런 지연바인딩의 동작에서 변경되는 사항이 있는데, 그게 바로 소스 IP 의 변경이다. 5번부터 시작되는 웹프록시와 웹서버간의 동작에서 소스 IP 가 웹프록시 IP로 변경된다. 

따라서 웹서버는 실제 사용자의 IP를 확인하지 못한다. 




IP 변경에 따른 고려사항

사용자의 IP가 변경되게 되면, 일단, 웹서버에서는 고민거리가 생기게 된다. 
웹서버는 처리하는 모든 트랜잭션에 대한 로그를 남기는데, 이런 웹로그에 사용자 IP를 구분할 수 없게 된다. 나중에 문제가 생겨 웹로그를 참고해야 할 상황이 생긴다면 이런 경우는 크나큰 낭패가 아닐수 없다. 

또한 사용자 IP 기반으로 동작하는 웹어플리케이션 로직이 있다면.. 이 역시 IP 변경시 문제가 된다. 

웹서버 또는 웹어플리케이션 뿐만 아니라.. 웹프록시와 웹서버 사이에 존재하는 네트워크 장비등에서도 운영에 문제가 발생한다. 
IP 기반의 ACL Rule 등을 활용하기가 힘들어진다.
네트워크 방화벽이 존재한다면.. 같은 제약사항이 발생하는것이다. 

이처럼 사용자 IP 기반으로한 정책들이 있다면, 웹프록시로 인한 사용자 IP 변경은 운영에 큰 영향을 미칠수 있는 중요한 요소가 된다.


x-forwarded-for 헤더를 이용한 사용자 IP 구분

위 고려사항을 모두 해결할 수는 없겠으나, 웹로그 및 웹 애플리케이션 로직상 사용자 IP를 구분할 수 있게 해주는 방안이 있다. 

그건 바로 "x-forwarded-for" 헤더이다. 

웹프록시는 자신이 처리한 클라이언트의 HTTP 요청을 웹서버로 전달하는 과정에서 x-forwarded-for 헤더정보를 추가하여 실제 사용자 IP를 알려준다. 

다음 그림을 보자.


클라이언트의 요청이 웹프록시를 통해서 웹서버로 전달되는 과정의 HTTP 헤더 정보이다. 
그림에서와 같이 웹프록시를 통해 웹서버로 전달되는 요청에서 보면, "x-forwarded-for" 헤더가 추가됨을 볼수 있다. 




x-forwarded-for 헤더의 정보에는 실제 사용자의 IP 가 담겨 있음을 확인할 수 있다. 

웹서버에서는 기존의 웹로그에서 사용자의 IP를 남기는 부분을 IP헤더가 아닌 x-forwarded-for 헤더의 정보를 참고하도록 하면 되며, 웹 애플리케이션의 로직에서도 마찬가지로 x-forwarded-for 헤더 정보를 참고하게 변경하면 사용자 IP 변경을 어느정도 대응할 수 있다. 

그동안 HTTP 프로토콜 강좌를 관심있게 봐주신 여러 독자 분들께 진심으로 감사의 말씀을 전한다. 

앞으로도 기술적으로 정리할 내용이 있다면, 최대한 쉽고 알차게 정리할 수 있도록 노력하겠다. 

끝~



2017년 10월 24일 화요일

[HTTP 프로토콜 강좌]#29 HTTP 가속 - TCP Multiplexing

오늘이 HTTP 가속 기술의 마지막 시간이다.

HTTP 프로토콜 강좌를 시작한지 약 4개월 정도 된것 같다.
거의 다 왔다. 이번 포스팅과 다음 포스팅까지해서 30개의 강좌를 끝으로 마무리하려 한다.

하지만, 기술은 항상 변하고 또 변한다.
이후 정리할 내용이 더 있다고 생각되면, 포스팅을 멈추진 않을 계획이다.

TCP Multiplexing

강좌 초반 HTTP 기본 동작에 대해 다음과 같이 설명한 바 있다.

"HTTP는 어플리케이션 영역으로 TCP 연결 기반위에서 동작한다"

그럼 단순한 HTTP 메시지 교환의 동작 흐름을 다시 좀 살펴보자.


HTTP 메시지를 전달하기 위해서는 반드시 TCP 세션을 먼저 연결해야 하고, 메시지 교환이 완료되면 TCP 연결을 종료해야 한다.

이런 사용자의 수가 많다고 가정하게 되면.. 본연의 HTTP 요청과 응답을 처리하는 것과 함께 TCP 연결을 맺고 끊는 것을 잘 관리 해야 하는 동작이 필요하다.
TCP 연결 관리에 대한 부담이 사실 웹서버의 성능에 직접적으로 관련되는 요소가 되는 것이다.

TCP 커넥션의 부하를 줄이기 위한 HTTP 프로토콜의 기술이 2가지가 있었다.
기억할 것이다. 그것은 바로


  1. Persistence
  2. Pipelining


이다.

이에 대한 세부 내용은 여기 를 클릭하여 해당 강좌를 참고하도록 하자.

간단히 이야기 하면..
Persistence 는 TCP 세션의 재사용 기술이고, Pipelining 은 HTTP 트랜잭션들의 순차처리가 아닌 병행처리를 지원하는 기술이다.



위 2가지 기술들을 활용하여 웹서버의 TCP 부하를 획기적으로 줄이는 장비가 있다.
초기에는 이를 "TCP Processor" 라고 칭했으나, 요즘은 ADC 스위치나 웹가속기에 이 기능이 포함되어 있다.

이 장비는 앞서 강의했던 SSL 가속기와 같이 클라이언트와 웹서버 사이에 놓이게 되며, TCP 세션을 중간에서 중개해 주는 일종의 세션 Proxy 같은 역할을 수행하는 형식이다.

그림으로 살펴 보면 아래와 같다.

위와 같이 4명의 클라이언트가 웹서버에 접속한다고 가정한다면..
웹서는 4개의 TCP 세션과 4개의 HTTP 요청을 처리해야 한다.

하지만, 클라이언트와 웹서버 중간에 TCP Processor 역할을 하는 장비가 놓이게 된다면, 웹서버는 1개의 TCP 세션과 4개의 HTTP 요청을 처리하게 된다.
TCP Processor 가 TCP 세션의 부담을 줄여주기 때문이다.

통상 장비마다 동작하는 알고리즘에는 차이가 있을지 모르지만, 궁극적으로 구현하려는 모양은 위와 같다.

최초 접속하는 클라이언트의 TCP 세션을 재활용하는 방식으로 동작하는것이 통상적이긴 하다.



이 기술에는 한가지 유념해야 할 사항이 있다.
위 기술을 이용해서 웹서버의 TCP 세션에 대한 부담을 줄여줄 수는 있으나, TCP 세션을 재활용하기 때문에 한가지 제약사항이 따른다. 바로 클라이언트의 IP가 NAT되는 점이다.

TCP는 IP 기반위에서 동작하는 프로토콜이다. TCP 세션을 재활용하는 것은 IP를 재활용하는 의미와 같다.
따라서 재활용되는 세션상에서 처리되는 클라이언트의 HTTP 요청은 모두 사용자의 IP가 변경된다고 보는게 맞다.

이런 환경에서 사용자의 IP를 구분하기 위해서는 HTTP 헤더의 "X-forwarded-for" 를 사용할 수 있는데, 이에 대해서는 다음 강좌에서 다루기로 한다.

여기까지 해서 HTTP 가속 이란 주제의 강좌를 마무리한다.

2017년 10월 13일 금요일

[HTTP 프로토콜 강좌]#28 HTTP 가속 - SSL Termination

오랜만의 포스팅이 된다.

10여일의 길고도 긴 추석명절이 지났다. 명절이 길면 길수록 다시 일상으로 복귀하게 될때의 피로도는 비례적으로 높은것 같다.

오늘은 HTTP의 보안성을 향상시킬 수 있는 SSL 에 대한 이야기를 하려한다.

SSL 그리고 TLS

HTTP는 클라이언트와 웹서버간 통신을 시켜주는 프로토콜이다.
HTTP라는 프로토콜을 이용해서 클라이언트와 웹서버는 서로 메시지 / 데어터를 주고 받지만, 불행하게도 보안성을 제공하지는 않는다.

즉, 클라이언트와 웹서버간 전달하는 메시지 또는 데이터에 개인정보(아이디,비밀번호,주민번호등)가 포함되어 있는 경우에는 중간자가 모두 내용을 들여다 볼수 있다는 뜻이다.

웹(WEB) 이 발전하여 생활의 근간시스템을 제공하면서 보안성에 대한 요구는 점차 증가하였다.
이를 해결하고자 등장한것이 SSL (Secure Socket Layer) 이다.
SSL 은 넷스케이프사가 개발한 것으로 클라이언트와 웹서버간 전달하는 메시지나 데이터를 암호화 하여 중간자가 이를 확인하지 못하게 한다.

SSL 의 필요성이 점차 증가하게 되면서 이에 대한 표준화 요구 역시 생기게 된다. IETF 기구가 넷스케이프사의 SSL 을 기반으로 표준화를 하게 되는데, 바로 SSL을 표준화 한것이 TLS이다.

TLS(Transport Layer Security) 의 초기 버젼은 사실 SSL과 차이가 없었다.
허나, 지금은 여러가지 측면의 기능을 넣고, 발전시킴으로 인해 현재는 1.3까지 공식적으로 소개되고 있다.

TLS라는 용어를 사용하는게 맞지만.. SSL 의 초반 이미지가 너무 강했던 탓일까? TLS로 바뀐뒤에도 여전히 SSL 이라는 용어로 이를 대신하고 있긴 하다.

HTTP 에 SSL 을 이용하여 전송되는 메시지 / 데이터를 암호화 한것을 HTTPS 라고 부르며, 맨뒤의 'S'는 예상했겠지만, Secure 를 의미한다.





일반적인 HTTPS 처리

그럼 HTTPS 를 이용한 통신은 어떻게 이루어지는 지 살펴보자.

HTTP 통신은 TCP 기반위에서 동작하는 프로토콜이므로, TCP 세션이 정상적으로 만들어지고 난 후 메시지 또는 데이터 교환이 이루어진다.

HTTPS 역시 TCP 기반 위에서 동작하는 프로토콜이다.
다만, 클라이언트와 웹서버가 데이터를 전송하기 전 데이터를 암호화할 사전 정보를 교환하는 과정이 추가될 뿐이다.

이 과정을 SSL Handshake 또는 SSL Negotiation 이라고 하는데 다음 그림과 같은 과정을 밟는다.

먼저, 1번과 2번의 Client Hello와 Server Hello 과정에서 서로 암호화에 사용할 알고리즘을 결정한다.
클라이언트가 자신이 지원하는 암호화 알고리즘을 모두 나열하게 되면, 웹서버는 이를 검토하고 자신 역시 지원하는 알고리즘 중 보안성이 가장 높은 것을 선택하게 된다.

암호화 알고리즘이 결정되면 3번에 해당하는 과정에서 데이터를 암호화하는데 사용할 키를 서로 교환하게 된다.  전달되는 키는 보안성 때문에 2번과정에서의 Certificate 에 포함된 웹서버의 공개키로 암호화 하여 안전하게 전달한다.

4,5번 과정의 Finished 메시지는 서로 데이터 암호화에 필요한 정보교환이 모두 정상적으로 되었으며, 이제 본격적으로 데이터를 암호화할 준비가 되었다는 의미로 보면 된다.

암호화 알고리즘과, 암호화 키가 성공적으로 교환되면 이후 HTTP 메시지 / 데이터를 암호화 하여 서로 통신하게 된다.





SSL에서의 성능(Performance)

SSL 은 주 목적이 클라이언트와 웹서간 주고 받는 메시지, 데이터에 대한 암호화이다.
복잡한 수학연산이 있는 암호화 알고리즘을 이용하기 때문에 CPU 리소스를 많이 요구한다.

일반적인 웹서버에서 SSL 을 HTTP 와 동시에 처리하는 상황이라면, 성능에 대한 고민을 하지 않을 수는 없을 것이다.

요즘에는 이런 고민들을 덜어줄 어플라이언스 기반 장비들이 시장에 소개되고 있다.
CPU를 사용하지 않고 하드웨어 기반에서 SSL을 처리하는 기능을 별도로 장착한 장비로 보통 웹서버 앞단에 놓여 전달되는 데이터의 암복호화를 직접 처리한다.

다음과 같은 그림으로 구성되어 동작된다고 보면 이해가 쉬울 것이다.

위 그림과 같이 SSL 처리 장비 기준으로 클라이언트쪽은 HTTPS 통신을 하고, 웹서버쪽은 HTTP 통신을 하는 형태로 나뉘게 되는데, 웹서버가 CPU 연산을 많이 필요로 하는 SSL 처리 부담을 제거하여 처리 성능을 높이는 형태이다.

결국 궁극적으로 클라이언트는 기존 CPU에서의 연산보다 처리속도가 빠른 전용 하드웨어 칩 또는 카드를 이용하기 때문에 응답에 대한 체감속도가 빨라지게 되고, 웹서버도 HTTP 로만 처리하기 때문에 응답속도의 개선 효과를 같이 기대할 수 있는것이다.


2017년 9월 29일 금요일

[HTTP 프로토콜 강좌]#27 HTTP 가속 - 웹 캐싱(Web Caching) II

지난 시간에 이어 웹 캐시 프록시서버의 구성위치에 따른 특색을 살펴 보았다.
오늘은 웹 캐시 프록시 서버를 사용자가 적용하기 위한 방법에 대해 이야기 해보려 한다.

클라이언트에게 웹 캐시 서버를 적용시키는 방법에는 다음과 같은 방안이 존재한다.

1. 클라이언트의 직접 적용
2. 트랜스페런트 형태의 적용

클라이언트의 직접 적용

먼저 첫번째 방법이다.
클라이언트의 브라우저에 보면 다음과 같이 프록시 서버를 적용하는 옵션이 존재한다.


인터넷 익스플로어의 설정 화면이다.
프록시 서버의 IP 와 서비스 포트를 정의하는 곳에 프록시 정보를 입력하면 된다.

적용 후 사용자가 다음(www.daum.net) 이나 네이버(www.naver.com) 등 인터넷 홈페이지를 접속하게 되면 모든 요청을 프록시로 전달하게 된다.

프록시는 자신이 캐싱하고 있는 컨텐츠일 경우 직접 응답을 하게 되고, 그렇지 않은 경우에는 인터넷상에 있는 실제 서비스 홈페이지에 접속하여 해당 컨텐츠를 저장한 후 사용자에게 전달하게 된다.

하지만, 이 방법은 사용자의 수가 많지 않은 경우 큰 부담이 되지 않으나 사용자의 수가 엄청 많은 경우에는 관리적인 부담이 증가하게 된다. (사용자들의 브라우저 설정을 과연 어떻게 통제할것인가? )
또한 인터넷 접속이 원활하지 않은 경우 사용자의 설정을 점검해야 하기도 하고, 프록시의 IP 정보가 변경되면 모든 사용자에게 이를 알려야 한다.

그렇다면.. 사용자의 설정을 건들지 않은채 프록시 를 적용할 수 있는 방법은 없을까?





트랜스페런트(Transparent) 형태의 적용

트랜스페런트(Transparent) 형태의 적용이 바로 그 답이다.
트랜스페런트는 사전적 의미로 '투명한' 이란 뜻이다. 의미 그대로 프록시 서버를 투명하게 하여 사용자에게는 프록시가 없는 것처럼 한다는 의미이다.

사용자는 웹 브라우저에서 별도의 설정을 하지 않아도 된다. 그냥 여느때와 마찬가지로 인터넷 접속을 하면 그 요청을 프록시 캐시 서버를 통해 서비스를 하게끔 하는 것이다.

이런 형태의 적용을 위해서는 크게 다음 두가지 기술을 알아야 한다.

1. 라우터 / L3 스위치에서 적용하는 방법
2. L4 스위치에서 적용하는 방법

웹브라우저의 설정없이 사용자의 웹사이트 요청을 프록시가 처리하기 위해서는 중간에 L3 스위치 또는 L4 스위치가 프록시로 해당 요청을 전달해 주어야 한다.

1. WCCP (Web Cache Communication Protocol)

먼저 라우터 또는 L3 스위치가 그 역할을 하기 위해서는 WCCP 라는 프로토콜을 지원해야 한다.
WCCP는 Web Cache Communication Protocol 의 약어로 Cisco 가 개발한 프로토콜이다.
개념은 간단하다. 웹 캐시서버의 존재를 확인한 후 웹캐시서버가 동작을 잘 한다고 판단되면 사용자의 웹 요청을 프록시서버로 꺽어(Redirect) 주는 것이다.

먼저 WCCP 가 지원하는 메시지 형태를 살펴 보자.
  • HERE_I_AM
  • I_SEE_YOU
HERE_I_AM 은 캐시서버가 라우터/L3 스위치에 보내는 메시지로, "나 여기 있어요~" 의 뜻이다. 즉, 캐시서버가 나 서비스 할 준비가 되어 있다는 것을 알리는 목적이다. 

I_SEE_YOU 는 캐시서버가 보낸 메시지에 대한 응답이다. "OK.. 캐시서버의 IP와 연결 포트를 확인했습니다." 라는 의미로 보면 되겠다.

이후 캐시서버는 보통 10초마다 지속적으로 HERE_I_AM 메시지를 보내게 되는데 라우터나 L3는 이 메시지를 통해 캐시버서의 상태를 확인한다.
HERE_I_AM 메시지가 지속적으로 들어오면 캐시서버가 살아 있는것으로 판단하고 웹트래픽을 캐시서버로 리다이렉트 해 주게 되고..
그렇지 않은 경우.. 즉.. HERE_I_AM 메시지가 전송되지 않게 되면, 캐시서버가 Down 된 것으로 보고 직접 웹서버로 전달하게 된다.


그럼 WCCP를 통한 구성을 간단히 살펴보도록 하자.


위와 같이 라우터 혹은 L3 스위치에서 WCCP 기능을 통해 웹트래픽을 캐시서버로 리다이렉트하는 그림이고 아래는 캐시서버와 라우터/L3 스위치간 주고받는 WCCP 프로토콜 메시지이다.


HERE_I_AM 을 보내느 쪽이 캐시서버이고, I_SEE_YOU 메시지로 응답하는 쪽이 라우터이다.
사용하는 전송 프로토콜은 UDP 이며, 포트는 2048을 이용한다.

추가적으로 캐시서버가 여러대일 경우에는 WCCP 프로토콜의 분산알고리즘을 통해 서비스 트래픽 분산을 이용할 수 있다.
부하분산 방식은 두가지인데.. 첫번째로는 IP 주소의 mask 값을 사용하여 캐시서버를 할당하는 방법이고 나머지 한가지는 Hash 값을 이용하여 할당하는 방식을 취하고 있다.





2. L4 Redirect 

다른 한가지는 L4 스위치를 이용하는 것이다.
우리 HTTP 가속의 첫시간에 "로드 밸런서" 라는 것을 다루었는데, L4 스위치는 로드 밸런서의 역할을 하는 대표적인 스위치 장비이다.

로드 밸런싱 이라는 주요 기능 이외에 WCR (Web Cache Redirection) 또는 CSLB ( Cache Server Load Balancing) 라는 이름의 기능을 가지고 있는데, 바로 이 기능을 통해서 트랜스페런트한 웹 캐시서버 동작을 지원할 수 있는 것이다.

동작 흐름을 살펴보면 다음과 같다.


L4 스위치는 위와 같이 HTTP 서비스 (웹트래픽) 에 대해서는 캐시서버로 전달하고, 그외 서비스(메일등)에 대해서는 직접 서버로 전송하게 한다.
때문에 클라이언트는 웹브라우저에 별도의 설정없이 캐시서버의 적용을 받을 수 있게 된다.

또한, L4 스위치는 주기적으로 캐시서버의 서비스 상태를 체크하여 Up/Down 여부를 확인한다. 캐시서버가 서비스 불능(Down) 상태에 빠지게 되면 L4 스위치는 웹트래픽을 곧바로 웹서버에게 전달하여 서비스의 가용성을 유지시켜 주게 된다.

하나 더..
L4 스위치의 주된 기능인 로드밸런싱을 통해 다수의 캐시서버 두고 운영을 할 수 있다. 다수의 캐시서버를 통해 좀 더 안정적인 서비스를 가능하게 하고, 캐시서버가 성능문제에 직면하게 되면 유연하게 확장을 할 수 있게 한다.

이렇게 트랜스페런트 동작을 위한 두가지 구성을 살펴보았다.
캐시서버 뿐만 아니라 프록시서버 기반의 네트워크/보안 장비들의 구성에도 위 두가지 방법은 활용할 수 있고.. 현재도 많이 활용되고 있다.

오늘은 여기까지.. 끝~

2017년 9월 13일 수요일

[HTTP 프로토콜 강좌]#26 HTTP 가속 - 웹 캐싱(Web Caching) I

HTTP 가속에 대한 내용 중 두번째 시간이다.

HTTP 통신에 대한 가속효과를 주기 위한 기술로 지난 시간 "부하 분산(Load Balancer)" 를 이야기 했다.
오늘은 그 두번째로 HTTP 통신의 가속 기술 중 단연 으뜸이라 할 수 있는 캐싱(Caching)에 대한 이야기를 한다.

HTTP 캐싱은 기능적 효과가 좋아 캐싱관련 HTTP 헤더가 있을 정도이다.
이미 프로토콜에 캐싱 관련된 내용이 들어가 있는 만큼 그 중요성이 얼마나 큰지 지레 짐작할 수 있으리라 본다.

HTTP 캐싱은 웹사이트를 접속할 때 사용하는 웹브라우저에서 직접 지원하기도 하지만, 캐싱만을 목적으로한 솔루션(제품)이 존재할 뿐만 아니라, 웹 캐싱에 다른 HTTP 가속기술들을 혼합한 웹 가속기라는 제품도 시장에 출시되어 있기도 하다.

웹캐싱은 오래된 HTTP 가속 기술이지만, 오늘날까지도 굳건히 사용되고 있는 기술이기도 하다.
따라서 HTTP 관련 제품을 지원하는 분들이라면, 반드시 웹 캐싱에 대한 이해를 선행하는 것이 좋다.

자 그럼 지금부터 웹캐싱을 지원하는 프록시 서버에 대해 알아보도록 한다.

구성 위치에 따른 분류

웹 프록시 서버는 구성 위치가 어디냐에 따라 다음과 같이 크게 두가지로 분류할 수 있다.

  • 포워드 프록시 (Forward Proxy)
  • 리버스 프록시 (Reverse Proxy)


앞에 단어가 포워드 / 리버스 와 같으니 정방향 , 역방향.. 정도로 이해할 수도 있겠다.
별로 어려운 이야기는 아니다. 다음 구성 그림을 보자.



포워드 프록시는 클라이언트에게 가깝게 위치하고 있고, 리버스 프록시는 웹서버에 가깝게 위치하고 있다.

프록시 캐시서버가 위치한 곳에 따라 사용 목적이 클라이언트를 위함이냐 웹서버를 위함이냐가 결정된다.

1. 포워드 프록시

먼저 포워드 프록시..
포워드 프록시는 클라이언트(사용자)에게 가깝게 위치하고 있다. 보통 사용자들이 인터넷을 통해 접속하는 웹사이트는 무수히 많은게 사실이다.
다시 말하면 사용자들은 특정 웹사이트만을 접속하는게 아니라 다양한 곳을 방문하기 때문에 캐시서버의 적용대상을 한정할 수 없다.
따라서 캐시서버의 적용대상은 클라이언트가 접속하는 인터넷상에 있는 모든 웹사이트가 되는 것이다.

이 경우 캐시서버를 이용하여 효과를 볼수 있는 것은 다음과 같다.

첫째, 밴드위스(Bandwidth) 절감!!
WAN 구간의 인터넷 트래픽을 캐시서버를 통해 줄일수 있다. 생각해 보자.
A라는 클라이언트가 웹사이트를 최초 접속하면, 캐싱된 컨텐츠가 없기 때문에 모두 실제 웹서버로 부터 응답을 받게 된다.
B,C,D 라는 각각의 사용자들이 A가 먼저 접속했던 웹사이트를 다시 접속하려 한다면..
A사용자에 의해 캐싱해 놓은 컨텐츠들이 이미 존재하기 때문에 B,C,D, ... 사용자들은 인터넷을 통해 실제 홈페이지에 방문할 필요가 없어지게 된다.

캐시서버가 있는 경우에는 캐싱된 컨텐츠에 대해서는 인터넷 구간에서 트래픽을 유발할 필요가 없게 되므로 밴드위스(Bandwidth) 사용량을 절감하게 된다.

두번째, 사용자의 인터넷 체감 속도 향상!!
이미 캐싱된 컨텐츠를 요구하는 사용자들은 인터넷구간을 통해 컨텐츠를 다시 받을 필요가 없다. LAN 구간에 위치한 캐시서버에게서 곧장 요청 컨텐츠를 제공받기 때문에 당연히 응답속도의 개선 또는 향상 효과가 나타난다. 즉, 클라이언트들의 인터넷 사용 환경이 좋아진다.





마지막 세번째, 비업무 트래픽 제한!!
어느 회사의 사용자들이 업무시간에 인터넷 웹사이트를 통해 음악을 듣는다던지 동영상을 시청한다던지등의 불필요한 행위들을 제어할 수 있다.
모든 인터넷 웹사이트 접속을 프록시 캐시서버를 통해 이루어지다 보니, 당연히 사용자의 홈페이지 접속을 일부 제한할 수 있다.
비업무 사이트가 될수도 있고, C&C 서버와 같이 악의적인 사용자들의 해킹서버들도 포함된다. 이건 내부 사용자의 보안에 관련된 측면이 강하기 때문에 엄밀히 이야기 하면 클라이언트가 누리는 효과가 아니라 어느 조직의 관리자가 행하는 정책 지원이라는 성격이라 하겠다.

2. 리버스 프록시

포워드 프록시와는 다르게 리버스 프록시는 클라이언트보다는 웹서버의 안정성 측면에서 효과를 줄수 있는 구성이다.

위치적으로 웹서버와 가깝게 있다 보니, 적용 대상이 포워드 프록시와는 다르게 특정 웹서버로 한정된다.

그렇다 보니 포워드 프록시와는 다르게 다음의 효과를 기대할 수 있다.

첫째, 웹서버 안정성 향상!!
캐시서버를 통해 웹서버의 컨텐츠들이 거의 대부분 클라이언트들에게 제공되기 때문에,  웹서버에서는 TCP 세션의 부하가 많이 줄어든다.
캐싱되지 않는 컨텐츠에 대해서만 요청이 전달되기 때문에 당연한 결과이다.
웹서버가 실제 처리 해야 할 것들을 캐시서버가 대신 해주다보니 CPU사용량이나 메모리 사용량이 눈에 띄게 줄어든다. 그렇기에 당연히 안정적으로 서비스를 운영할 수 있는 환경이 마련된다.

뭐, 한발 더 나가서 생각해 보면 실제 웹서버가 처리해야 할 요청수가 줄어든다는 것은 운영 웹서버의 수를 줄일수 있는 상황이기도 하다. 줄인 서버들은 되려 다른 목적의 서버로 활용할 수 있는 측면으로 생각해 볼수도 있다.

또.. 뭐가 있을까? 사실 리버스 프록시의 주 목적은 웹서버의 안정성을 높혀 서비스 환경을 좋게 만드는데 있다.

3. 정리 

포워드 프록시와 리버스 프록시에 대해서 살펴 봤다.
좀 정리를 하자면..

먼저 접속 환경 비교.

포워드 프록시는 다음 그림과 같이 "특정 클라이언트 -> 랜덤 웹사이트" 이지만

리버스 프록시는 "랜덤 클라이언트 -> 특정 웹사이트" 이다.



두번째, 운영 효과 비교
포워드 프록시는 "밴드위스 절감, 인터넷 웹사이트 접속속도 향상, 웹사이트 접속 제어" 이고 리버스 프록시는 "웹서버의 처리 부하 감소" 를 통한 안정적인 서비스 환경 마련 이다.

세번째, 캐싱 효과 타켓
뭐 운영 효과와 겹치는 부분이지만, 캐시서버를 통해 실제 효과를 보는 대상이 누군지는 구분할 필요가 있을것 같아서..
포워드 프록시는 클라이언트(사용자)가 효과를 볼수 있는 대상이고, 리버스 프록시는 특정 웹사이트이다.




번외로.. 캐싱서비스에서 Hit Rate 라는 단어를 사용하는데 이게 뭐냐면..
프록시 캐시서버가 캐싱하고 요청한 컨텐츠 중에 얼마나 캐싱하고 있는 컨텐츠를 제공하고 있는가 를 확인하는 지표이다.

당연히 Hit Rate 가 높을 수록 캐싱에 의한 효과는 크다고 보는게 맞다.

보통 포워드 프록시 보다 리버스 프록시가 Hit Rate 가 높다.
나의 경험으로 보면 포워드는 60% 정도이고, 리버스는 90% 이상이다. 이건 왜 이럴까?
포워드 프록시는 캐싱효과가 왜 리버스 프록시보다 낮을까?

답은 위 내용에 있다.

포워드 프록시는 캐싱적용 대상이 인터넷상에 있는 다수의 랜덤한 웹사이트인 반면 리버스 프록시는 특정 웹서버이기 때문이다.
그렇기에 포워드 프록시는 요청 컨텐츠가 매우 다양한 반면, 리버스 프록시는 요청컨텐츠가 정해져 있다. 이 뜻은 캐시서버가 캐싱해야 할 컨텐츠가 무지 다양한 것과 그렇지 않은것의 차이이다.

이렇기에 캐싱된 컨텐츠가 재사용될 확률이 아주 높은 리버스가 당연히 Hit Rate 가 높은 것이다.

오늘은 여기까지.. ~
끝~~


2017년 9월 4일 월요일

[HTTP 프로토콜 강좌]#25 HTTP 가속 - Load Balancing

웹사이트가 인터넷상에 처음 등장한 이후 지금까지 많은 발전과 변화가 있었다. 웹사이트는 그 발전을 거듭하여 현재 비즈니스는 물론 우리의 생활 깊숙히 파고 들어와 있다.

우리가 이메일 없이는 업무가 힘들고, 홈쇼핑, 인터넷 뱅킹, 공과급 납무며 주요 행정기관의 민원업무등도 이미 웹사이트를 통해 이용하고 있다.

또한 스마트폰의 등장으로 HTTP/HTTPS 를 이용한 각종 편리한 애플리케이션들이 많이 소개 되어 있다.

웹사이트의 접속률이 꾸준히 증가함에 따라 인터넷 홈페이지의 서비스 속도를 빠르게 하기 위한 기술들도 같이 발전하고 있다.

그 대표적인 기술로는

  1. 부하분산(Load Balancing)
  2. 웹 캐싱(Caching)
  3. SSL 가속 
  4. TCP 멀티플렉싱(Multiplexing)
이 있다. 


오늘은 위 4가지 기술 중 부하분산에 대한 이야기를 해볼까 한다.

부하분산

부하분산의 방식에 대해서는 이미 많은 엔지니어가 익숙히도 알고 있다. 신규 시스템 구축 사업들을 봐도 L4 스위치는 기본적으로 구축되는 인프라 시스템의 아이템 중 하나이고, 바로 이 L4 스위치를 통해 구현하는 기술이 부하분산인 것이기 때문이다.

이미 IT 현장에는 무수히 많은 L4 스위치 엔지니어들이 일을 하고 있으며, 이 엔지니어들을 통해 여러 웹 애플리케이션들이 안정적으로 사용자의 디바이스(PC 또는 스마트폰,패드 등)로 전달이 되고 있다.

때문에 여기서는 L4 스위치에 대한 모든 이야기 보다는 가볍게 부하분산이라는 개념적인 측면에서의 설명만 하고 넘어간다.
이 교육의 주된 목적도 HTTP 가속을 위한 기술 소개에 중점을 두고 있기 때문이다.

I. 서버의 위치

1. 서버가 로컬에 위치 한 경우 ( 로컬 로드 밸런싱 )

로컬 로드 밸런싱은 부하 분산의 대상이 되는 웹 서버들이 로컬에 위치하는 경우이다.

다음 그림을 살펴보도록 하자.



그림과 같이 인터넷을 통해 유입된 수많은 클라이언트의 요청을 같은 역할을 하는 여러대의 서버로 고르게 분산하게 된다. 이때 분산대상이 되는 웹서버들은 모두 로컬에 위치한다.

아주 단순한 이러한 동작이 주는 이점은 상당하다.
먼저 관리적인 측면에서 보면 서버의 부하가 증가하게 되면 신규 웹서버를 간단히 추가하기만 하면 된다. 새로 추가된 서버는 현재 가동중인 서버들의 부하를 줄여줄 것이다.

추가된 서버들로 인해 줄어든 부하는 궁극적으로는 사용자의 서비스 이용환경의 질을 높여주게 된다. 서버의 부하가 낮아진 만큼 처리 속도를 빠르게 해주어 결국 사용자가 체감하는 응답속도는 크게 개선될 것이다.



또한, 여러 대의 웹서버 중 일부의 서버에 장애가 발생하더라도 부하 분산 스위치에 의해 정상적인 웹서버가 그 역할을 대신하여 서비스 가용성을 극대화 시켜줄것이다.
결국 부하분산은 웹사이트의 서비스에 대한 신뢰성을 향상시켜 서비스 주최 기관의 매출신장을 도모를 기대할 수 있게끔 한다.

이렇듯 로컬 로드 밸런싱은 주요 초점이 로컬에 위치한 웹서버에 맞추어져 있다.
웹서버의 부하를 줄이고, 장애가 발생된 웹서버의 유지보수를 서비스 연속성을 보장한 상태에서 가능케 해 주니 말이다.

2. 서버가 외부에 위치 한 경우 ( 글로벌 로드 밸런싱 )

부하분산 대상이 되는 웹서버가 로컬이 아닌 외부에 있는 경우이다.
같은 서비스를 제공하는 웹서버가 여러 지역(Region) 에 위치해 있는 상태이며, 아래 그림과 같이 서비스를 요청하는 클라이언트들과 가까운 지역의 웹서버로 요청을 분산하는 케이스이다.



유럽에 위치한 클라이언트에게는 유럽에 있는 웹서버로, 아시아권에 있는 클라이언트에게는 아시아 지역에 있는 웹서버로 요청을 분산하여 좀 더 빠르게 응답을 할 수 있게끔 하는 것이다.



글로벌 로드 밸런싱은 로컬 로드 밸런싱과는 다르게 운영 초점이 사용자에게 가까운 경우라 할 수 있다. 웹서버의 안정적인 운영보다는 사용자의 응답속도 개선의 측면이 더 높다.

물론, 사용자 응답속도 개선을 위해 위와 같이 운영하게 되면, 각 지역에 위치한 웹서버들로 부하가 분산되기 때문에 특정 지역적인 측면에서만 보면, 밴드위스 절감등의 이점이 있긴하다.
또한, 로컬 로드 밸런싱과 마찬가지로 가용성을 유지하는 것이 가능하다.
예를 들어 유럽지역의 웹서버가 다운되는 경우 로드밸런서에 의해서 다운된 지역으로는 트래픽을 분산하지 않기 때문이다.

글로벌 부하분산은 보통 트래픽 분산으로도 이용되지만, DR (재해복구) 센터 운영에 대한 기술로도 활용이 되고 있다.
(평소에는 유럽지역으로 분산을 하다가 유럽지역에 테러/자연재해로 인한 서비스 불가 상태에 빠지게 되면 자연스레 아시아쪽으로 트래픽을 분산시켜 가용성을 확보하는 방법이다.)





II. 부하 분산 방법

부하를 분산하는 방법으로는 크게 2가지가 있을 수 있다.
그중 첫번째는 DNS 를 이용하는 것이다.

DNS는 많은 분들이 알고 있듯이 도메인 네임을 IP 주소로 변경해 주는 역할을 한다. 실제로 로 인터넷 브라우저에 "www.daum.net" 과 같은 도메인 네임을 입력하게 되면, DNS 서버에 www.daum.net 의 IP 주소를 묻고, 전달 받은 IP 주소로 접속을 시도하게 된다.

따라서 다음과 같이 DNS 서버가 클라이언트의 요청마다 다른 IP 주소를 알려주게 되면 클라이언트의 실제 접속 요청이 분산되게 된다.

아래 그림을 참고하자.

클라이언트 A와 클라이언트 B는 "www.daum.net" 이라는 같은 곳을 접속하지만, DNS 서버에 의해서 서로 다른 위치의 웹서버(같은 서비스의 서버)로 접속이 이루어 지게 된다.

이처럼 DNS 를 통해 클라이언트들의 요청을 분배하는... 즉, 부하분산을 가능케 하는 기술이 글로벌 로드 밸런싱에서 사용되는 기술이다.

두번째는 전용 로드 밸런싱 장비를 이용하는 것이다.

앞서 설명했던 로컬 로드 밸런싱 장비를 이용하는 경우가 바로 그것이다. 이 경우 통상 DNS Lookup IP (서비스 IP)는 로드밸렁신 장비가 가지게 된다.

서비스 IP로 유입된 클라이언트들의 요청은 전용 로드밸런싱 장비의 다양한 부한 분산 알고리즘을 통해 적절하게 웹서버들로 분산되어진다.
이 역할을 하는 주요 장비가 바로 "L4 스위치" 이다.

통상 로드 밸런싱 장비가 제공하는 부하 분산 방식으로는 크게 정적(Static) 방식과 동적(Dynamic) 방식이 있다.

Round Robin 과 같이 유입된 순서대로 웹서버들에게 한번씩 분산하는 것이 정적 방식이고, 웹서버의 세션 수를 체크하여 적은 세션을 가지고 있는 웹서버에게 먼저 분산한다던지 CPU 사용량이 낮은 웹서버에게 먼저 전달한다던지 응답시간을 체크하여 빠른 웹서버에게 부하를 먼저 포워딩하는 형태들이 동적 방식이 되겠다.

이런 다양한 부하분산 방식들은 결국에는 다음 2가지를 목적으로 사용되는데..

  1. 좀 더 빠른 웹서비스 환경 제공
  2. 좀 더 안정적인 웹서비스 환경 제공
이라 할 수 있다. 

오늘은 여기까지.. 끝~~

2017년 8월 28일 월요일

[HTTP 프로토콜 강좌]#24 응답 상태 코드 (HTTP Status Code) - 4xx, 5xx

지난 시간에 이어 HTTP 상태 코드를 정리한다.

우리는 HTTP 상태코드에는 크게 1xx, 2xx, 3xx, 4xx, 5xx 이렇게 다섯 카테고리로 구분하며,

  • 1xx 는 단순 정보 제공
  • 2xx 는 클라이언트의 요청을 정상적으로 처리 (OK)
  • 3xx 는 리다이렉트
라는 것을 배웠다. 

오늘은 4xx 와 5xx 에 대한 상태코드를 배운다. 

1. Client Error (4xx)

400 Bad Request

클라이언트의 에러를 표현하는 가장 대표적인 응답 상태 코드이다. 웹서버가 클라이언트의 요청을 이해하지 못했을때 전달하는 메시지이다. 
대체로 클라이언트의 요청 형태(format) 가 잘못 되었거나, 사이즈가 너무 크거나 하는 등.. 이러한 경우 400 Bad Request 가 반환된다.


401 Unauthorized

"401 Unauthorized" 응답 코드는 클라이언트에게 인증을 요구할때 사용된다. 
클라이언트가 요청한 컨텐츠의 접근권한을 확인하려는 목적으로 전달된다. 
"401 Unauthroized" 응답 코드와 함께 "WWW-Authenticate" 헤더에 인증 방식을 표시하여 같이 전달한다. 

우리 이전 요청헤더 강좌 중에 "Authorization"을 다룰때 언급한적이 있는데 이 헤더에 대한 내용을 자세히 알고 싶다면 여기 를 클릭하자.

402 Payment Required

HTTP 에서는 "402 Payment Required" 에 대해 명세하고 있으나, 현재는 미래를 위해 예약해 둔 상태코드이다.
응답 코드에 연결된 메시지(Payment Required) 처럼 디지털 캐시나 마이크로 페이먼트와 같은 경우에 지불정보를 요구하는 형태로 사용된다고 하지만.. 아직 실무에서 확인해 본 바는 없다.

구글 개발 API 에서 특정 개발자가 하루 임계 요청량을 초과한 경우 이 코드를 반환하는 형태고 사용된다고는 한다.

403 Forbidden

클라이언트의 요청 형태등에서 잘못된 것은 없다. 다만, 요청한 컨텐츠에 접근할 수 있는 권한이 없는 경우 이 응답 상태코드를 받게 된다.
가령 특정 디렉토리 또는 컨텐츠에 접근할 수 있는 권한이 없는 사용자가 해당 컨텐츠를 요구한 경우가 이에 해당된다.

401 응답코드와 비슷하지만, 403의 경우에는 요청에 Authroization 헤더가 존재하지 않는다. 때문에 웹서버는 사용자의 정보를 요구하지 않고 바로 "403 Forbidden" 코드를 반납한다.

404 Not Found

웹서버에 존재하지 않는 컨텐츠를 요청한 경우 반환되는 메시지이다.
4xx 코드 중에서 실제 가장 많이 확인해 볼수 있는 응답 상태 코드이기도 하다.

405 Method Not Allowed

클라이언트가 사용한 HTTP 요청 메소드(Method) 가 웹서버에서 허용되지 않았음을 의미한다. 이 상태코드 메시지와 함께 전달되는 Allow 헤더에 허용된 메서드들에 대해 표시된다.

아래 HTTP 요청/응답헤더를 살펴보자.
클라이언트가 DELETE 라는 요청 방식을 사용했으나, 웹서버는 이를 허용하지 않았다.
405 응답코드를 반환했고, Allow 헤더를 이용해서 현재 웹서버에서 사용가능한 메소드 들을 알려준다.

406 Not Acceptable

클라이언트는 웹서버로 요청을 할 때, 자신이 지원하는 여러정보들을 함께 보낸다.
브라우저로 표현할 수 있는 컨텐츠 타입, 언어, 인코딩 타입등등..

웹서버가 클라이언트의 요청을 처리하여 응답할때 이러한 클라이언트의 정보를 참고하게 되는데, 자신이 응답하는 컨텐츠가 클라이언트가 지원하는 형태에 맞지 않을때 406 응답 상태 코드를 사용하게 된다.

407 Proxy Authentication Required

이 코드는 클라이언트가 먼저 프록시로부터 인증을 받아야 한다는 것을 의미한다.
클라이언트가 요청하는 컨텐츠에 대해서, 프록시로부터 인증을 먼저 받아야만 정상 처리가 가능하다는 뜻이다.

프록시 서버가 전달하는 응답코드이며, Proxy-Authenticate 헤더를 포함하여 어떤 인증방식을 이용할 것인지를 클라이언트에게 알린다.

클라이언트는 Proxy-Authenticate 헤더와 함께 407 응답코드를 받게 되면 이후 요청에서 Proxy-Authorization 헤더에 인증 정보를 포함하여 전달하게 된다.

408 Request Timeout

클라이언트의 요청을 웹서버가 기다리다가 더이상 기다리지 못하게 되면, 이 응답코드를 보낸다.

예를 들어 다음과 같은 상황을 가정하자.
정상적인 경우..


클라이언트가 Expect 헤더를 이용하여 웹서버로 부터 데이터를 보내도 되는지 여부를 묻는다. 웹서버에서 처리 가능한 데이터일 경우 100 Continue 응답 상태 코드를 전달하여 데이터를 받아 처리한다.

비정상인 경우...

클라이언트이 Expect 헤더를 보고 100 Continue 응답 코드를 보냈으나, 클라이언트가 이후 데이터를 보내지 않은 경우 웹서버는 자신의 Timeout 시간동안 기다려보고 데이터가 오지 않으면 "408 Request Timeout" 메시지를 반환한다.

409 Conflict

웹서버에 있는 컨텐츠를 누군가 먼저 요청하고 작업중인데 다른 사용자가 같은 컨텐츠에 대한 작업을 요청하면 "409 Conflict" 메시지를 후 사용자에게 전달한다.

예를 들어 PUT 방식으로 어떤 컨텐츠에 대한 변경을 진행하고 있는 중... 다른 사용자가 같은 작업을 하려 하는 경우가 이에 해당된다.



410 Gone

요청한 컨텐츠가 더이상 사용가능하지 않은 경우 반환되는 코드이다. 약간 404 Not Found 응답 코드가 의미적으로 비슷하다.
다만, 차이점은 404는 임시적인 상태인 경우의 메시지이고.. 410은 지속적인 상태의 메시지이다.

다시 말하면.. 404 응답코드는 현재는 없는 컨텐츠이지만, 이후 존재할 가능성이 있다는 뜻이고, 410은 현재도 없고, 앞으로도 없을 것이라는 의미이다.

검색엔진이 410 Gone 코드를 받게 되면 자신의 색인 목록에서 이를 삭제해야 한다.
그러나 대부분의 경우 색인목록에서의 삭제를 요구하지 않아서 410보다는 404 코드가 많이 사용되긴 한다.

411 Length Required

클라이언트가 유효한 Content-Length 헤더를 갖지 않은 경우 웹서버는 요청을 거절하면서 이 응답 상태 코드를 사용할 수 있다.

412 Precondition Failed

웹서버 또는 프록시서버가 클라이언트의 요청을 처리하기 위해 어떤 조건(If-Match와 같은)을 요구하는 경우가 있을 수 있는데.. 이 정보가 웹 서버 기준에서 충족하지 않는 경우 이 응답코드가 반환된다.



413 Request Entity Too Large

웹서버에서 수용할 수 있는 메시지 바디의 사이즈보다 큰 데이터가 들어온 경우 이 응답 상태 코드를 반환한다.

414 Request-URI Too Long

413 코드와 비슷한 형태의 에러 메시지이다. 다만, 414 응답 코드는 URI 길이가 웹서버에서 처리 할 수 있는 범위를 넘어 선 경우 반환된다.

415 Unsupported Media Type

요청 메시지 바디의 미디어 타입을 웹서버에서 지원하지 않는 경우 반환되는 코드이다.
예를 들어, 클라이언트가 이미지 파일을 하나 업로드 한다. 이때 이미지는 image/svg+xml 인 경우.. svg+xml 형태의 이미지를 웹서버에서 지원하지 않는 경우가 해당된다.

416 Requested Range Not Satisfiable

앞서 Range 헤더를 이용해서 클라이언트는 이어받기를 할 수 있다는것을 배운바 있다.
(Range 헤더에 대한 상세 내용은 여기 를 클릭하여 확인 가능하다. )

클라이언트가 대용량의 파일을 다운로드하다가 중간에 끊어지게 되면.. 마지막 전송받은 바이트(Bytes) 부터 다시 요청하여 이어 받기를 한다.
이때 다시 전달받을 용량의 시작점을 Range 헤더에 명시하게 되는데..

클라이언트가 이 정보를 잘못 명시한 경우 웹서버는 416 응답 상태 코드를 반환한다.

417 Expectation Failed

클라이언트가 요청시 Expect 헤더에 클라이언트가 예상하는 정보를 담아 보낼수 있다.
우리가 엎서 배운 것으로는  Expect: 100-continue 가 있다.

이와 같이 클라이언트가 예상하는 어떤 정보를 웹서버가 만족하지 못할 경우 417 응답 상태코드를 반환한다.

426 Upgrade Required

앞서 Upgrade 헤더에 대해 배운 적이 있다. ( 여기 를 클릭하여 Upgrade 의 상세 내용을 확인할 수 있다.)

클라이언트가 HTTP 를 TLS 등과 같이 보안 프로토콜로 변환하고자 할 경우 Upgrade 헤더를 사용한다. 비슷하지만.. 426 Upgrade Required 응답 상태 코드는 서버가 보안채널을 통한 통신을 하고자 할때 클라이언트에게 전달하는 상태 코드인 것이다.


2. Server Error (5xx)

500 Internal Server Error

500 응답 코드는 일반적인 서버의 문제를 알리는 상태 코드이다. 웹서버가 추가적으로 에러에 대한 상세한 내용을 전하는 경우 응답 메시지 바디를 이용한다.

501 Not Implemented

요청 메소드를 전혀 웹서버가 이해하지 못할때 반환되는 코드이다. 흔히 새로운 기능의 웹기반 API 에서 발생되는 에러 코드의 종류이다.

클라이언트의 요청 메소드에는 전혀 문제가 없으나, 서버가 이를 정상적으로 처리하지 못하는 경우인것이다. (서버 문제)

502 Bad Gateway

프록시 서버가 유효하지 않은 응답을 웹서버로부터 받게 되면 "502 Bad Gateway" 메시지를 반환하게 된다.

예로 다음과 같은 경우가 502 Bad Gateway 가 발생하는 상태이다.



  • 1~3번까지는 TCP 연결 생성 과정이다. (3-way 핸드쉐이크)
  • 4번은 프록시 서버와 정상적으로 TCP 연결을 맺은 다음 HTTP 요청을 한다. 
  • 프록시 서버는 클라이언트의 요청을 전달하기 위해 웹서버와 TCP 연결을 맺는다.
    (5~7번 과정)
  • 하지만 웹서버에서는 80포트는 열려있으나 HTTP 데몬이 아니다. 즉, HTTP 요청을 정상적으로 처리할 수 없는 상태이다. 따라서 8번과 같이 클라이언트의 HTTP 요청이 전달되면 9번과 같이 세션을 끊는다. 
  • 프록시 서버는 웹서버와 TCP 세션은 맺었으나 요청에 대한 응답을 받지 못했기에 클라이언트에게 "502 Bad Gateway" 메시지를 전달한다. 
프록시 서버 입장에서 웹서버가 TCP 세션은 열려있으나 HTTP 처리가 되지 않는 경우.. 
세션이 끊어지거나 HTTP 가 아닌 다른 프로토콜의 응답을 받게 되는 경우 웹서버는 502 상태 코드를 반환한다. 




503 Service Unavailable

웹서버가 클라이언트의 요청을 정상적으로 처리할 수 없는 상태인 경우이다. 
물리적으로 웹서버는 살아 있으나, 웹서비스 데몬이 다운되었거나 부하가 심해서 처리가 불가능한 상태이거나 한 경우가 이에 해당된다. 

다음과 같은 경우를 예로 살펴 보자. 






  • 1~3번 과정을 통해 프록시 서버와 TCP 연결을 수립한다. 
  • 4번 HTTP 요청을 보낸다. 
  • 프록시 서버는 클라이언트의 요청을 전달하기 위해서 웹서버에 TCP 연결을 하려고 시도한다. 하지만, 웹 서비스 포트가 다운되어 있어서 접속이 불가하다. 
  • 프록시 서버는 클라이언트에게 503 상태 메시지를 전달한다. 
프록시 서버가 웹서버로 클라이언트의 요청을 전달하기 위해서 TCP 연결을 시도 했으나, 웹서버의 데몬이 다운되어 연결이 되지 못한 경우, 서비스가 불가하기 때문에 "503 Service Unavailable" 상태코드를 전달한다. 

504 Gateway Timeout

클라이언트의 요청을 프록시 서버가 웹서버로 전달한 후... 이정 시간이 지났는데도 응답을 받지 못하게 되면.. 프록시는 마냥 기다리기만 하지 않는다. 
일정 시간이 지나도록 요청에 대한 응답이 없다면, 서비스가 정상적이지 못하다고 판단하고 클라이언트에게 "504 Gateway Timeout" 메시지를 반환한다. 

다음의 경우와 같다. 





  • 8번과 같이 클라이언트의 요청을 정상적으로 웹서버에게 전달했으나 이에 대한 응답이 없다. 
  • 그렇다면 일정시간 후 프록시는 클라이언트에게 504 Gateway Timeout 을 보낸다.
505 Version Not Supported

클라이언트의 HTTP 요청 버젼을 웹서버가 지원하지 못하는 경우이다. 
웹서버는 HTTP 0.9 를 지원하고 있는데, 느닷없이 클라이언트가 HTTP 1.1 로 요청한 경우 처리가 불가능하기 때문에 "505 Version Not Supported" 를 반환한다. 

뭐, 요새가 어떤 세상이랴~~~~.. 
현업에서 505 상태코드는 본적이 없긴 하다. ^^

여기까지 해서 HTTP 상태 코드를 모두 마친다. 
아무래도 5xx 코드는 설명을 위해 노력을 좀 한 편이긴 하다. 엔지니어들이 5xx 에러코드를 만나는 경우 아~~ 이런 경우겠구나.. 하고 문제접근을 하는게 중요하기 때문이다. 

다음 시간 부터는 가속과 보안에 대해 이야기 하도록 한다. 

끝!!!



2017년 8월 25일 금요일

[HTTP 프로토콜 강좌]#23 응답 상태 코드 (HTTP Status Code) - 1xx, 2xx, 3xx

이전 강좌를 마치며, HTTP 보안과 HTTP 가속에 대한 내용을 다룬다고 했었다.
그런데, 내가 HTTP 상태코드에 대해 정리를 한적이 없다는 것을 어제 저녁에 알게 되니.. 아차 싶다. 

이전 강좌들에서 주제를 설명하면서 들었던 예시들에 자주 등장했던게 바로 HTTP 상태코드인데... 그리 중요한것을 정리하지 않고 넘어갈 뻔 한게 아닌가? 

그래서 HTTP 보안 그리고 가속의 내용으로 넘어가기 전에 오늘은 HTTP 상태코드에 대한 정리를 좀 해 보려 한다. 

HTTP 상태코드는 클라이언트의 요청을 처리하고 난 후 결과를 설명하는 아주 중요한 정보이다. 상태코드는 숫자 3자리로 되어 있으며 첫번째 자리의 숫자를 기준으로 크게 다음과 같이 구분한다.

  • 1xx : 단순 정보 제공 
  • 2xx : 성공 (클라이언트의 요청을 정상적으로 처리함)
  • 3xx : 리다이렉트 (클라이언트를 다른 URI 또는 도메인으로 리다이렉트 함)
  • 4xx : 클라이언트쪽 에러 
  • 5xx : 서버쪽 에러
각 코드별로 가장 첫번째 자리가 해당 코드군의 마스터 상태 코드이다. 
그러니까 1xx 의 마스터는 100 이고, 2xx 의 마스터는 200 인것이다. 

클라이언트는 서버가 정의되지 않은 HTTP 상태코드를 주는 경우는 마스터코드로 처리하게 된다. 예를 들어 미정의된 278 코드를 전달받으면 클라이언트는 200으로 여기고 처리한다는 뜻이다. 

다음 테이블은 HTTP 상태코드를 정리해 놓은 것이니 참고하면 좋겠다. 

클래스코드설명
클래스 코드 설명
1xx Informational
100 Continue
101 Switching Protocols
2xx Successful
200 OK
201 Created
202 Accepted
203 Non-Authoritative Information
204 No Content
205 Reset Content
206 Partial Content
3xx Redirect
300 Multiple Choices
301 Moved Permanently
302 Found
303 See Other
304 Not Modified
305 Use Proxy
307 Temporary Redirect
4xx Client Error
400 Bad Request
401 Unauthorized
402 Payment Required
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
407 Proxy Authentication Required
408 Request Timeout
409 Conflict
410 Gone
411 Length Required
412 Precondition Failed
413 Request Entity Too Large
414 Request URI Too Long
415 Unsupported Media Type
416 Requested Range Not Satisfiable
417 Expectation Failed
426 Upgrade Required
5xx Server Error
500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 Version Not Supported


자 그럼 이제 상태코드 메시지에 대해서 하나하나 살펴보도록 하자.

1. Informational (1xx)

100 Continue

클라이언트가 데이터를 서버로 전송하려 하는데, 서버에는 데이터 사이즈에 대한 제약이 걸려있는 상황이다.

이걸 무시하고, 일단 클라이언트가 서버의 제약보다 큰 데이터를 보내게 되면 서버는 이를 처리하지 못하고 에러를 보낸다.

이렇게 되면,
첫째, 클라이언트는 원하는 데이터를 서버로 전송하지 못해서 불쾌하게 되며,
둘째, 네트워크상에는 불필요한 데이터가 전송에 사용되었으므로 이 역시 네트워크 자원측면에서도 손해이다.

클라이언트가 먼저 서버에게 자신이 보내려는 데이터 사이즈가 이정도인데, 처리가 가능한지 묻고 데이터를 보낸다면 위 두가지 문제점들이 해결되게 된다.

먼저, 처리가 불가능하다는 것을 알았기 때문에 불쾌한 결과를 경험하지 않아도 된다.
그리고, 불필요한 데이터 전송을 하지 않으므로 네트워크 자원 사용면에서도 이익이다.

이걸 가능하게 하는것이 "Expect: 100-continue" 헤더를 요청에 포함하여 보내는 것이다.

이에 대한 상세한 동작흐름도나 랩테스트 결과는 이전 강좌 중 Expect 헤더를 다룬 부분에서 이야기 한 적 있다.

Expect 헤더에 대한 상세한 내용은 여기 를 클릭하여 확인토록 하자.

100 Switching Protocols

클라이언트와 서버간 통신하는 프로토콜의 업그레이드가 필요한 경우 Upgrade 헤더를 사용한다는 것을 이전 강좌를 통해 배운적이 있다.

Upgrade 헤더에 대한 서버의 응답메시지에 바로 "100 Switching Protocols" 가 사용된다.

가령, HTTP 로 통신하다가 보안이 적용된 TLS 로 통신프로토콜을 바꾸고자 하는 경우가 이에 해당된다.

Upgrade 헤더에 대한 상세한 내용은 여기 를 클릭하여 확인하자.





2. Successful (2xx)

200 OK

가장 많이 확인할 수 있는 응답 메시지 코드 중 하나이다. 클라이언트의 요청에 대해 웹서버가 정상적으로 응답한 경우 "200 OK" 를 보낸다.

요청 방식에 따라 200 OK 라는 상태코드와 함께 추가적인 정보가 전달되는데..
가령 GET의 경우 웹서버는 요청한 컨텐츠를 함께 전달하며, HEAD의 경우에는 그렇지 않다.
또한 컨텐츠의 종류 및 인코딩 타입등.. 메시지 바디에 해당되는 엔티티 헤더들도 함께 전달이 된다.

201 Created

클라이언트가 PUT 메소드를 이용하여 웹서버에 어떤 파일을 생성하는 경우, 파일 생성이 정상적으로 잘 되었다면 웹서버는 클라이언트에게 "201 Created" 상태코드를 보낸다.

상태메시지와 함께 Location 헤더에 파일이 생성된 위치정보(URI)를 함께 전달한다.

관련 예제는 우리 PUT 메소드를 다뤘던 이전 강좌에서 확인이 가능하다.
PUT 메소드 관련 강좌는 여기 를 클릭하여 확인할 수 있다.

202 Accepted

클라이언트의 요청을 받았으나 아직 처리는 하지 않는 그런 경우에 반환되는 상태 코드이다.

웹서버가 "응~ 일단 요청은 잘 받았어요.. 이따 정해진 시간에 당신의 요청은 처리됩니다."  라는 의미로 클라이언트에게 응답하는 경우라 할 수 있다.

서버에서 HTTP 의 요청에 대한 처리 동작을 배치형태로 정해진 시간에만 처리하는 경우 이 응답 코드가 사용되어진다.

하지만, 일반적인 인터넷 사용환경에서는 거의 볼 수 없는 응답코드이긴 하다.



203 Non-Authoritative Information

웹서버가 클라이언트의 요청을 정상적으로 처리하여 응답을 주었으나, 중간에 있는 프록시등의 중간 서버에 의해 메시지 바디가 변경되는 경우 반환되는 응답코드이다.

뭐.. 202 Accepted 코드와 마찬가지로 실제 환경에서는 거의 볼수 없는 응답코드이다.

204 No Content

"204 No Content" 상태코드 메시지는 웹서버가 클라이언트의 요청을 정상적으로 처리는 했지만, 응답 해줄 어떤 데이터도 없을 경우 반환되는 코드이다.

다음의 예를 살펴보면 이해가 쉽다.

아래와 같은 웹페이지가 있다고 가정하고..
전기요금 그래프 상태를 5초마다 갱신하고 싶은 경우 체크박스에 체크를 하면 된다.

하지만, 그래프 상태가 연단위라서 체크를 하던 안하던.. 브라우저를 통해 볼수 있는 페이지 정보는 변경이 없다.

클라이언트가 브라우저의 체크박스에 체크를 하게 되면, 이정보를 웹서버에게 전달하게 된다. 웹서버는 클라이언트의 요청을 처리한 후 처리결과를 응답으로 전송한다.
이때, 아래 화면에 포함된 그래프 정보등의 이미지도 같이 보내야 한다.

정보의 변경이 없는 경우에 .. 이런 상황이라면.. 얼마나 불필요한 동작을 수행해야 하는지 느낌이 올것이다.

따라서 이런 경우 클라이언트의 요청을 정상적으로 처리하였다는 메시지만 전달하고, 브라우저에 표시되는 내용 정보들은 기존의 것을 그대로 활용하게 끔 하는 목적에서 사용할 수 있는 상태코드가 필요한데 이게 바로 "204 No Content" 인것이다.


하지만 이 코드도 실제로 사용되는 경우를 본적이 없다.

이론적으로 보면, 참 유용한 동작 같은데..
이런 형태의 동작이 필요한 곳은 주로 어떤 현황을 모니터링 하는 관제쪽에 주로 사용될것 같은데.. 아직 그쪽으로의 지원경험이 거의 없어서 그런가?? ..

암튼.. 잘 알아두자. ^^

205 Reset Content

204 No Content 코드와 유사한 코드이다. 두 상태코드 모두 응답 데이터(메시지 바디)를 포함하지 않는다.

다만, 205 Reset Content 의 경우 일반적으로 웹 입력 폼 중에 Reset 버튼과 같은 역할을 한다고 보면 좋다.
우리가 회원가입등의 절차에 따라 요구되는 입력폼 (주소, 이름, 성별등등)에 내용을 채워나가다가 Reset 버튼을 누르면 입력된 내용이 모두 지워지는 것과 같이 현재의 브라우저에 표시된 Document View를 Reset 하게 된다.

206 Partial Content

우리가 앞서 Range 헤더를 배울때 상태코드로 언급되었던 코드이다.
Range 헤더는 대용량 파일을 클라이언트가 다운로드 하다가 중간에 중단된 경우 이를 이어받기를 원할때 사용되는 헤더이다.

클라이언트가 이어받기를 시도하면 웹서버가 이에 대한 응답코드로 "206 Partial Content" 와 함께 Range 헤더에 명시된 데이터의 부분(byte) 부터 전송을 시작한다.

Range 헤더의 상세한 내용을 알고 싶다면 여기 를 클릭하면 된다.





3. Redirect (3xx)

300 Multiple Choices

클라이언트의 요청에 대해 다른 URI 로 리다이렉트를 하는 것인데, 클라이언트가 선택할 수 있는 리스트를 하나 이상 부여한다.

300 Multiple Choices 상태코드와 함께 리다이렉트 URI 들을 메시지 바디에 담아 응답한다.

301 Moved Permanently

URI 의 변경을 지속적으로 하고 싶은 경우 301 Moved Permanently 상태코드를 전달한다.
이 상태코드를 받게 되는 경우, 클라이언트는 지속적으로 변경된 URI 로 요청을 하게 된다.

302 Found

302 Found 코드는 임시적으로 클라이언트가 새로운 URI 로 접속하게끔 유도한다.
302 Found 코드를 받은 클라이언트는 안내받은 URI로 GET 방식을 사용하여 접속을 시도하게 된다.
다시 말해, POST 요청방식으로 접속을 시도하더라도 302 Found 코드로 인해 리다이렉트가 되면 새로운 URI 접속 시 POST 방식을 다시 사용하지 않고 GET을 사용한다는 의미이다.

303 See Other

302 Found 상태코드와 같이 다른 URI 로 리다이렉트 하는 것은 같으나, 주로 PUT 또는 POST와 같이 클라이언트가 전송하는 데이터를 처리해야 하는 요청방식에 주로 사용된다.

303 See Other 상태코드와 함께 전달되는 Location 헤더의 경로는 완전 새로운 경로가 아닌 현재 요청과 관련된 URI 정보이다.

가령 PUT 또는 POST 를 이용해서 하나의 파일을 업로드 하는 경우 웹서버는 이를 처리하고 있음을 클라이언트에게 알리는 페이지를 보여주고 싶다고 하자.
이 경우 303 See Other 상태코드를 사용할 수 있다.

업로드 요청 URI와 현재 요청된 동작을 처리중이라는 페이지는 전혀 상관없는 페이지가 아니다. 즉 303 See Other 상태코드와 관련되는 URI 정보가 Location 헤더의 값으로 표시되는 것이다.
반면, 302 Found 는 요청 동작과 무관한 새로운 URI 정보가 Location 헤더에 담긴다.

효율적인 내용인 반면. 나로서는 실제로 사용되는 예는 아직 경험해 보진 못했다.


304 Not Modified

캐싱된 컨텐츠를 다시 사용해 된다는 의미를 클라이언트에게 전달하는 상태코드 메시지이다.
클라이언트가 요청헤더에 If-Modified-Since 또는 If-Match 와 같은 조건 내용을 전달하는 경우 웹서버는 이를 확인하여 요청하는 컨텐츠의 변경이 없다고 판단되는 경우 304 Not Modified 메시지를 전달한다.

305 Use Proxy

실제 웹서버가 클라이언트에게 프록시를 사용할 것을 요청하는 응답 상태코드이다.
최초 요청에 한해서만 반환될 수 있는 코드이다.

클라이언트가 요청한 컨텐츠들이 프록시를 경유해야만 정상적인 응답을 할 수 있는 경우 사용되는데, 시중에 있는 대부분의 웹브라우져(파이어폭스, 크롬, IE)들은 보안상의 이유로 이 메시지를 무시하는 경향이 많다.

307 Temporary Redirect

302 Found 상태코드와 동작 방식이 같다.
클라이언트가 요청한 URI에 대해 302 Found 메시지를 받게 되면 메시지와 함께 전달된 응답헤더 Location 의 정보를 참고하여 그 URI 로 접속을 시도한다.

307 Temporary Redirect 도 302 코드와 마찬가지로 Location 헤더의 내용을 참고하여 그쪽으로 새로 접속을 시도하게 된다.

302 코드와 차이가 있다면.. 302 코드는 클라이언트가 POST등과 같이 GET 이 아닌 요청 메소드를 사용해도 결국 Redirect 는 GET으로 하게 되지만, 307 코드는 POST 로 요청한 경우 Redirect 도 POST 방식으로 한다는 데 있다.

오늘은 여기까지 진행한다.
4xx 와 5xx에 대한 내용은 다음 포스팅에 정리하여 올리도록 한다.
4xx 코드의 내용이 많기도 하고, 이번주 업무와 함께 내용을 정리하려 하니 여유가 잘 나지 않는다. 그렇다고 정리가 다될때까지 기다리는 것도 좀 아닌거 같아서...

양해를 부탁드린다.

끝~


2017년 8월 22일 화요일

[HTTP 프로토콜 강좌]#22 HTTP 엔티티 헤더 II - Expires, Last-Modified


오늘은 HTTP 엔티티 헤더 두번째 시간이다.
엔티티헤더는 첫번째 시간에 거의 모든 내용을 다룬 터라 오늘은 내용이 많지 않다.

가벼운 마음으로 아래 내용을 살펴 보시고, 지금껏 강의한 HTTP 헤더의 내용들을 정리하시면 좋겠다.

첫 강좌를 시작한게 6월 말이었는데, 어느덧 두달째가 되어간다.
오늘까지 전체 내용 중 2/3 정도를 진행한것 같다.

1. Expires

캐시서버은 디스크 또는 메모리와 같은 자신의 저정영역에 저장한 컨텐츠들에 대해선 유효성을 고민해야 한다.
실제적으로 클라이언트에게 직접 전달해되 되는지 또는 그렇지 않은지에 대한 판단을 늘 해야 하며, 제공된 컨텐츠는 항상 서비스에 유효한 것이어야 한다.

캐시서버가 이러한 판단을 할 수 있게끔 도움을 주는 HTTP 헤더가 몇가지 있는데, Expires 헤더가 그 중 하나이다.

Expires 헤더는 단어 뜻 그대로 컨텐츠의 유효기간이라고 이해하면 좋다.

유통되는 우유나 음료/식품등에 유통기간이 적혀 있고, 그 기간을 넘어가게 되면 식품의 변질을 의심해야 한다.

캐시서버가 캐싱하고 있는 (저장하고 있는) 컨텐츠 역시 마찬가지이다.
Expires 헤더에 명시되어 있는 기간이 지나게 되면, 더 이상 유효한지 아닌지를 실제 웹서버에서 확인해야 한다.

Expires 헤더의 값은 시간정보를 포함한 날짜 정보이다.
아래가 그 예이다.

Expires: Mon, 21 Aug 2017 09:00:05 GMT

만약 웹서버가 제공하는 컨텐츠가 캐싱되지 않기를 원한다면, Expires 헤더의 값을 응답하는 Date 헤더의 값과 같거나 지난 날짜를 설정해서 전달하면 된다.

이전 강좌의 Cache-Control 부분에서 max-age 값의 의미를 설명할 때, Expires 를 이야기 한적이 있다.
다시 간단히 정리하면.. Cache-Control은 HTTP 1.1에서 등장한 헤더이다. Expires 와 Cache-Control 헤더의 max-age가 같이 사용된 경우에는 Cache-Control 헤더가 먼저 적용된기 때문에 Expires 헤더가 무시될 수 있다.

Cache-Control 의 max-age 내용을 자세히 알고 싶다면 여기 를 클릭한다.




2. Last-Modified

웹서버에 있는 컨텐츠가 내용이 변경된 경우 컨텐츠의 생성/수정 시간이 변경된 시점으로 바뀐다. 이는 서버만 알고 있는 정보이긴한데.. 클라이언트가 변경된 컨텐츠를 요청한 경우 HTTP 헤더에 이 날짜정보(시간 포함)를 표시하여 캐시서버나 클라이언트에게 알린다.

Last-Modified 헤더는 주로 If-Modified-Since 헤더와 같이 사용된다.
이 두 헤더 정보를 통해 캐시서버가 현재 캐싱하고 있는 컨텐츠를 제공할지 아니면 웹서버에 있는 오리지널 컨텐츠를 제공할지 결정하기도 한다.

아래는 이에 대한 동작 흐름 그림이다.


먼저, 최초 요청에 대한 설명이다.
위그림에서..


  1. 클라이언트가 최초 요청을 보낸다. 
  2. 프록시서버는 그 요청을 받고 자신이 캐싱한 컨텐츠를 확인해 본다.
    캐싱한 컨텐츠가 없으니 실제 웹서버로 요청을 전달한다.
  3. 웹서버가 요청한 컨텐츠에 대한 응답을 한다.
    응답 시 컨텐츠의 생성/수정 시간을 참고하여 Last-Modified 헤더에 기록한 후 전달한다.
  4. 캐시서버 역시 컨텐츠를 캐싱한 후 클라이언트에게 전달한다. 




같은 요청을 다시 한 경우이다.




  1. 클라이언트가 같은 요청을 다시 한다. 
  2. 캐시서버가 유효성 확인을 위해 캐싱한 이미지의 Last-Modified 헤더의 시간정보를 참고하여 If-Modified-Since 헤더에 기록한 후 요청한다. 
  3. 실제 웹서버는 If-Modified-Since 헤더의 시간정보를 참고해보니 그때 이후 변경된 바가 없음을 확인한다.
    캐싱하고 있는 컨텐츠를 사용해도 좋다는 의미의 "304 Not Modified" 메시지를 전달한다. 
  4. 캐시서버는 자신이 캐싱하고 있는 컨텐츠를 그대로 전송한다. 

이상 끝~

여기까지 해서 HTTP 헤더 내용을 모두 다뤄봤다. 
나름 어렵지 않게 설명하려 애 썼는데, 다들 어떻게 느끼셨는지 모르겠다. 
의견이 있으시면 댓글로 주시면 좋겠다. 적극적으로 반영하여 강좌 내용의 질을 높일수 있게 하겠다. 






아!!!!

HTTP 헤더를 이야기 하면서 아래와 같이 4가지 HTTP 헤더를 다뤘었다. 

  1. 요청 헤더 (Request Header)
  2. 응답 헤더 (Response Header)
  3. 일반 헤더 (General Header)
  4. 엔티티 헤더 (Entity Header)
요청헤더, 응답헤더는 명확해서 알겠는데, 일반헤더는 뭐고, 엔티티 헤더는 뭐지?? 
이 두개는 요청이나 응답에 들어 가는 거니까.. 거기에 두면 안되나? 

이런 생각을 가진 분이 계시리라... 나도 그랬으니까~.. ㅎ

이 내용을 간단히.... 정말 간단히 정리하고 오늘 포스팅을 마친다. 
  • 요청헤더 : 요청메시지에서만 확인할 수 있는 헤더
  • 응답헤더 : 응답메시지에서만 확인할 수 있는 헤더
  • 일반헤더 : 요청/응답 모두에서 확인할 수 있는 헤더
  • 엔티티헤더 : 본문(메시지 바디)에 관련된 HTTP 헤더, 따라서 응답헤더에서 확인 됨

이제 HTTP 보안에 관련된 내용 그리고 HTTP 가속에 관련된 내용이 남았다. 
조금만 더 가면 된다. 힘을 내자. ^^


2017년 8월 21일 월요일

[HTTP 프로토콜 강좌]#21 HTTP 엔티티 헤더 I - Content-Encoding, Content-Language, Content-Length, Content-Location, Content-Type, Content-Range

오늘부터 이틀간 HTTP 헤더의 마지막인 엔티티(Entity) 헤더를 다루게 된다.
메시지 바디 부분에 포함되는 부분의 정보를 담는 것이다 보니 주로 응답헤더쪽에 많이 사용된다.

오늘은 엔티티 헤더 중 주로 Content 로 시작하는 헤더를 이야기 한다.


  1. Content-Encoding
  2. Content-Language
  3. Content-Length
  4. Content-Location
  5. Content-Type
  6. Content-Range


총 6개에 해당하는 내용이지만, 각 헤더별로 살펴볼 내용이 그리 많지는 않다.


1. Content-Encoding

웹서버가 응답으로 전달하는 메시지의 인코딩 방식을 명시하는 헤더이다.
주로 Content-Type 헤더와 같이 사용되며, Content-Type 은 전달하는 컨텐츠의 포맷을 나타낸다.

예로, 다음과 같이 클라이언트가 요청한 aaa.pdf 파일에 대한 응답 결과를 보자.


위와 같이 웹서버의 응답헤더에서 Content-Encoding, Content-Type 부분을 보면,

  • Content-Type : application/pdf
  • Content-Encoding : gzip
이다. 
문서가 PDF 형태의 문서였으니 Content-Type 에 'application/pdf' 형태로 나타냈고, 전달하는 메시지 인코딩 방식은 'gzip' 을 이용해서 전달한다는 의미이다. 

이렇듯, Content-Encoding 은 전달하는 메시지의 압축방식과 관련이 깊다. 
HTTP 에서는 Content-Encoding 의 값으로 총 4가지를 사용할 수 있음을 정의하고 있다. 

  1. compress : 유닉스 시스템에서 사용하는 압축방식이다. 
  2. deflate : zlib 압축 포맷이다. 이는 RFC 1950에 정의되어 있다. 
  3. gzip : gzip 프로그램을 이용하여 압축한 형태이다. RFC 1952에 정의되어 있다. 
  4. identity : 특정한 압축 포맷이 사용되지 않았음을 의미한다. 
Content-Encoding 은 앞서 배웠던 HTTP 메시지 전송방식의 Transfer-Encoding 과는 비슷하면서도 차이가 있다. 
Content-Encoding 은 전달하는 컨텐츠 본래의 형태이지만, Transfer-Encoding 은 HTTP 서버에 의해 적용되는 컨텐츠 전송 방식인 것이다. 

* Transfer-Encoding 헤더의 자세한 내용은 여기 를 통해 확인 할 수 있다. 


2. Content-Language 

전달되는 컨텐츠 자체의 언어를 정의하는 헤더이다. Content-Language 의 값의 형태는 Accept-Language 와 같다.

Accept-Language 헤더의 자세한 내용은 여기 를 통해 확인 가능하다.

Content-Language 는 한국어,영어와 같은 인간의 언어를 표시한다. 컴퓨터언어인 C나 자바가 아님은 참고로 알아 두자.





3. Content-Length

메시지 바디의 전체 사이즈를 뜻하는 헤더이다. 보통 바이트 단위로 표시된다.
여기서.. 한가지 문제..
우리가 앞서 HTTP 요청 방식 중 HEAD 를 배웠었다. HEAD는 GET과는 달리 응답헤더만 요구할뿐 컨텐츠 자체는 되돌려주지 않는다.
그럼 HEAD 방식으로 컨텐츠를 요청했을때 메시지 바디가 없는데.. 이때의 Content-Length는 어떻게 표시될까?
그렇다. HEAD 로 요청한다고 해도, Content-Length에는 메시지 바디의 전체 사이즈를 표시해서 응답을 하게 된다.

Content-Length는 HTTP 1.1 환경에서 반드시 필요한 헤더 정보이다. 수신자는 이 정보를 참고하여 자신이 요청한 컨텐츠의 시작과 끝을 결정한다.

수신자가 컨텐츠의 시작과 끝을 결정하는 것에 다른 정보를 활용하기도 한다.
앞서 배웠던 Transfer-Encoding 의 Chunked 방식이 있고.. 또한 TCP 커넥션의 종료도 메시지바디의 마지막으로 인식한다.

다음은 수신자가 컨텐츠의 마지막을 결정하는 방식을 정리한 것이다. 아래 순서는 우선순위를 의미하기도 한다.


  1. 응답메시지의 상태코드가 1xx, 204, 304 인 경우 컨텐츠 자체를 포함하지 않기 때문에 헤더필드 다음의 공백 라인이 메시지의 끝이다.
  2. Transfer-Encoding 방식이 Chunked 인 경우 Chunked 전송방식과 같이 메시지바디의 끝에 '0' 을 표시하여 끝을 알린다. 
  3. Content-Length 에 표시된 전체 바이트를 참고하여 수신 바이트를 계산한다.
    계산된 바이트를 모두 전송받은 경우가 메시지 바디의 끝이다. 
  4. Content-Type 의 헤더값이 multi-part/byteranges 인 경우 미디어 타입 형태에서 끝을 명시한다. 
  5. 서버의 TCP 커넥션이 끊어진 경우 서버로부터 전송받은 마지막 바이트가 메시지 바디의 끝부분이다.  



4. Content-Location

Content-Location 헤더는 메시지 바디와 관련된 URI 정보를 제공하는 헤더이다.
클라이언트의 Accept-Language 헤더 정보를 이용해서 사용자의 언어환경을 파악한 후 적절한 언어의 서비스 URI 를 전달하려 할때 활용할 수 있다.

예를 들어 웹서버가 다중 언어를 지원하는 형태로 개발되었다고 하자.
영어환경의 사용자에게는 영문 메인페이지 URI를... 한국어 사용자에게는 한글 메인페이지 URI를 제공하려면, Content-Location 헤더를 이용하면 된다.

Accept-Language: en-US 인경우, 응답헤더의 Content-Location: /main_us.html 를...
Accept-Language: ko-KR 인경우, 응답헤더의 Content-Location: /main_ko.html

이런식으로 처리하게 되면, 영어사용자에게는 영문홈페이지를, 한국어 사용자에게는 한글 홈페이지를 접속하게 할 수 있는것이다.

하지만, 생각보다 Content-Location 헤더의 사용빈도가 그리 높지는 않다. Location 헤더의 사용 빈도가 매우 높기 때문이다.

Location 헤더의 상세한 내용은 여기 를 통해 확인할 수 있다.

클라이언트가 접하는 결과물로 보면 이 두헤더가 비슷하지만 Content-Location 과 Location 헤더에는 차이점이 있다.

Content-Location 에 명시된 URI 가 메시지 바디 자체를 회신하는 것이지만, Location 에 표시된 URI는 클라이언트를 다른 URI로 라디이렉트 하는 것이다.

즉, 클라이언트가 요청한 컨텐츠의 메시지 바디가 Content-Location 의 URI 에는 직접 포함되어 있으나, Location 헤더의 URI에는 메시지 바디와 직접적인 연관이 없는 경우가 크다.

5. Content-Type

Content-Type 헤더는 클라이언트가 요청한 컨텐츠의 형태를 표시하는 헤더이다.
Content-Type 의 형태는 다음과 같다.


  •  Content-Type: 주타입 / 서브타입


이미 지난 시간에 다뤘던 Accept 헤더와 형태가 비슷하다.

다음은 실제 사용된 응답 헤더의 내용이다. (제일 마지막 라인 참고)



Content-Type 헤더의 값으로 메인 타입(image) 와 서브타입(png) 를 확인 할 수 있다.
Content-Type 헤더에는 아래 예와 같이 메시지 바디의 문자셋(Character-set) 을 추가적으로 명시할 수도 있다.

Content-Type: text/plain; Charser=ISO-8859-4




6. Content-Range

클라이언트가 대용량의 파일을 웹서버에서 다운로드를 하다가 중간에 끊기는 일이 발생했다. 클라이언트가 Range 헤더를 이용해서 끊긴 부분부터 다시 다운 받기를 시도하는 경우 웹서버는 Accept-Range 헤더와 함께 이어서 파일을 전송해 줄수 있다는 것을 이전 시간에 배운바 있다.

Range 헤더와 Accept-Range 헤더의 자세한 내용은 다음을 참고토록 하자.

  • Range 헤더 : 여기 를 클릭
  • Accept-Ragne 헤더 : 여기 를 클릭

Range 헤더를 이용해서 파일을 이어받으려는 경우 웹서버는 Accept-Range 헤더와 함께 클라이언트가 요청한 부분부터 데이터를 전송한다는 정보를 전달하는데 바로 이때 사용되는 헤더가 Content-Range 헤더이다.


위와 같이 웹서버가 다시 전송을 시작하는 시점을 Content-Range 에 표시한다.

끝~

2017년 8월 18일 금요일

[HTTP 프로토콜 강좌]#20 HTTP 일반 헤더 II - Transfer-Encoding, Upgrade, Warning, Trailer

이전 시간에 이어 오늘은 General 헤더의 마지막 시간이다.
오늘은 포스팅 글 제목에 있듯이 4개의 헤더를 다룬다.

  1. Transfer-Encoding
  2. Upgrade
  3. Warning
  4. Trailer



1. Transfer-Encoding

먼저 Transfer-Encoding 헤더를 이해하려면, HTTP 의 데이터 전송방식을 이해할 필요가 있다.

HTTP 1.0에서 클라이언트는 자신이 요청한 컨텐츠의 사이즈를 어떻게 알 수 있을까?
HTTP 1.0 은 연결유지 기능이 없기 때문에 TCP 커넥션이 끊어지는 것이 곧 데이터 전송의 완료라고 볼 수 있다.
(HTTP 1.0 에서는 하나의 TCP 커넥션에 하나의 요청만 처리되기 때문에 데이터 전송이 완료되면 커넥션이 끊어진다.)



따라서, HTTP 1.0 에서는 웹서버가 따로 전달하려는 데이터의 사이즈를 알려줄 필요가 없을뿐더러, 클라이언트 역시 데이터를 전달받기 전에 미리 사이즈를 알아야 할 이유가 없다.


하지만 HTTP 1.1에서는 좀 다르다. 바로 연결 유지(persist connection) 때문이다.
HTTP 1.1에서는 기본적으로 연결 유지 기능이 활성화 되어 있다. 하나의 TCP 커넥션에 여러개의 요청이 가능하기 때문에 클라이언트는 요청마다 전달될 컨텐츠의 데이터 사이즈를 미리 알고 있어야 한다. 웹서버가 전달해 주는 컨텐츠의 시작과 끝을 알아야만 해당 요청에 대한 처리가 올바르게 될 수 있기 때문이다.

그래서 HTTP 1.1에서는 Content-Length 라는 헤더로 전달하고자 하는 컨텐츠의 사이즈를 표시한다.

다음은 인기 그룹 트와이스의 이미지를 요청했을 때 서버의 응답헤더 부분이다.


응답헤더에서 볼수 있듯이 웹서버는 클라이언트의 요청 컨텐츠를 전달하기 앞서 Content-Length 헤더를 통해 이미지 사이즈를 먼저 알려준 후 데이터를 전달한다.

앞서 살펴 본 바와 같이 웹서버에서는 다음의 과정으로 데이터를 처리하게 되는데...

  1. 웹서버가 클라이언트의 요청을 받는다. 
  2. 웹서버는 클라이언트에게 전달해 줄 컨텐츠의 사이즈를 먼저 계산한다. 
  3. 계산된 컨텐츠의 전체 사이즈와 함께 데이터를 전달한다. 
바로 2번 과정에서 컨텐츠의 사이즈가 엄청 큰 경우 문제가 발생할 수 있다. 
컨텐츠가 큰 경우 전체 사이즈를 계산하는 과정이 오래 걸리게 되고.. 이는 곧 클라이언트가 느끼는 지연시간에 반영되게 된다. 

컨텐츠 사이즈가 큰 경우에는 이런 방식 보다는 좀 더 효율적인 다른 방식이 필요하다.
그것이 바로 "Chunked" 전송 방식이다. 

Chunked 전송 방식의 개념은 간단하다.
전체 덩어리를 한번에 주지 않고, 조금씩 조금씩 떼어 주는 방식이다. 
웹서버는 Chunked 방식으로 데이터를 전송하는 경우에는 전체 사이즈를 한번에 계산할 필요가 없다. 
일단 자신이 보내려는 덩어리 정도만 먼저 클라이언트에게 알리고 데이터를 보내고.. 그 다음에 또 전송할 덩어리만큼 알리고 보내고.. 글로 표현하자니.. 이거 원.... 
아래 그림을 참고해 보자. 



그림처럼 클라이언트가 트와이스 이미지를 요청하면, 웹서버는 전체 이미지의 부분만 떼어서 전달해 주는 방식이다.  떼어주는 부분의 사이즈만 알려주면 되기 때문에 전체 사이즈를 계산하지 않아도 되어서 기존 전송방식의 단점을 극복한 방식이다. 

컨텐츠의 마지막 부분을 전송하고 나서는 "0" 을 보내어 데이터가 모두 전송되었음을 알린다.



따라서 Chunked 전송방식에는 Content-Length 헤더가 존재하지 않는다. 
아래 Chunked 방식의 HTTP 헤더 내용을 살펴보자. 



  1. Transfer-Encoding: Chunked 를 통해 Chunked 전송방식으로 데이터를 전송할 것을 알린다. 
  2. 이후 데이터 전송시 전송하려는 데이터의 부분적인 사이즈를 16진수로 표시하여 알린 후 실제 데이터를 사이즈만큼 보낸다. 
  3. 위 2번 과정을 반복한다. 
  4. 데이터의 마지막 끝부분에 "0" 을 표시하여 데이터 전송이 완료되었음을 알린다. 
이 과정이 Chunked 전송방식의 전부이다. 

정리하면 Chunked 방식은 전달하려는 컨텐츠의 사이즈가 큰경우 서버의 처리 지연을 보완할수 있는 방법인것이다. 

Transfer-Encoding 헤더는 Chunked 전송방식으로 데이터를 전달하려 할때 주로 사용되는 헤더이며, 값으로는 위 헤더 내용처럼 "Chunked" 를 가지게 된다. 




2. Upgrade

Upgrade 헤더는 클라이언트와 서버간 통신 프로토콜을 바꾸려고 할때 사용하는 헤더이다. 새로운 HTTP 버젼이나 또는 TLS 와 같은 암호화 프로토콜로 변경하려고 하는 경우 Upgrade 헤더를 이용해서 프로토콜을 변경할 수 있다.

다음은 그 예이다.

GET http://www.compay.com/index.html HTTP/1.1
Host: www.company.com
Upgrade: TLS/1.0
Connection: Upgrade

위와 같은 요청을 받으면 서버는 "101 Switching Protocols" 상태 코드를 다음과 같이 전달한다.

HTTP/1.1 101 Switching Protocols
Upgrade: TLS/1.0, HTTP/1.1
Connection: Upgrade

클라이언트의 요청, 그리고 웹서버의 응답헤더 모두에 "Connection: Upgrade" 가 포함되어 있다. 이 부분은 Upgrade 헤더를 사용하면 항상 같이 포함되어 있는 헤더이다. 이유는 클라이언트가 직접 통신하는 대상은 실제 웹서버일수도 있지만, 중간 프록시 서버가 존재하는 경우라면 실제 웹서버가 아니기 때문이다.

클라이언트는 실제 통신하는 대상과 프로토콜 협상을 하기 때문에 Upgrade 헤더가 프록시를 경유하여 직접 통신하지 않는 실제 웹서버나 다른 프록시서버로 전달될 필요가 없다.

따라서 프록시를 경유하여 전달되는 헤더 정보에서 Upgrade 를 제거해야 하는데 이를 위해서는 Connection 헤더가 필요하기 때문이다.
(Connection 헤더에 대해서는 바로 이전 시간에 상세히 다룬바 있다. 여기 를 클릭하여 자세한 내용을 확인할 수 있다.)

"101 Switching Protocols" 상태코드도 Upgrade 헤더에 의한 확인 메시지로 사용된다. 위 응답헤더에서 우리는 TLS 1.0을 통한 HTTP 1.1 로 업그레이드 되었음을 알 수 있다.


3. Warning

Warning 헤더는 캐시서버의 문제점을 사용자에게 알리는 용도로 사용되는 헤더이다. 다음과 같은 형태로 경고코드 및 내용등이 포함되어 진다.

Warning: 110 proxy.com "Response is stale"
             Fri, 31 Dec 2000 10:10:07 GMT

위 내용 처럼, 첫번째 필드는 경고 코드(110), 그리고 다음 필드는 경고코드가 생성된 서버(proxy.com), 그리고 인용부호 안에 메시지(Response is stale)은 일반적인 경고 메시지이다.

추가적으로 마지막 필드의 시간정보는 경고 문구가 만들어진 시간인데, 사실 필수는 아니고 있어도 되고, 없어도 되는 옵션 필드이다.

HTTP 1.1에서 정의하고 있는 경고 코드(Warning Code) 는 다음과 같다.

코드 설명 의미
110 Response is stale 캐시서버가 제공한 컨텐츠가 만료시간을 초과한 오래된 것이다. (아마도 클라이언트가 max-stale 캐시 항목을 사용한것으로 보인다.)
111 Revalidation failed 캐시서버가 제공하려는 컨텐츠의 유효성 체크에 실패했다. (아마도 실제 웹서버와 통신할 수 없는 상태인것 같다.)
112 Disconnection operation 캐시서버가 의도적으로 통신이 끊겼다.
113 Heuristic expiration 캐시서버가 제공하려는 컨텐츠가 아직은 유효한데, 저장된지 24시간 이상 지난 컨텐츠입니다.
199 Miscellaneous warning 임의적인 경고 메시지입니다
214 Transformation applied 캐시서버가 컨텐츠를 임의적으로 수정했습니다.(캐시 저장공간이 넉넉치 않아 이미지 포맷을 변경한것 같습니다.)
299 Miscellaneous persistent warning 경고코드 199와 같은 임의적인 경고메시지인데 좀 상태가 지속되는 것으로 보입니다.




4. Trailer

클라이언트와 서버는 Chunked 전송방식을 사용하는 경우 Trailer 헤더를 포함할 수 있다. Trailer 헤더는 다른 HTTP 헤더처럼 나열되게 되는데, 위치가 메시지 바디의 제일 끝부분이다.

Trailer 헤더는 수신자로 하여금 어떠한 HTTP 헤더가 Chunked 방식의 트레일러로 사용될 것인지를 알게 해주는 헤더이다.

트레일러 헤더로는 HTTP 헤더 중 어떤것도 사용이 가능하지만 대표적으로 아래 3가지는 사용이 금지된다.


  • Transfer-Encoding
  • Content-Length
  • Trailer
다음 예제를 통해 Trailer 헤더가 어떻게 사용되는지 확인 해 보자. 

HTTP/1.1 200 OK
Date: Mon, 21 Aug 2017 09:20:01 GMT
Content-Type: text/plain
Transfer-Encoding: Chunked
Trailer: Expires

1a
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0
Expires: Sat, 25 Aug 2017 18:00:00 GMT

위 예제는 응답헤더에 Trailer 가 사용된 예이다. Trailer 헤더의 값으로 Expires 헤더를 명시하였다. 즉, Expires 를 Chunked 메시지의 트레일러로 사용하겠다는 의미이다. 
데이터 제일 마지막 부분에 Expires 헤더 정보가 위치함을 확인할 수 있다. 

이상 끝~

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 를 이용하여 모바일 디바이스를 구분하기도 하고, 접근을 제어하기도 한다.

이상 끝!~