Protocols for the World-Wide Web Service
(HTTP/1.0, HTTP/1.1, PEP, and HTTP-NG)

305-350, 대전광역시 유성구 가정동 161번지
한국전자통신연구소 멀티미디어표준연구실
김 용 운
E-mail : qkim@pec.etri.re.kr
URL : http://pec.etri.re.kr/~qkim/

World-Wide Web 서비스 자체를 위해 쓰이는 프로토콜은 HTTP라고 하는 것이다. 최초에 개발되었을 때는 단지 실제 데이타의 전송만을 위해 쓰였으나 지금은 다양한 기능을 프로토콜에 넣고자 하고 있다. 이러한 과정으로 개발되고 있는 다양한 프로토콜들을 여기서 정리하고자 하며 미처 정리하지 못한 다른 프로토콜들은 다음 기회에 정리하고자 한다. 이 글에서는 아래의 네 가지 프로토콜에 대해 살펴보도록 한다.


HyperText Transfer Protocol - HTTP/1.0
(Korean Version 2.0)

Abstract:
HTTP는 HyperText Transfer Protocol의 약자이며, 분산환경 및 공동작업 환경에 이용할 하이퍼미디어 정보시스템의 개발을 목적으로 설계된 응용계층의 프로토콜로서 WWW에서의 하이퍼텍스트 문서의 전송을 위해 쓰이는 프로토콜이란 뜻이다. 그러나 글뜻에서 보이는 HyperText 문서만이 아니라 음성, 화상, 데이타 등과 같이 MIME에 의해 정의될 수 있는 모든 문서 형식을 전송할 수 있다. 이것은 HTTP 프로토콜의 기본적인 전송 방식이 이진모드(binary mode)에 근거하고 있기 때문이다. 여기에서는 HTTP 프로토콜의 구조와 동작 메카니즘에 대해 살펴보고자 한다.[1]

Keywords:
HTTP, Protocol, BNF, Message, Header, Request, Response, Entity, Method, Proxy, Cache, Access Authentication

Status:
이 문서는 ftp://ds.internic.net/rfc/rfc1945.txt 문서를 정리한 것이다. 본문 속에 들어있는 많은 부분이 그대로 또는 보완되어 있으며, 빠져있는 부분은 Korean Version 3.0에 추가될 예정이다. 본 문서인 Korean Version 2.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/http10v2.html 이며, 이전 문서인 Korean Version 1.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/http10v1.html 이다. 최종적으로 정리될 완결판은 Korean Version 3으로 정리될 것이며 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/http10v3.html 이다. WWW에서 사용하는 각종 프로토콜에 대한 문서 정리는 http://pec.etri.re.kr/~qkim/HTTP/에 정리되고 있으며 문서 내용의 변경에 대한 알림글이 있다.

1. 서론

1.1 HTTP vs. TCP/IP

HTTP는 World Wide Web에서 사용하고 있는 데이타 전송 프로토콜이며 MIME으로 지정할 수 있는 모든 데이타 형식에 대해 8bit 이진모드로 전송할 수 있다. (8bit 이진모드 전송이라 함은 1bit도 빠짐없이 완전무결하게 전송한다는 것이며 7bit 아스키모드 전송이라 함은 8bit 기본 단위에서 MSB 1bit의 완전무결성을 보장하지 못 한다는 것이므로 데이타 전송에 오류가 생길 가능성이 있다. 따라서 ASCII 텍스트 문서를 전송할 때는 7bit 아스키모드로 전송을 해도 되지만 실행파일과 같은 binary data를 전송하고자 할 때는 반드시 8bit 이진모드로 전송하여야만 한다.)

이것은 FTP의 경우에서와 같이 이진모드로 데이타 송수신이 가능함을 뜻하며, 다만 WWW용의 추가적인 정보가 HTTP 프로토콜에서 활용되고 있을 뿐이다. 따라서 HTTP 프로토콜은 TCP/IP 프로토콜 체계 가운데 TELNET이나 FTP와 같은 응용 프로토콜의 한 가지이다. 즉, 아래의 그림에서 보이는 것처럼 HTTP는 TELNET처럼 TCP 수송계층 프로토콜을 이용해서 데이타 송수신을 하는 응용 계층 프로토콜의 일종이라는 것이다.

TCP/IP 프로토콜에서는 TCP 전송 프로토콜을 이용하는 응용 프로토콜들 사이의 구별을 port 번호를 통해 해결하고 있다. 그러므로 HTTP 응용 프로토콜에 할당되어 사용하는 TCP 포트가 있으며 80번으로 지정되어 있다. 정의되어 있지 않은 다른 임의의 포트를 이용할 수도 있으나 기본적으로 정의되어 있는 번호는 80번이다.

그렇다고 해서 HTTP 프로토콜은 TCP/IP에서만 동작할 수 있는 것은 아니다. OSI 참조모델을 이용한 프로토콜 체계에서도 수송계층의 전송 프로토콜 상위에서 HTTP 프로토콜은 응용 프로토콜로서 활용될 수 있는 것이다. 다만 다른 프로토콜 체계에서 사용하고자 할 때는 그에 맞게끔 약간의 적절한 수정을 해야만 가능할 것이다.

TCP/IP Protocol Stack
[그림 1] TCP/IP Protocol Stack[2]

버전 1.0 HTTP 프로토콜(HTTP/1.0)은 IETF (Internet Engineering Task Forces)에 의해 RFC 1945로 정식 등록되었으며, 버전 1.1은(HTTP/1.1)은 Proposed Standard로 등록되어 RFC editor에 의해 재작성된 후 RFC로서 새로이 등록될 예정이다. 현재의 WWW에서 쓰이고 있는 HTTP 프로토콜은 1.0 버전이며 1.1 버전의 것이 구현되고 있는 중이고 '96년 10월 현재 W3C에서 발표한 Amaya와 Jigsaw가 1.1 버전을 구현한 것이다.

1.2 HTTP의 등장 배경

실제적인 정보시스템에서는 검색, 정보 갱신, 및 주석 등과 같은 간단한 작업보다는 보다 다양한 기능을 필요로 하고 있다. 또한 분산 환경, 공동작업 환경, 하이퍼미디어 정보시스템 등의 상황에서 필요로 하는 빠른 속도와 간편성을 제공하기 위한 프로토콜이 필요하게 되었고 이를 목적으로 HTTP 응용 프로토콜이 설계되었다.

이에 따라 대상체의 위치나 이름을 지정하는 URI에 의해 제공되는 정보를 이용하여, 대상 화일을 어떻게 활용할 것인가 지정하는 method의 집합에 따라서 적절한 기능 동작을 하게끔 HTTP는 설계되어 있다. 이에 따라 송수신되는 프로토콜 구성체는 메시지라는 이름으로 불리우며 Internet Mail과 MIME에서 사용하는 방식과 비슷하게 구성되어 송수신된다.

또한 HTTP는 사용자 브라우저와 프락시 서버 또는 게이트웨이 사이에서 SMTP, NNTP, FTP, Gopher, WAIS 등과 같은 기존 프로토콜과의 통신을 가능하게 해주는 프로토콜의 역할을 하게끔 할 수도 있다. 이에 따라 기존의 축적되어 있는 하이퍼미디어 정보들을 그대로 활용할 수 있게 하며 사용자 브라우저의 구현도 단순화 시킬 수 있게 한다.

1.3 HTTP 프로토콜 규격서에 쓰이는 용어

HTTP 프로토콜 설명서에는 여러 가지 용어들이 쓰이고 있으며 주요 용어들에 대해 설명하도록 한다.

연결(connection)
데이타 송수신을 위해 두 개의 응용 프로그램 사이에 TCP 데이타 전송 프로토콜을 이용해서 만들어진 가상적인 연결선

메시지(message)
HTTP 프로토콜의 통신을 위해 사용되는 기본적인 송수신 단위

요구(request)
HTTP 프로토콜 상에서 브라우저가 어떤 데이타 요구를 하기 위해 보내는 HTTP 메시지

응답(response)
HTTP 프로토콜 상에서 서버가 수신한 요구에 대해 처리한 결과를 브라우저에게 응답으로 보내는 HTTP 메시지

자원(resource)
URI에 의해 지정될 수 있는 서비스 또는 통신망 상의 데이타

엔터티(entity), 개체
전송 가능한 데이타 자원 또는 어느 서비스 제공용 서버로부터의 응답이 엔터티가 될 수 있으며, 이것은 요구 또는 응답 메시지에 포함될 수 있어야 한다. 엔터티는 그 자체 정보(content)와 이것이 어떤 형태의 데이타인지 알려주는 metainformation으로 (4.2.4 참조) 구성되어 있다.

클라이언트(client)
HTTP 프로토콜 규약에 맞추어 요구를 보내고 서버가 보내오는 응답을 수신하는 역할을 하며, 이런 송수신을 위해 연결을 설립하는 응용 프로그램. 브라우저라고 불리기도 한다.

브라우저(browser), 사용자 에이전트(user agent)
요구를 발생시키는 역할을 하는 클라이언트 프로그램. 브라우저, editors, spiders(web-traversing robots) 등.

서버(server)
요청받은 서비스를 제공해주기 위해 연결을 허용하는 응용 프로그램

origin server
실제 데이타를 저장해두고 있거나 요구에 의해 저장할 수 있는 장소

프락시(proxy)
다른 클라이언트 프로그램과의 사이에서 서버로서도 클라이언트로서도 동작하는 중계 프로그램. requests는 내부적인 동작에 의해 처리되어 제공되든지, 아니면 다른 서버로 전달되든지 한다.

게이트웨이(gateway)
다른 서버와의 중계 역할을 하는 서버. 프락시와는 달리 브라우저가 요구한 것에 대해 마치 실제 서버인양 서비스를 제공해준다. 따라서 브라우저에서는 제공받은 서비스가 게이트웨이로부터 전달된 것인지 모른다.

캐시(cache)
응답받은 메시지를 자신의 컴퓨터에 저장한 장소 또는 저장/검색/삭제가 가능하도록 만든 저장 시스템. 이미 가져온 데이타를 저장해두고 있다가 같은 데이타인 경우 다시 가져오지 않고 저장되어 있는 것을 보여주도록 하여 응답 시간을 빠르게 하고 통신망 이용의 효율성을 높인다.

터널(tunnel)
두 개의 연결 사이에서 무조건 중계(blind relay)의 역할을 하는 중간 프로그램.

1.4 HTTP 프로토콜의 동작

HTTP 프로토콜은 요구/응답 (Request/Response) 방식을 이용하여 동작하고 있다. 즉, 원하는 프로토콜 기능(예: GET, HEAD, POST)에 대해 서비스 요구를 하면 데이타 송수신을 위한 TCP 연결이 만들어지고, 서버가 응답을 보내어 데이타 전송을 끝내면 자동적으로 연결이 끊어지게 되는 것이다.

즉, 클라이언트는 서버와의 사이에 TCP를 기반으로 한 HTTP 연결을 만들고 method, URI, protocol version, 클라이언트 정보, 사용자 데이타 등과 같이 규정되어 있는 요구 형식에 따라 서버에게 요구 메시지를 보낸다. 서버는 프로토콜 버전, 성공 또는 오류코드 번호, 서버 정보, 데이타 정보, 사용자 데이타 등을 포함하는 응답 메시지를 보낸다.

아래 1.4.1절과 1.4.2절에 요구와 응답의 경우에 대한 간단한 예를 보이고 있다.

1.4.1 Requests

HTTP의 Request 형식은 아주 간단하다. 첫 번째 줄 처음에 어떤 기능을 이용하려는지 지정을 한다. 가장 일반적으로 쓰이고 있는 것이 GET 이다. 이것은 브라우저가 서버에게 문서를 보내달라고 요청하는 것이다. 그 다음에는 화일 이름처럼 대상이 되는 것을 지정하고 현재 쓰이고 있는 HTTP 프로토콜의 버전을 지정한다. 이 다음에는 일련의 지정 사항들을 덧붙일 수가 있은데, 예를 들어 브라우저의 종류나 브라우저가 다룰 수 있는 데이타 형식 등이다. 아래와 같은 예를 볼 수 있다.

Request Example
GET  /index.html  HTTP/1.0
Accept: text/plain
Accept: text/html
Accept: */*
User-Agent: Netscape 1.2

1.4.2 Responses

HTTP에서의 응답 형식도 아주 간단하게 구성되어 있다. 서버에서 쓰이고 있는 프로토콜 버전, Request에 대한 실행 결과, 전달해줄 데이타의 형식, 데이타 길이 등과 같은 추가적인 정보가 전달되고, 이러한 헤더 정보의 끝을 나타내는 빈줄이 들어가고, 뒤이어 실제 데이타가 전달된다. 데이타 전달이 끝나면 서버는 연결을 끊는다. 아래와 같은 예를 볼 수 있다.

Response Example
HTTP/1.0 200 OK
Server: MDMA/0.1
MIME-version: 1.0
Content-type: text/html
Last-Modified: Thu Jul 7 00:25:33 1994
Content-Length: 2003
Right here waiting for you...

1.5 HTTP 프로토콜의 구성

HTTP 프로토콜이 구성되어 있는 형식을 표현하기 위한 방법이 있는데 여기서 사용하는 것은 BNF (Backus-Naur Form) 형식이며 여기에 약간의 보충을 하여 이용하도록 한다. 이를 위해 표현 형식에 대한 설명을 먼저 하도록 하고, 프로토콜 형식의 표기상 사용한 약속을 정의하고, 이어서 HTTP 프로토콜로서 동작하는 메시지의 종류와 구조를 살펴보도록 한다. TCP/IP 연결을 통해 송수신되는 HTTP 프로토콜 데이타는 메시지라는 종류로 구분되고 있다. 즉, 요구 메시지와 이에 대한 응답 메시지가 바로 그것이다. 이 속에 구성되어 있는 규격이 HTTP 프로토콜 규격이 된다.

2. BNF (Backus-Naur Form) 형식

2.1 확장 BNF

이 문서에 포함되어 있는 모든 메카니즘들은 RFC 822에서 사용하고 있는 것과 비슷하게 BNF와 이에 대한 정의 설명으로 표현되어 있다. 구현자들은 이것을 숙지하여 HTTP 프로토콜 규격서를 이해하면서 구현하여야 한다. 확장 BNF는 다음과 같다.

name=definition
어떤 규격의 이름과 이에 대한 정의를 나타내고 있으며 '=' 표시에 의해 구분되고 있다. 빈 공백은(whitespace)는 한 줄 이상의 여러 줄로서 표시되는 규약에 있어 연이은 줄임을 나타내는 들여쓰기(indentation)의 의미로서만 쓰인다. 예를 들어 다음과 같은 예가 있다.

Request = Simple-Request | Full-Request 또는,

Method = "GET" | "HEAD" | "POST" | extension-method
"literal"
'"' 표시 사이에 들어가는 것은 단어 그 자체로서 표현되는 것이다. 따라서 HTTP 프로토콜에서는 이 문자 그대로 송수신된다. 다음과 같은 예를 살펴볼 수 있는데, 뒤에서 나올 프로토콜 규격에 나오는 weekday란 부분은 일곱 가지 요일 가운데 하나가 글자 그대로 전달된다는 것이다.

weekday = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"
rule1 | rule2
OR 조건을 나타낸다. 따라서 두 가지 가운데 한 가지를 택할 수 있다는 뜻이다.

(rule1 rule2)
두 가지 요소로 구성되어 있으나 하나의 요소로서 취급한다는 뜻이다. 아래와 같은 예의 경우에,

"(elem (foo | bar) elem)" 이것은 "elem foo elem""elem bar elem" 두 가지로 구성된다는 뜻이다.

*rule
이것은 반복을 의미하는 것으로서 뒤이어서 나올 #rule과 혼동을 일으키는 표현 방식이므로 유의해야 한다. 반복을 통해 이루어지는 결과는 하나의 단어나 한 개의 수 표현 형태로 되는 것이며 #rule에서는 똑같은 반복이지만 단어나 수의 열 형태로 여러 개가 나올 수 있다. *rule의 표기 방법은 아래와 같이 해서 쓰인다.

<n>*<m>element 이것은 적어도 n개와 최대 m개의 element 요소로 구성되는 한 가지 결과를 의미한다. 즉, 1*2DIGIT 라는 표현은 숫자가 적어도 한 개 최대 두 개로 구성되어 한 개의 수를 나타낸다는 뜻이다. 4는 한 가지 예이며, 45도 한 가지 예가 된다. 그러나 345의 경우에는 숫자 세 개로 구성되어 있으므로 최소 갯수와 최대 갯수에 위배되어 적합하지 않다.

n의 기본값은 0이며 m의 기본값은 무한대이다. 그러므로 "*(element)"는 0개를 포함해서 어떤 갯수라도 가능한 표현법이다. "1*element"의 경우는 적어도 한 개는 있어야 하며 최대 갯수에는 제한이 없다.

[rule]
선택적으로 사용할 수 있다는 뜻이다. 예를 들어, "[foo bar]" 이것은 "foo bar"를 사용할 수도 있고 사용하지 않을 수도 있다는 것이다. 그러므로 "*1(foo bar)"로 표현할 수 있다.

N rule
특정 횟수만큼의 반복을 나타낸다. 2DIGIT은 두 자리 숫자를 나타낸다는 것이다. 따라서 "*(element)"로 나타낼 수 있는 것이다.

#rule
앞서 설명한 것처럼 반복을 나타내긴 하지만 요소들의 나열로서 표현되는 것이다. 즉, 1#Method 라고 하면 Method의 요소들은 GET, HEAD, POST 등이므로 적어도 한 개의 Method가 있어야 하고 최대 갯수는 제한이 없다는 것으로 이해할 수 있다. 다시 말해 GET 하나만으로 구성될 수도 있고, GET, HEAD, POST 이렇게 세 가지 요소들의 나열로서 표현될 수도 있다는 것이다. 각 요소들 사이의 구분은 ','를 이용한다. 또 다른 예를 들자면, 1#2(2DIGIT) 이것은 숫자 두 개로 구성된 수가 적어도 한 개가 있어야 하며 최대 두 개까지 가능하다는 것이다. 즉, 23 이렇게 표현될 수도 있고, 23, 56 이렇게 두 개로 표현될 수도 있다.

이것이 *rule과의 차이점이고, #rule 에서도 "#element" 의 구성이 그대로 성립함을 볼 수 있다. 이에 대한 설명은 *rule 의 경우와 같다. ','를 이용하여 나열함에 있어, null element가 허용된다. 예를 들어, 1#3(2DIGIT)과 같은 표현식에 대해

23, , 56, 34 이렇게 null element 표시가 가능하지만, 실제 갯수는 세 개로서 간주된다. 따라서 최소 한 개 최대 세 개의 제한에 위배되지 않는다.

; comment
이것은 규칙에 대한 설명을 하기 위해 표시하는 부분이다. 줄의 끝까지가 이 표시가 미치는 영향이다. 따라서 다음 줄까지 설명문을 연장하려면 다음 줄 처음에 ; 표시를 하여야 한다. 즉, 다음과 같다.

Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822 ; updated by RFC 1123
implied *LWS
두 개의 인접한 단어 (token or quoted-string) 또는 인접한 토큰(tokens)과 식별자 (tspecials) 사이에 LWS(linear whitespace)가 포함될 수 있다. 여기서 두 개의 토큰 사이에는 반드시 적어도 하나의 식별자가 존재하여 서로 하나의 토큰으로 간주되지 않게끔 구별되어야 한다.

2.2 기본적인 규칙

OCTET = <any 8-bit sequence of data> CHAR = <any US-ASCII character (octets 0 - 127)> UPALPHA = <any US-ASCII oppercase letter "A" .. "Z"> LOALPHA = <any US-ASCII lowercase letter "a" .. "z"> ALPHA = UPALPHA | LOALPHA DIGIT = <any US-ASCII digit "0" .. "9"> CTL = <any US-ASCII control character (octets 0-31) and DEL(127)> CR = <US-ASCII CR, carriage return (13)> LF = <US-ASCII LF, linefeed (10)> SP = <US-ASCII SP, space (32)> HT = <US-ASCII HT, horizontal-tab (9)> <"> = <US-ASCII double-quote mark (34)> CRLF = CR LF ; CR LF로 구성되어 있으며 Entity-Body를 제외한 모든 프로토콜 요소들에 ; 대한 줄의 끝 (end-of-line)을 표시한다. LWS = [CRLF] 1*(SP | HT) ; HTTP 프로토콜 헤더가 여러 줄로 구성될 수 있는데, 이때 다음 줄로의 ; 계속 표시를 나타내는 데에 쓰인다. 줄의 첫 시작에 SP나 HT가 있으면 ; 앞 줄의 계속으로서 인식된다. TEXT = <any OCTET except CTLs, but including LWS> ; LWS는 포함하나 모든 CTL 요소를 제외한 OCTET. 내용 설명 및 값 ; 표시로서 쓰일 수 있으며 메시지 해석기(parser)에서 번역되지는 않는다. ; US-ASCII 문자세트 이외의 octets를 포함하는 TEXT 필드의 경우에는 ; ISO-8859-1 문자로 표현된 것이라고 간주한다. HEX = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT word = token | quoted-string ; HTTP 프로토콜의 헤더 필드는 LWS 또는 특수 문자들에 의해 구분되는 ; 단어들로 구성되어 있다. 이러한 특수 문자들은 파라미터 값 속에 ; '"'(quoted string) 표시에 의해 나타내진다. token = 1*<any CHAR except CTLs or tspecials> ; CTL 문자나 tspecials 문자를 제외한 하나 이상의 문자로 구성된 글자. tspecials = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT ; 위에서 <"> 표기는 "(" 의 경우와 똑같이 그 문자 자체를 나타낸다. comment = "(" *(ctext | comment) ")" ; HTTP 프로토콜 헤더 속에 괄호 표시로서 설명문을 포함시킬 수 있다. ctext = <any TEXT excluding "(" and ")"> ; 괄호를 제외한 어떤 문자라도 가능하다. quoted-string = (<"> *(qdtext) <">) ; 괄호 표시 속에 전체가 들어 있으므로 한 가지 요소로서 취급된다. ; 예를 들어, "I Love You!" 가 이의 예가 된다. qdtext = <any CHAR except <"> and CTLs, but including LWS>

여기서 "\"를 사용하는 single-character quoting은 HTTP/1.0에서는 허용되지 않는다.

3. HTTP 프로토콜 파라미터

HTTP 프로토콜 규격 설명서는 메시지 단위의 설명으로 이루어져 있으며 이를 위하여 여러 가지 파라미터가 표현되어 있다. 이러한 기본적인 파라미터들의 종류와 내용을 살펴보도록 한다.

3.1 HTTP Version

HTTP 프로토콜의 버전을 표현하기 위해 "." 방식을 사용한다. 여기서 major 부분은 프로토콜 메시지 형식의 변경과 같이 중요한 변경 사항이 있을 때 사용하는 것이고, minor 부분은 파라미터 변경과 같이 부수적인 사항들의 변경이 있을 때 사용하는 것이다. 현재 이루어지고 있는 프로토콜의 버전은 1.0이다. 각 숫자는 양의 정수를 사용하여 1씩 증가하도록 되어 있으므로, HTTP/2.13은 HTTP/2.4보다 상위 버전이다.

프로토콜의 버전을 나타내는 것은, 송신측이 요구(request)를 보낼 때 사용하는 메시지의 표현 형식을 나타내고 서버나 브라우저가 어떤 형식의 메시지를 이해하고 처리할 수 있는지 표시하는 중요한 요소이다.

minor 번호가 바뀔 때는 메시지 해석 알고리즘을 변경하지 않고도 프로토콜 기능에 대한 변화를 줄 수 있을 때이고, 프로토콜 내의 메시지 형식이 바뀔 때와 같은 큰 변화가 뒤따를 때 major 번호를 바꾼다.

HTTP 메시지의 버전은 HTTP-Version 필드를 통해 표시하며 메시지의 첫 번째 줄에 자리한다. 만약 프로토콜 버전이 표시되지 않으면 수신측에서는 HTTP/0.9 버전의 단순 형식으로 간주한다.

HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT

서버나 브라우저를 구현하고자 할 때 반드시 포함되어야 하는 HTTP 프로토콜은 0.9와 1.0 버전 모두이며, 이 문서 속에서는 둘 다 기술되어 있다.

이 문서에 정의되어 있는 Full-Request 또는 Full-Response 형식의 메시지를 전송하는 응용 프로그램에서는 "HTTP/1.0"이란 HTTP-Version을 나타내어야 한다.

HTTP/1.0 서버는, HTTP/0.9와 HTTP/1.0 요구를 위한 Request-Line 표현 형식을 인식할 수 있어야 하고, HTTP/0.9와 HTTP/1.0 형식으로 되어 있는 유효요구 (valid request)를 이해할 수 있어야 하고, 또한 클라이언트가 사용한 프로토콜 버전과 같은 메시지 형식으로 적절히 응답할 수 있어야 한다.

HTTP/1.0 클라이언트는, HTTP/1.0 응답 형식인 Status-Line의 메시지 형식을 인식할 수 있어야 하고, HTTP/0.9 또는 HTTP/1.0 형식으로 도착된 유효응답 (valid response)을 이해할 수 있어야 한다.

프락시나 게이트웨이 응용 프로그램은 자신의 프로토콜 버전과 다른 요구를 클라이언트로부터 수신했을 때는 이의 처리를 보다 신중하게 하여야 한다. 프로토콜 버전은 송신측 클라이언트의 프로토콜 처리 능력을 나타내는 것이므로 프락시나 게이트웨이는 송신측 버전보다 높은 메시지를 전달하면 절대 안 된다. 만약 프락시나 게이트웨의의 프로토콜 버전보다 높은 버전의 송신측 요구가 도착하면 요구한 프로토콜 버전을 낮추거나 오류를 되돌려 보내어야 한다. 만약 낮은 버전의 송신측 요구가 도착하면 중계해주기 앞서 버전을 높이는 방법도 가능하다. 해당 송신측 요구에 대한 프락시나 게이트웨이의 응답은 위에서 언급한 서버 요구사항을 만족시켜야 한다.

3.2 URI (Uniform Resource Identifiers)

URI는 현재 여러 가지 이름으로 불리우고 쓰이고 있다. 예를 들어, WWW addresses, Universal Document Identifiers, Universal Resource Identifiers 등이며, 최종적으로 URL (Uniform Resource Locators) 와 URN (Uniform Resource Names)의 결합으로 정의되고 있다. 이것은 하나의 대상체에 대해 이름, 위치, 서비스, 프로토콜 등등 여러 가지 요소들을 참조할 수 있게 형식화 시킨 것이다.

3.2.1 일반적 형식

HTTP 프로토콜에 있어서의 URI란 어떤 알려진 URI에 기반하여 사용하기에 따라 절대 형식 또는 상대 형식으로 표현할 수 있는 것이다. 두 가지 요소의 차이는 표현 방법으로 구분할 수 있는데, 절대 URI 형식은 항상 scheme 이름과 뒤따르는 ":"의 표시에 의해 구분된다.

URI = (absoluteURI | relativeURI) ["#" fragment] absoluteURI = scheme ":" *(uchar | reserved) relativeURI = net_path | abs_path | rel_path net_path = "//" net_loc [abs_path] abs_path = "/" rel_path rel_path = [path] [";" params] ["?" query] path = fsegment *("/" segment) fsegment = 1*pchar segment = *pchar params = param *(";" param) param = *(pchar | "/") scheme = 1*(ALPHA | DIGIT | "+" | "-" | ".") net_loc = *(pchar | ";" | "?") query = *(uchar | reserved) fragment = *(uchar | reserved) pchar = uchar | ":" | "@" | "&" | "=" | "+" uchar = unreserved | escape unreserved = ALPHA | DIGIT | safe | extra | national escape = "%" hex hex reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" extra = "!" | "*" | "'" | "(" | ")" | "," safe = "$" | "-" | "_" | "." unsafe = CTL | SP | <"> | "#" | "%" | "<" | ">" national = <any OCTET excluding ALPHA, DIGIT, reserved, extra, safe, and unsafe>

URL 형식과 의미에 관한 내용은 RFC 1738과 RFC 1808을 참조하면 된다. 위에 표시되어 있는 BNF 표현식 가운데 RFC 1738에 정의되어 있지 않은 rational이란 것이 쓰이고 있다. 이것은 rel_path 주소 부분에 쓰이는 unreserved 글자 집합에 한계가 있기 때문이다. HTTP 프락시는 RFC 1738에 정의되지 않은 URI를 가진 요구를 수신할 수도 있다.

3.2.2 HTTP URL 형식

http 표현식은 HTTP 프로토콜을 이용하여 활용할 네트워크 자원을 지시하는 데에 쓰인다.

http_URL = "http:" "//" host [":" port] [abs_path] host = <A legal Internet host domain name or IP address (in dotted- decimal form), as defined by Section 2.1 of RFC 1123> port = *DIGIT

위 규정은 이용하고자 하는 네트워크 자원이 위치하고 있는 곳의 URL 표시를 하기 위한 것이며, port 부분에 아무런 숫자가 없다면 WWW 서비스를 위해 할당되어 있는 80번으로 인식한다.

위에 표시된 사항의 의미는 지정된 자원이 해당 hostabs_path의 장소에 있으며, 이 서버 호스트는 지정된 port 번호에서 TCP 연결을 맺는다는 것이다. 이때 abs_path는 해당 자원에 대한 Request-URI가 되고, 만약 abs_path가 URL에 표시되어 있지 않다면 Request-URI에 사용될 때는 "/" 표시가 반드시 들어가 있어야 한다.

HTTP 프로토콜은 TCP와 같은 수송계층 프로토콜의 종류에 상관없이 쓰일 수 있는 프로토콜이다. 그러나 위와 같은 URL 표시 방식은 TCP에서나 쓰일 수 있는 것이다. 그러므로 다른 종류의 수송계층에 HTTP가 쓰이기 위해서는 그에 맞는 URI 표현 방식을 정의하여야 한다.

3.2.3 Date/Time 형식

HTTP/1.0 응용에서는 세 가지 형식의 일자/시간 표현 방식을 지원한다.

Sun, 06 nov 1994 08:49:30 GMT ; RFC 822, updated by RFC 1123 Sunday, 06-Nov-94 08:49:30 GMT ; RFC 850, obsoleted by RFC 1036 Sun Nov 6 08:49:30 1994 ; ANSI C's asctime() format

첫 번째 형식은 인터넷 표준으로서 쓰이는 것이며 RFC 1123에서 정의된 길이 제한에 따라 표시된다. 두 번째 형식은 RFC 850의 형식을 따르고 있으며 네 자리의 년도를 표시하기는 불가능한 것이다. HTTP/1.0을 지원하는 클라이언트나 서버는 위 세 가지 형식을 모두 인식할 수 있어야 하지만 메시지를 만들 때는 세 번째 형식을 만들어서는 안 된다. 왜냐하면 프락시나 게이트웨이를 통해 non-HTTP 응용 프로그램들이 SMTP 또는 NNTP를 이용하여 데이타를 전달할 때 생성되는 일자/시간을 인식할 수 있어야 하기 때문이다.

모든 HTTP/1.0 일자/시간 사항은 예외없이 반드시 GMT 형식으로 표현되어야 한다. 앞서 두 가지 표현 형식은 GMT로서 표시되어 있으나 세 번째 형식은 생략되어 있다. 하지만 표시되어 있지 않은 asctime 형식일지라도 GMT라고 간주하도록 한다.

이것을 프로토콜 규격의 형식으로 다시 표현하면 아래와 같다.

HTTP-date = rfc1123-date | rfc850-date | asctime-date rfc1123-date = wkday "," SP date1 SP time SP "GMT" rfc850-date = weekday "," SP date2 SP time SP "GMT" asctime-date = wkday SP date3 SP time SP 4DIGIT date1 = 2DIGIT SP month SP 4DIGIT ; e.g., 16 Nov 1995 date2 = 2DIGIT "-" month "-" 2DIGIT ; e.g., 16-Nov-95 date3 = month SP (2DIGIT | (SP 1DIGIT)) ; e.g., Jun 2 time = 2DIGIT ":" 2DIGIT ":" 2DIGIT ; e.g., 21:34:24 wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" weekday = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday" month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"

3.2.4 Character Sets

HTTP 프로토콜 규격서에서는 'character set'이란 용어를 MIME 규격서에서 정의한 것도 똑같이 사용한다. 즉,
character set
일련의 8bit 데이타를 적절한 대응 관계에 있는 일련의 글자로 변환시킬 수 있게끔 한 개 또는 그 이상의 표로서 만들어서 참조하게 하는 수단이다. 그러므로 무조건 변환시켜서는 안 될 것이며, 모든 글자가 character set에 정의되어 있지 않을 수 있고, 특정한 글자를 표현하기 위해 하나 이상의 8bit 데이타열이 존재할 수도 있다.

이 정의에 따르면, US-ASCII와 같은 단순한 변환표로부터 ISO 2022의 경우에서와 같이 복잡한 변환표에 이르기까지 다양한 종류의 character encoding들은 허용한다. 하지만 MIME character set 이름과 관련된 정의는 8bit 데이타로부터 글자로의 변환에 관한 사항을 완전하게 명시하여야 한다. 완전한 변환 관계를 정의하기 위해 다른 수단을 통한 외부 정보를 활용해서는 안 된다.

HTTP character set은 대소문자 구별을 하지 않으며, HTTP 구현시에 권고하는 문자 집합의 종류로서는 아래와 같다.

charset = "US-ASCII" | "ISO-8859-1" | "ISO-8859-2" | "ISO-8859-3" | "ISO-8859-4" | "ISO-8859-5" | "ISO-8859-6" | "ISO-8859-7" | "ISO-8859-8" | "ISO-8859-9" | "ISO-2022-JP" | "ISO-2022-JP-2" | "ISO-2022-KR" | "UNICODE-1-1" | "UNICODE-1-1-UTF-7" | "UNICODE-1-1-UTF-8" | token

HTTP에서는 문자집합의 종류로서 임의의 토큰을 허용하고 있으므로 위에 규정되지 않은 다른 것도 사용할 수 있으나, 이것은 IANA 문자집합 등록표에 등록되어 있는 것이어야 하며, 응용 프로그램에서도 문자집합의 사용을 IANA에 등록되어 있는 것으로 한정해야 한다.

3.2.5 Content Codings

해당 자원에 대해 적용되어 있는 인코딩 변환 방식을 알리기 위해 사용한다. 이것은 실제 데이타의 화일 형식이나 내용을 손상시키지 않고 데이타를 압축하거나 보안을 위해 암호화할 때 주로 쓰일 수 있다. 이 방식으로 인코딩된 데이타가 저장되어 있다가 송수신되어 실제 활용되기 전에는 디코딩이 되어야 한다.

content-coding = "x-gzip" | "x-compress" | token

여기서 gzip 또는 compress는 응용 프로그램에서는 x-gzipx-compress로 각각 동일하게 취급된다. 표시된 모든 content-coding 변수는 대소문자를 가리지 않는다.

3.2.6 Media Types

HTTP 프로토콜에서는 데이타 형식 표현의 개방성과 확장성을 위해 Content-Type 헤더 필드를 두고서 데이타 형식을 표현하고 있다. 데이타 형식은 Content-Type 필드 다음에 표시될 데이타 형식 (media type)은 다음과 같은 표현식에 따른다. Content-Type 필드의 표현식은 Entity 부분에서 다시 설명된다.

media-type = type "/" subtype *( ";" parameter ) type = token subtype = token

파라미터는 type/subtype에 뒤이어 attributevalue의 쌍으로 구성된다.

parameter = attribute "=" value attribute = token value = token | quoted-string

예를 들어 다음과 같이 나타낼 수 있다.

Content-Type: text/plain; charset="iso-8859-1"

여기서 type, subtype, 및 parameter attribute 이름은 대소문자 구분을 하지 않지만, parameter value는 parameter 종류에 따라 대소문자를 구분할 수도 있고 구분하지 않을 수도 있다.

이러한 표현식에 있어 LWS는 type과 subtype 사이에 절대 허용되지 않으며, 또한 attribute와 이의 value 사이에도 허용되지 않는다. 인식할 수 없는 parameter를 가진 media type이 수신되면 클라이언트는 처리할 수 없는 종류의 media type으로서 적용한다.

오래 전의 일부 HTTP 구현 프로그램에서는 media type의 parameter를 인식할 수 없었다. HTTP/1.0 구현 프로그램에서는 메시지 내용이 어떤 종류인지 지정할 필요가 있을 때만 media type의 parameter를 사용해야 한다.

media-type의 value는 IANA에 등록되어 있는 것을 사용하면 된다. 등록되어 있지 않은 것을 사용하는 것은 좋은 방법이 아니다.

3.2.7 Product Tokens

사용하고 있는 응용 프로그램에 대한 정보를 알려주기 위해 사용된다. 빈 공백 표시(whitespace)를 이용하여 해당 응용 프로그램의 주요 부분에 대한 정보를 연이어서 표시할 수도 있다. 그러므로 중요도가 가장 높은 사항을 먼저 표시하고 뒤 이어서 다른 사항들을 표시하도록 한다.

product = token ["/" product-version] product-version = token

이에 의한 예를 들어보면 아래와 같다.

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

또 다른 예로서,

Server: Apache/0.8.4

이러한 것을 볼 수 있다.

이와 같은 프로그램 정보를 표시할 때는 간단하게 핵심 사항만 나타나게 하여야 하며, 제품 선전이나 중요하지 않는 사항을 알린다든지 하는 것은 허용되지 않는다. 그리고 product-version의 자리에는 어떤 종류의 글자가 오더라도 상관이 없으나, 반드시 버전을 나타내어 같은 프로그램의 개량 종류를 구분할 수 있도록 하여야 한다.

4. HTTP Message

4.1 HTTP 메시지 종류

HTTP 프로토콜의 동작을 위해 존재하는 메시지는 클라이언트로부터 서버로 보내는 request 메시지와 반대로 서버에서 클라이언트로 보내는 response 메시지로 구성되고, 이것은 모두 네 가지 종류로 해서 구성되어 있다.

두 가지는 예전의 0.9 버전의 프로토콜에서 쓰이던 것이고 나머지 두 가지는 현재의 1.0 버전 프로토콜에서 쓰이는 것이다. 이에 대한 표현 형식이 아래와 같다.

HTTP-message = Simple-Request ; HTTP/0.9 messages | Simple-Response | Full-Request ; HTTP/1.0 messages | Full-Response

Full-RequestFull-Response는 데이타 송수신을 위해 RFC 822에서 정의하고 있는 메시지 형식을 사용한다. 각 메시지 형식은 선택 가능한 몇 가지 헤더 필드와 실제 데이타 부분인 Entity-Body로 구성되어 있다. Entity-Body는 헤더 부분과의 구분을 한 줄짜리 빈 공백으로서 하고 있다.

브라우저가 서버에게 문서 요청을 할 때, 브라우저가 사용하고 있는 프로토콜 버전에 따라서 Simple-Request 형식이나 Full-Request 형식이나 둘 중 하나를 만들어서 요구하게 된다. 그러면 서버는 브라우저가 요구한 프로토콜 버전에 따라서 이에 대한 응답으로 Simple-ResponseFull-Response 형식의 응답을 전달한다.

이러한 메시지는 응용 프로토콜 레벨에서 만들어지는 것이므로 실제로 인터넷을 통해 전달이 될 때는 추가적인 과정이 더 존재하게 된다. 먼저 브라우저는 문서 요구를 위한 HTTP 요구 메시지를 위에 정의에 따라 만들고, 이것은 TCP/IP 프로토콜을 기반으로 하는 인터넷을 통해 전달되어야 하므로, TCP 프로토콜에서는 위에서 만든 메시지 앞에다 TCP 프로토콜을 위한 헤더를 추가하고, 그 다음 단계인 IP 프로토콜에서 IP 프로토콜을 위한 헤더를 앞 부분에 추가해서 보내게 된다.

IP 프로토콜에서 만들어진 헤더는 인터넷을 여행하는 가운데 중간 경로상의 라우터에서 목적지까지의 경로를 찾기 위해 참조가 되고, TCP 프로토콜에서 만들어진 헤더는 목적지에 도착해서 속에 든 HTTP 메시지에 데이타 손상과 같은 문제가 없이 제대로 도착했는지 확인해보기 위해 쓰이게 된다.

그런 다음에 HTTP 프로토콜이 HTTP 메시지를 해석하고 이에 따라 서버는 적절하게 동작한다. 이렇게 동작한 결과를 HTTP 응답 메시지로 만들고 위에서 설명한 과정을 똑같이 거쳐 최초에 요구한 브라우저로 전달된다.

따라서 HTTP 프로토콜이 어떻게 구성되어 있는지 알고자 한다면 위 네 가지 메시지의 구성 형식을 살펴보면 되는 것이다. 이것이 HTTP 프로토콜의 모든 것이다.

4.1.1 HTTP/0.9 메시지 형식

0.9 버전에서의 HTTP 메시지 형식은 아래와 같이 단순하게 되어 있다. 여기서는 어떤 종류의 헤더 정보도 허용되지 않으며, 단지 요구 방법으로서 GET이란 request method가 쓰이고, 이에 대한 요구 문서의 URI가 표현될 뿐이다.

Simple-Request = "GET" SP Request-URI CRLF Simple-Response = [Entity-Body]

이러한 0.9 버전 HTTP 프로토콜 요구/응답에서 사용할 수 있는 method 는 GET 하나 뿐이다. 그러므로 브라우저는 서버에게 문서를 보내 달라고 하는 요청만 가능하며 서버에게 문서를 올리거나 지우거나 하는 기능은 불가능하다. GET을 통해 문서를 요청하면서 해당하는 문서의 URI 를 지정해야 할 것이며 이것이 Request-URI에 해당한다. 이러한 요청에 따른 응답이 Entity-Body로서 실려오게 된다. 이때 전달되는 문서의 media type이 표시될 수 없기 때문에 Simple-Request 형식의 사용은 지양해야 한다.

4.1.2 HTTP/1.0 메시지 형식

HTTP/1.0 버전에서는 0.9 버전에 비해 보다 다양한 기능들을 제공한다. 이에 따라 메시지 구성 형식은 훨씬 더 복잡한 형태를 띠고 있다.

Full-Request = Request-Line *(General-Header | Request-Header | Entity-Header) CRLF [Entity-Body] Full-Response = Status-Line *(General-Header | Response-Header | Entity-Header) CRLF [Entity-Body]

위에서 Full-Request의 예를 들자면 이와 같은 표현 방식에 의해 다음과 같은 예들이 가능함을 알 수 있다.

Full-Request = Request-Line CRLF Full-Request = Request-Line General-Header CRLF Full-Request = Request-Line General-Header Request-Header CRLF Full-Request = Request-Line General-Header Request-Header Entity-Header CRLF Entity-Body

Full-Response의 경우도 마찬가지로 살펴볼 수 있다.

Full-Response = Status-Line CRLF Full-Response = Status-Line General-Header CRLF Full-Response = Status-Line General-Header Response-Header CRLF Full-Response = Status-Line General-Header Response-Header Entity-Header CRLF Entity-Body

각 경우에서 보듯이 Entity-BodyCRLF 에 의해 공백 줄이 추가되어 구분되고 있다.

4.2 Message Headers

앞서 메시지 필드들에 보면, General-Header, Request-Header, Response-Header, Entity-Header 등과 같이 네 가지 헤더 형식이 있다. 여기에서 공통적으로 사용하는 표현 형식은 RFC 822의 3.1절에서 정의하고 있는 것이다.

이러한 헤더의 순서는 중요하지 않으나 가능하다면 아래에 나열되어 있는 순서처럼, General-Header가 먼저 나오고 이어서 Request-Header 또는 Response-Header가 나오고 그 다음에 Entity-Header 필드가 나오는 것이 좋다. 각 헤더 필드는 이름과 뒤이은 ":", 한 개짜리 빈칸 (sinle space, SP), 그리고 필드의 value로 구성된다. 필드의 이름은 대소문자를 가리지 않는다. 헤더 필드는, 권장하는 것은 아니지만, 적어도 한 개의 SP 또는 HT 표시를 통해 줄 바꾸기 하여 여러 줄로 표시할 수 있다.

HTTP-header = field-name ":" [ field-value ] CRLF field-name = token field-value = *(field-content | LWS) field-content = <the OCTETs making up the field-value and consisting of either *TEXT or combinations of token, tspecials, and quoted-string>

field-value#(values)와 같은 방식에 의해 ","로 구분되는 여러 개 values로서 표현된다면 같은 field-name을 가진 여러 개의 HTTP-header 필드로 표현될 수 있다. 이 경우에는 반드시 여러 개의 헤더 필드를 하나의 "field-name:field-value"의 쌍으로 결합할 수 있어야 한다.

4.2.1 General Header Fields

General Header는 Full-Request 메시지와 Full-Response 메시지에 공통적으로 포함되어 있는 헤더 형식이다. 이것은 전송되고 있는 메시지에 관한 사항을 알리는 것이지, 전송되고 있는 사용자 데이타에 관한 사항을 알리는 것이 아니다.

General-Header = Date | Pragma Date = "Date" ":" HTTP-date Progma = "Pragma" ":" 1#pragma-directive pragma-directive = "no-cache" | extension-pragma extension-pragma = token ["=" word]

필드 이름은 HTTP 프로토콜의 버전 변경과 함께 프로토콜의 확장을 꾀할 때 추가될 수 있다. 그러나 이렇게 확장되는 필드는 general header field가 가진 역할에 적합해야 할 것이다. 인식할 수 없는 헤더 필드는 Entity-Header 필드로서 간주한다.

위의 헤더 형식을 풀어서 다시 살펴보면 아래와 같이 나타내 보일 수 있다.

General-Header = Date | Pragma Date = "Date" ":" HTTP-date HTTP-date = rfc1123-date | rfc850-date | asctime-date rfc1123-date = wkday "," SP date1 SP time SP "GMT" rfc850-date = weekday "," SP date2 SP time SP "GMT" asctime-date = wkday SP date3 SP time SP 4DIGIT date1 = 2DIGIT SP month SP 4DIGIT date2 = 2DIGIT "-" month "-" 2DIGIT date3 = month SP (2DIGIT | (SP 1DIGIT)) time = 2DIGIT ":" 2DIGIT ":" 2DIGIT wkday = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" weekday = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday" month = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec" Pragma = "Pragma" ":" 1#pragma-directive pragma-directive = "no-cache" | extension-pragma extension-pragma = token ["=" word]

4.2.2 Request Header Fields

Request-Header 필드는 Full-Request 메시지에 포함되는 것이며, 요구 사항에 대한 또는 클라이언트 자체에 대한 추가적인 정보를 서버에게 전달할 때 쓰인다.

Request-Header = Authorization | From | If-Modified-Since | Referer | User-Agent

Request-Header의 필드 이름은 HTTP 프로토콜의 버전 변경과 함께 프로토콜의 확장을 꾀할 때 추가될 수 있다. 그러나 이렇게 확장되는 필드는 request header field가 가진 역할에 적합해야 할 것이다. 인식할 수 없는 헤더 필드는 Entity-Header 필드로서 간주한다.

이것을 보다 상세히 풀어서 나타내면 아래와 같다.

Request-Header = Authorization | From | If-Modified-Since | Referer | User-Agent Authorization = "Authorization" ":" credentials credentials = basic-credentials | (auth-scheme #auth-param) basic-credentials = "Basic" SP basic-cookie basic-cookie = <base64 encoding of userid-password, except not limited to 76 char/line> userid-password = [token] ":" *TEXT auth-scheme = token auth-param = token "=" quoted-string quoted-string = (<"> *(qdtext) <">) qdtext = <any CHAR except <"> and CTLs, but including LWS> From = "From" ":" mailbox If-Modified-Since = "If-Modified-Since" ":" HTTP-date Referer = "Referer" ":" (absoluteURI | relativeURI) relativeURI = net_path | abs_path | rel_path net_path = "//" net_loc [abs_path] net_loc = *(pchar | ";" | "?") abs_path = "/" rel_path rel_path = [path] [";" params] ["?" query] User-Agent = "User-Agent" ":" 1*(product | comment) product = token ["/" product-version] product-version = token

4.2.3 Response Header Fields

response header 필드는 서버가 응답 메시지를 보낼 때 Status-Line에다 실을 수 없는 추가적인 정보를 전달하고자 할 때 쓰인다. 서버를 이것을 이용하여 서버 자신에 대한 정보나 Request-URI에서 명시한 자원에 대한 접근 및 이용 방법에 대한 정보를 전달할 수 있다. 다음과 같은 표현식으로 나타낸다.

Response-Header = Location | Server | WWW-Authenticate

Response-Header의 필드 이름은 HTTP 프로토콜의 버전 변경과 함께 프로토콜의 확장을 꾀할 때 추가될 수 있다. 그러나 이렇게 확장되는 필드는 response header field가 가진 역할에 적합해야 할 것이다. 인식할 수 없는 헤더 필드는 Entity-Header 필드로서 간주한다.

이것을 보다 상세히 풀어서 나타내면 아래와 같다.

Response-Header = Location | Server | WWW-Authenticate Location = "Location" ":" absoluteURI Server = "Server" ":" 1*(product | comment) WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge challenge = auth-scheme 1*SP realm *("," auth-param) realm = "realm" "=" realm-value realm-value = quoted-string

4.2.4 Entity Header Fields

Entity-Header 필드는 Entity-Body에 대한 인코딩 방식, 최종 수정 일자, 유효 기간, 문서 길이 등과 같은 외형적 정보(metainformation)를 나타낼 때 쓰이거나, 전달할 entity body 데이타가 없을 때는 요구 메시지에서 지정한 해당 자원에 대한 정보를 알려줄 때 쓰인다.

Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type | Expires | Last-Modified | extension-header extension-header = HTTP-header

extension-header 필드는 프로토콜을 수정하지 않더라도 추가적인 Entity-Header 필드를 정의하도록 쓰일 수 있다. 그러나 수신측에서 이것이 Entity-Header의 의미로서 해석되어서는 안 된다. 인식할 수 없는 헤더 필드는 수신측이 무시하거나 프락시가 다른 곳으로 중계하여야 한다.

이것을 풀어서 보다 상세히 나타내면 아래와 같다.

Entity-Header = Allow | Content-Encoding | Content-Length | Content-Type | Expires | Last-Modified | extension-header Allow = "Allow" ":" 1#method Content-Encoding = "Content-Encoding" ":" content-coding econtent-coding = "x-gzip" | "x-compress" | token Content-Length = "Content-Length" ":" 1*DIGIT Content-Type = "Content-Type" ":" media-type media-type = type "/" subtype *(";" parameter) type = token subtype = token parameter = attribute "=" value attribute = token value = token | quoted-string Expires = "Expires" ":" HTTP-date Last-Modified = "Last-Modified" ":" HTTP-date extension-header = HTTP-header

5. Request

사용자의 요구 사항을 받은 클라이언트가 HTTP 프로토콜에 따라서 서버에게 요구 사항을 전달할 때 정의되어 있는 요구 메시지가 사용된다. 이러한 요구 메시지는 프로토콜의 버전에 따라서 두 가지 종류가 있음을 앞서 4.1절에서 보였으며 Simple-RequestFull-Request가 바로 그것이다.

Full-Request 메시지의 구성 형식을 앞서 4.1.2절에서 살펴보았으며, 이 가운데 General-Header의 형식은 4.3절에서 살펴보았고 Entity-Header는 7장에서 살펴볼 것이다. 여기서는 Full-Request 메시지와 관련해서 나머지 헤더와 형식을 살펴보기로 한다.

요구 메시지의 첫 번째 줄에 원하는 해당 자원에 적용할 이용 방법, 자원의 위치와 같은 정보, 및 사용하고 있는 프로토콜 버전 등이 포함된다. HTTP/0.9 버전의 프로토콜도 지원하기 위해 요구 메시지는 Simple-RequestFull-Request의 두 가지 종류로서 표시된다.

요구 메시지의 형식을 다음과 같이 나타내 보일 수 있다.

Request = Simple-Request | Full-Request Simple-Request = "GET" SP Request-URI CRLF Full-Request = Request-Line *(General-Header | Request-Header | Entity-Header) CRLF [ Entity-Body ]

HTTP/1.0 서버가 Simple-Request를 수신한다면, 응답을 할 때 반드시 HTTP/0.9 형식의 Simple-Response 형식으로 응답하여야 한다. Full-Response를 수신할 수 있는 HTTP/1.0 클라이언트는 절대 Simple-Request를 보내지 않아야 한다.

5.1 Request-Line

요구 메시지에 들어가는 첫 번째 줄의 첫 순서 내용이 Request-Line이며 아래와 같은 구성 형식으로 되어 있다. Request-Line은 자원의 이용 방법을 나타내는 method token, 해당 자원을 가리키는 Request-URI, 프로토콜 버전, 그리고 마지막에 CRLF로서 표시된다. 각각의 파라미터들은 SP에 의해 구분되고 있다.

메시지 정보의 끝을 나타내는 CRLF은 마지막 이외의 장소에는 허용되지 않는다. 다만 사용자 정보 데이타와 같은 Entity 부분은 CRLF에 뒤이어 나타날 수 있다. 따라서 실제 사용자 데이타를 보내기 위해서는 메시지 정보 다음에 공백의 빈줄을 반드시 집어 넣어야 인식할 수 있다.

Request-Line = Method SP Request-URI SP HTTP-Version CRLF

보다 상세하게 풀어서 나타내면 아래와 같다.

Request-Line = Method SP Request-URI SP HTTP-Version CRLF Method = "GET" | "HEAD" | "POST" | extension-method extension-method = token Request-URI = absoluteURI | abs_path absoluteURI = scheme ":" *(uchar | reserved) scheme = 1*(ALPHA | DIGIT | "+" | "-" | ".") uchar = unreserved | escape unreserved = ALPHA | DIGIT | safe | extra | national safe = "$" | "-" | "_" | "." extra = "!" | "*" | "'" | "(" | ")" | "," national = <any OCTET excluding ALPHA, DIGIT, reserved, extra, safe, and unsafe> unsafe = CTL | SP | <"> | "#" | "%" | "<" | ">" escape = "%" HEX HEX HEX = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" abs_path = "/" rel_path rel_path = [path] [";" params] ["?" query] path = fsegment *("/" segment) fsegment = 1*pchar segment = *pchar pchar = uchar | ":" | "@" | "&" | "=" | "+" params = param *(";" param) param = *(pchar | "/") query = *(uchar | reserved) HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT

Simple-RequestFull-Request 속에 있는 Request-Line의 차이점은 HTTP-Version 필드의 존재 유무와 GET 이외의 다른 방법을 지정할 수 있는지 없는지 하는 것이다.

5.1.1 Method

Request-URI로 지정되는 대상체에 대해 어떻게 활용할 것인지 그 이용 방법을 지정한다. 예를 들어 GET이란 method로 지정되어 있으면 Request-URI로 지정되어 있는 데이타 화일을 가지고 오라는 뜻이 되며, POST란 method로 지정되어 있으면 Request-URI로 지정되어 있는 장소에 글을 올릴 수 있다. 현재 세 가지 종류가 정의되어 쓰이고 있으며 다음과 같다. method는 대소문자 가리지 않는다.

GET, HEAD, POST라고 하는 세 가지 method에 대한 설명은 8장에서 이루어질 것이다.

다음과 같은 표시 형식으로 나타낼 수 있다.

Method = "GET" ; 8.1절 참조 | "HEAD" ; 8.2절 참조 | "POST" ; 8.3절 참조 | extension-method extension-method = token

클라이언트가 대상 자원에 대해 요청한 method 요청이 서버에서 처리할 수 없는 것이라면 서버는 501 (not implemented) 상태 정보를 되돌려 준다.

5.1.2 Request-URI

요구 메시지에 있는 method에 의해 지정되는 동작을 어느 장소에 있는 대상에게 적용할 것인지 나타낸다. 이렇게 표시되는 URI는 다양한 정보를 함축하고 있으며 3.2절을 참조하면 된다. 다음과 같은 표시 형식으로 나타낼 수 있다.

Request-URI = absoluteURI | abs_path

absoluteURI 형식은 요구 메시지가 프락시 서버로 전달될 때에만 쓰인다. 프락시는 수신한 요구 메시지를 중계하고 전달받은 응답 메시지를 최초 요구한 클라이언트에게 전달한다. 요구 메시지가 GET 또는 HEAD이고 해당 요구에 대한 이전 응답이 이미 캐시되어 있다면 Expires 제한 조건에 위배되지 않는 한 이미 캐시되어 있는 응답 메시지를 그대로 전달한다. 여기서 Expires는 캐시되어 있는 정보에 대한 유효 기간을 지정한 것이다.

프락시는 수신한 요구 메시지를 다른 프락시로 중계할 수도 있으며, 또는 absoluteURI에서 지정한 서버로 곧바로 중계해줄 수도 있다. 이때 요구 메시지의 루핑(looping)을 방지하기 위해 프락시는 자신의 모든 서버 이름과 IP 주소를 인식하고 있어야 하며, 이때의 서버 이름에는 alias 이름이나 호스트 내부에 설정되어 있는 별명까지도 포함된다.

한 가지 예는 다음과 같다.

GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.0

Request-URI의 가장 일반적인 형태는 프락시 서버가 아닌 호스트 서버에 있는 자원을 지정할 때 쓰이는 것이며, 이 경우에는 URI의 절대 경로 (absolute path) 만이 전달된다. (5.1절의 상세 표현식에서 abs_path 참조.) 예를 들어, 호스트 서버로부터 위에 명시한 문서를 클라이언트가 직접 가져오고자 하는 경우, www.w3.org 호스트에 80번 포트로 TCP 연결을 맺어 다음과 같은 내용을 보낸다.

GET /pub/WWW/TheProject.html HTTP/1.0

위에 이어서 Full-Request의 나머지 부분이 뒤따른다. 여기서 절대 경로는 절대 생략될 수 없다. 따라서 만약에 원래 URI에 아무 것도 지정되어 있지 않다면 Request-URI"/" 이 표시가 들어가야 한다. 예를 들어 다음과 같다.

GET /

다시 말해, 사용자가 브라우저에 http://www.w3.org 와 같은 URL을 지정하여 절대 경로 표시가 되어 있지 않을 때 위와 같은 과정을 거치는 것이다. 만약 http://www.w3.org/ 이와 같은 URL을 지정했을 때는 절대 경로가 "/"로서 이미 표시되어 있으므로 당연히 위와 같은 표현식이 된다. 즉, 결과적으로는 두 가지 경우에 대한 Request-URI 표현식이 똑 같다.

Request-URI가 전송될 때는 인코딩되어 전달된다. 여기서 몇 가지 글자는 RFC 1738에서 정의하고 있는 "%HEX HEX" 인코딩 방식으로 변환될 수 있다. 수신하는 서버는 요구 메시지를 적절히 처리하기 위하여 인코딩되어 있는 Request-URI를 디코딩할 수 있어야 한다.

5.2 Request Header Fields

4.2.2절을 참조하면 된다.

6. Response

서버는 수신한 요구 메시지를 HTTP 프로토콜에 맞게 번역하여 적절한 동작을 수행하고 프로토콜의 응답 메시지 형식에 맞춰 결과를 전달한다. 요구 메시지의 형식을 다음과 같이 나타내 보일 수 있다.

Response = Simple-Response | Full-Response Simple-Response = [Entity-Body] Full-Response = Status-Line *(General-Header | Response-Header | Entity-Header) CRLF [Entity-Body]

이러한 응답 메시지는 프로토콜의 버전에 따라서 두 가지 종류가 있음을 4.1절에서 보였으며 Simple-ResponseFull-Response가 그것이다. Simple-Response는 HTTP/0.9 프로토콜 형식의 요구 메시지에 대한 응답 또는 서버가 HTTP/0.9 프로토콜로 제한적으로 쓰일 때의 응답으로만 사용되어야 한다.

클라이언트가 HTTP/1.0 형식의 Full-Request를 보냈는데 수신한 응답이 Status-Line으로 시작하지 않는다면, 수신한 응답이 Simple-Request라고 간주하고 적절하게 파싱(parsing) 처리를 하도록 한다.

Full-Response의 각 헤더 필드들은 4.2절에서 이미 살펴보았다.

6.1 Status-Line

Full-Response 메시지에 들어가는 첫 번째 줄의 내용이 Status-Line이며 아래와 같은 구성 형식으로 되어 있다. 각각의 파라미터들은 SP에 의해 구분되고 있으며, HTTP 버전이 제일 먼저 나오고 이어서 숫자로 된 상태 코드가 표시되고 이어서 관련된 추가적인 내용 설명이 덧붙여진다. 메시지 정보의 끝을 나타내는 CRLF는 마지막 이외의 장소에는 허용되지 않는다. 다만 사용자 데이타와 같은 Entity 부분은 CRLF에 뒤이어 나타날 수 있다. 따라서 실제 사용자 데이타를 보내기 위해서는 메시지 정보 다음에 공백의 빈줄을 반드시 집어넣어야 인식할 수 있다.

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

보다 상세하게 풀어서 나타내면 아래와 같다.

Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF HTTP-Version = "HTTP/" 1*DIGIT "." 1*DIGIT Status-Code = "200" ; OK | "201" ; Created | "202" ; Accepted | ... | extension-code extension-code = 3DIGIT Reason-Phrase = *<TEXT, excluding CR and LF>

6.1.1 Status-Code

서버가 요구 메시지를 수신하여 처리한 결과를 알려주는 세 자리의 정수로 표현되는 처리 결과 번호이다. Reason-Phrase에는 Status-Code에 대한 짤막한 설명문이 들어갈 수 있다. 클라이언트는 Reason-Phrase를 반드시 점검하거나 화면에 보이게 할 필요는 없다.

첫 번째 자리 숫자는 응답의 분류 기호이며 나머지 두 자리 숫자는 일련번호이다. 현재 첫 번째 자리 숫자에 의해 다섯 가지로 분류되어 쓰이고 있다.

HTTP/1.0에서 정의한 상태 코드와 대응하는 Reason-Phrase 설명문을 아래의 예에서 볼 수 있다. 여기서의 설명문은 단지 권장 사항일 뿐이며, 같은 의미에 있어 다른 글로서 표현해도 된다.

Status-Code = "200" ; OK | "201" ; Created | "202" ; Accepted | "204" ; No Content | "301" ; Moved Permanently | "302" ; Moved Temporarily | "304" ; Not Modified | "400" ; Bad Request | "401" ; Unauthorized | "403" ; Forbidden | "404" ; Not Found | "500" ; Internal Server Error | "501" ; Not Implemented | "502" ; Bad Gateway | "503" ; Service Unavailable | extension-code

6.1.2 Reason-Phrase

위에서 표시한 Status-Code에 대해 상세 설명을 위한 추가적인 정보를 제공하고자 할 때 Reason-Phrase에 포함되어 전달된다. 위 6.1.1을 참조하면 된다.

7. Entity

Full-RequestFull-Response 메시지는 각 메시지 내에 문서나 사용자 데이타와 같은 엔터티 요소를 전송할 수 있다. 이러한 엔터티는 Entity-Header 필드와 Entity-Body 필드로서 구성된다. 7장의 설명에 있어서 클라이언트와 서버는 엔터티 요소를 전송하느냐 수신하느냐에 따라 각각 송신자 또는 수신자가 될 수 있다.

7.1 Entity Header Fields

4.2.4절에 설명되어 있다.

7.2 Entity Body

HTTP 요구 또는 응답 메시지에 포함되어 전달되는 entity body는 Entity-Header 필드에 의해 정의되는 형식과 인코딩 방식으로 구성되어 전달된다. Entity-Body는 다음과 같은 단순한 형식이다. Entity-Body = *OCTET

요구 메시지에 entity body가 존재한다는 것은 요구 메시지 헤더의 Content-Length 필드의 존재를 보고서도 알 수 있다. 즉, entity body를 포함하는 HTTP/1.0 요구 메시지는 반드시 Content-Length 헤더 필드를 포함해야 한다는 뜻이기도 하다.

entity body가 응답 메시지에 포함될지 안 될지는 요구 메시지와 이에 대한 결과 코드에 의해 좌우된다. HEAD method가 지정된 요구 메시지에 대한 모든 응답에는 entity body가 포함되어서는 안 된다. 그리고 1xx(informational), 204(no content), 304(not modified) 응답에도 entity body가 포함되어서는 안 된다. 이외의 다른 모든 응답에는 entity body가 포함되거나 Content-Length 헤더 필드에 '0'의 값이 들어가야 한다.

8. Method 정의

HTTP/1.0 프로토콜에는 요구 메시지의 활용 방법에 대한 표시를 하도록 되어 있는데, 이것이 method라고 하는 것이다. 즉, 지정한 Request-URI에 대해 보내달라고 전송 요청 (GET) 할지, 서버에 전달하고자 (POST) 할지, 해당 문서의 헤드 정보 (HEAD) 만을 전송 요청 할지, 이에 대한 활용 방법을 지정하는 것이다.

위 세 가지 method 종류 이외에 추가할 수도 있지만, 추가적인 기능 구현의 클라이언트와 서버를 위해 같은 역할을 하는 다른 이름의 method를 만들 수는 없다.

8.1 GET

GET method는 Request-URI에서 지정한 어떤 정보이든지 entity body로서 전달해 달라고 요청하는 의미로서 쓰인다. Request-URI가 어떤 실행 프로그램을 명시하는 경우에는 실행 프로그램 자체가 전달되는 것이 아니라 실행된 결과가 응답 메시지의 entity body로서 전달된다.

요구 메시지에 If-Modified-Since 헤더 필드가 포함되어 있다면 GET은 조건부 GET으로도 동작할 수 있다. 이 경우의 GET이 가지는 의미는, 지정된 자원이 If-Modified-Since에 의해 지정된 일자 이후에 수정된 것일 경우에만 전송하라는 것이다. 이 조건을 이용하여 불필요한 데이타 전송을 막을 수 있고 이미 캐시되어 있는 데이타를 사용자에게 전달해줌으로써 네트워크의 활용성을 높일 수 있다.

8.2 HEAD

HEAD method는, 응답 메시지의 Entity-Body에 어떤 내용도 실어 보내서는 안 된다는 점을 제외하고는 GET method와 똑같다. HEAD 요구 메시지에 대한 응답으로 HTTP 헤더에 포함되는 데이타 형태 정보는 (metainformation, 4.2.4 참조) GET 요구에 대한 응답으로 전달되는 정보와 동일해야 한다. 이러한 HEAD method는 Request-URI에 의해 지정되는 자원에 대해 Entity-Body에 실제 내용을 실어서 전달하지 않더라도 자원에 대한 외형 정보 (metainformation) 획득을 위해 사용할 수 있다. 이것을 활용하여 자원에 대한 유효성, 접근성, 최근 수정 정보 등에 대한 검사를 수행할 수 있다.

여기서 조건부 GET과 비슷하게 조건부 HEAD로서 동작하는 요구 메시지는 없다. 따라서 If-Modified-Since 헤더 필드가 HEAD 요구 메시지에 포함된다면 무시하도록 해야 한다.

8.3 POST

POST 요구 메시지는 메시지의 entity body에 포함되어 있는 자원을 Request-Line에 있는 Request-URI에서 지정하는 대로 서버에서 수용해달라고 요청할 때 쓰인다. 즉, POST는 다음과 같은 기능을 수행하기 위한 한 가지 방법으로 설계되었다.

POST method에 의해 수행되는 실제 동작은 서버에 의해 결정되고 통상 Request-URI에 의해 좌우된다. 포스팅되는 대상은, 하나의 화일이 어느 디렉토리에 자리하게 되고 뉴스 글이 포스팅되는 뉴스그룹에 올려지고 레코드가 데이타 베이스가 등록되는 등과 똑같은 방식으로 지정된 URI에 놓이게 된다.

POST는 대상 서버에 하나의 자원으로서 생성될 필요가 없고 추후의 참조를 위해 접근 가능해야 할 필요도 없다. 즉, POST method에 의해 수행되는 동작은 포스팅 되는 entity가 URI에 의해 지정될 수 있는 자원이 아니어도 된다는 것이다. 이 경우의 적절한 응답 결과 코드는 200 (ok) 또는 204 (no content)가 될 것인데, 응답 메시지에 entity가 포함되어 있느냐 있지 않느냐에 따라 구분이 될 것이다.

어떤 자원이 대상 서버에 생성되는 경우라면 응답 결과 코드는 201(created)이 되어야 하고 상태 정보나 생성된 새 자원에 대한 정보를 알려주는 entity가 포함되어 있어야 한다.

HTTP/1.0의 모든 POST 요구 메시지에는 Content-Length가 반드시 있어야 하며, 서버가 이에 대한 정보를 확보하지 못하게 되면 400(bad request) 메시지를 응답해야 한다.

응용 프로그램에서는 POST 요구 메시지에 대한 응답을 캐싱할 필요가 없다. 왜냐하면 서버가 추후의 요구 메시지에 대한 응답으로서 똑같은 응답을 할 것인지 알 수가 없기 때문이다.

9. 상태 코드 정의 (Status Code Definitions)

상태 코드에는 다음과 같은 것들이 존재한다. (6.1.1절 참조)

9.1 Informational 1xx

9.2 Successful 2xx

200 OK
201 Created
202 Accepted
204 No Content

9.3 Redirection 3xx

300 Multiple Choices
301 Moved Permanently
302 Moved Temporarily
304 Not Modified

9.4 Client Error 4xx

400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found

9.5 Server Error 5xx

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable

10. 헤더 필드 정의 (Header Field Definitions)

이 장에서는 HTTP/1.0 프로토콜의 헤더 필드들의 정의에 대한 표현 형식과 정의에 대한 내용을 다룬다.

10.1 Allow

Request-URI에 의해 지정되는 대상체에 대해 적용할 methods들을 나열하고 있다. 이것은 지정된 문서에 대해 적용할 method의 종류들을 수신측에게 알려주기 위해 사용된다. POST method를 사용하는 요구 메시지에는 Allow 필드가 허용되지 않는다. 그러므로 포함되어 있다면 무시하여야 한다.

다음과 같이 구성되어 있다.

Allow = "Allow" ":" 1#method

이의 예를 아래와 같이 보일 수 있다.

Allow: GET, HEAD

10.2 Authorization

브라우저가 서버에게 서비스 요청을 할 때 자신의 신분을 밝히고 인정받는 동작을 위해 사용되는 필드이다. 401 Unauthorized 응답을 수신한 이후라면 반드시 이 필드를 사용할 필요는 없다. Authorization 필드는 대상 자원에 대한 user agent의 인증 정보를 포함하는 credentials 정보로 구성한다.

Authorization = "Authorization" ":" credentials

이것을 보다 상세히 나타내면 다음과 같다.

Authorization = "Authorization" ":" credentials credentials = basic-credentials | (auth-scheme #auth-param) basic-credentials = "Basic" SP basic-cookie basic-cookie = <base64 encoding of userid-password, except not limited to 76 char/line> userid-password = [token] ":" *TEXT auth-scheme = token auth-param = token "=" quoted-string quoted-string = (<"> *(qdtext) <">) qdtext = <any CHAR except <"> and CTLs, but including LWS>

10.3 Content-Encoding

Entity 헤더의 Content-Encoding 필드는 전송 대상이 되는 개체가 지정된 media-type에 대해 어떤 방식으로 변환되어 있는지 나타낸다. (modifier to the media-type) 따라서 수신측의 입장에서 볼 때는 Content-Type 헤더 필드에 지정되어 있는 데이타 형식으로 원상 복구하기 위해 어떤 디코딩 알고리즘을 사용해야 할지 결정하는 역할을 Content-Encoding 필드가 하게 된다. 이것은 주로 실제 데이타에 대한 변질 없이 데이타 압축을 가능하게 하기 위해 사용된다.

Content-Encoding = "Content-Encoding" ":" content-coding

content-coding의 내용은 3.2.5절에서 살펴볼 수 있으며, 이의 예를 아래와 같이 보일 수 있다.

Content-Encoding: x-gzip

결국 Content-EncodingRequest-URI에 의해 지정되는 대상 자원의 데이타 속성을 나타내는 것이다. 그러므로 대상 자원이 인코딩되어 저장되어 있을 때 수신측에서 이것을 활용하기에 앞서 디코딩할 수 있도록 한다.

10.4 Content-Length

Entity 헤더의 Content-Length 필드는 Entity-Body의 크기를 바이트 단위로 표시하여 수신측에게 알려주는 용도로써 쓰인다. 요구 메시지의 method가 GET이라면 전송하는 데이타의 실제 크기란 의미로서 전달되지만, HEAD라면 전송되어야 하는 데이타의 크기가 어느 정도인지 의미하는 것이다. 다음과 같이 구성되어 있다.

Content-Length = "Content-Length" ":" 1*DIGIT

이의 예를 아래와 같이 보일 수 있다.

Content-Length: 3495

응용 프로그램에서는 이 필드의 값을 media-type에 무관하게 Entity-Body의 전송 크기로서 인식하여야 한다. Content-Length는 전송할 entity body를 가진 모든 HTTP 요구 메시지에 있어야 하며, 0 또는 이보다 큰 값이어야 한다. Content-Length 값이 없을 때 응답 메시지의 entity body의 길이를 결정하는 방법은 7.2.2절에 설명되어 있다.

10.5 Content-Type

Entity 헤더의 Content-Type 필드는 수신측에게 전달하는 Entity-Body의 데이타 형식을 표시한다. 요구 메시지의 method가 GET이라면 전송하는 데이타의 형식이란 의미로서 전달되지만, HEAD라면 전송되어야 하는 데이타의 형식이 어떤 것인지 표시하는 의미이다. 다음과 같이 구성되어 있다.

Content-Type = "Content-Type" ":" media-type

이의 예를 아래와 같이 보일 수 있다.

Content-Type: text/html

media-type에 대한 설명은 3.2.6절에 있다.

10.6 Date

메시지가 만들어지는 날짜와 시간을 나타낼 때 쓰이며, RFC 822에서 정의하고 있는 orig-date와 같은 의미이다. 이 필드는 3.2.3절에서 설명하는 것과 같이 HTTP-date로 표현되며 아래와 같다.

Date = "Date" ":" HTTP-date

이의 예는 다음과 같다.

Date: Tue, 15 Nov 1994 08:12:31 GMT

메시지가 사용자 에이전트나 서버와의 직접 연결을 통해 수신되는 것이라면 수신측에서는 이 날짜를 현재 날짜로 간주할 수 있다. HTTP 프로토콜 동작의 첫 시발점의 입장에서 보면, 날짜라고 하는 정보는 캐시되어 있던 정보를 검증하기 위한 중요한 요소이므로 응답하는 서버에서는 항상 Date 헤더를 포함하고 있어야 한다.

10.7 Expires

Entity 헤더의 Expires 필드는 전달하는 데이타를 의미없는 대상으로 간주하는 시기를 표시한다. 다시 말해, 식품의 유효기간 표시와 같이 일정 기간 유효한 대상에 대해 그 시각을 지나서는 유효하지 않다고 지정할 때 사용하는 것이다. 만약 캐시되어 있는 데이타에 대해 이렇게 표시되어 있을 때라면 지정한 시각이 지나고 난 다음에는 캐시되어 있는 데이타를 지워도 되는 것이다.

Expires = "Expires" ":" HTTP-date

이의 예를 아래와 같이 보일 수 있다.

Expires: Thu, 01 Dec 1994 16:00:00 GMT

이렇게 지정된 날짜가 Date 헤더 필드에 의해 지정된 것보다 앞선 날짜거나 같은 날짜라면 수신측에서는 포함된 entity를 절대 캐시해서는 안 된다. 해당 자원이 사용자나 어떤 실행 프로그램에 의해 자주 변경될 가능성이 있는 것이라면 Expires 날짜도 그만큼 반영되어야 한다.

10.8 From

요구 메시지의 From 헤더 필드에는 브라우저를 사용하여 요구 메시지를 보낸 사용자의 E-mail 주소가 들어간다. 이 주소는 RFC 822에 mailbox로 정의되어 있는 것과 같이 동작 시스템이 사용할 수 있는 것이어야 한다. 다음과 같이 구성된다.

From = "From" ":" mailbox

이의 예를 아래와 같이 보일 수가 있다.

From: qkim@pec.etri.re.kr

이러한 헤더 정보를 이용하여 이용자에 대한 정보를 축적할 수 있으며, 부적절하게 서비스 요청을 하는 사용자나 원하지 않는 사용자를 식별하는 수단으로 활용할 수도 있다. 그러나 이것을 사용자 접근 제어의 수단으로서 사용해서는 안 된다.

이 헤더 정보는 서비스 요청한 요구 메시지에 포함되어 있는 method에 대해 책임을 지는 사람이란 의미로서 해석된다. 특히, 로봇 에이전트를 사용하는 경우에 로봇을 수행시키는 사람의 연락 정보로서 반드시 들어가 있어야 한다. 이것을 통해 수신측에서 만약 문제가 발생했다면 경위 설명을 요구할 수 있을 것이다.

여기서 사용하는 E-mail 주소는 요구 메시지를 생성시키는 호스트 주소와는 별개로서 처리되어야 한다. 그래야만 프락시 서버를 통과하는 경우에도 최초 서비스 요청자의 주소가 그대로 전달될 수 있기 때문이고, 그리고 반드시 그리 되어야 한다.

그러나 이 정보는 클라이언트에서 사용자의 동의 하에 전달되어야 한다. 이것은 사용자의 개인 취향 문제일 수도 있고, 사용자가 위치 하는 곳의 보안 정책에 의해서일 수도 있지만, 반드시 사용자가 요구 메시지를 보내기 전에 From 헤더 필드를 함께 보낼 것인지 보내지 않을 것인지 또는 수정할 것이지 결정할 수 있어야 한다.

10.9 If-Modified-Since

요구 메시지의 If-Modiied-Since 헤더 필드는 8.1의 설명에서와 같이 GET method와 함께 조건부 동작으로 활용된다. 즉, 브라우저가 요구하는 문서에 대해 서버는 이 필드에 지정되어 있는 시각 이후에 수정된 화일만 제공해준다. 지정 시각 이후에 변경되지 않아서 해당 문서를 전달하지 않을 경우에는 Entity-Body 없이 304 (not modified) 응답만 보낸다. 다음과 같이 구성되어 있다.

If-Modified-Since = "If-Modified-Since" ":" HTTP-date

이의 예를 아래와 같이 보일 수가 있다.

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

10.10 Last-Modified

Entity 헤더 필드에 들어가는 Last-Modified 필드는 송신측에서 이 문서의 마지막 작업 일자와 시간을 알려주는 용도로 쓰인다. 이의 정확한 의미는 수신측이 이 문서를 어떻게 처리해야 하는가를 알려주는 것이다. 만약 수신측에서 수신하는 문서의 Last-Modified 날짜가 수신측에 똑같이 저장되어 있는 복사본 문서의 날짜 이후 것이라면 수신측은 앞서 저장된 문서를 무효로서 인식하여 삭제하든지 대치하든지 구현상의 문제로서 적절히 처리한다. 다음과 같이 구성되어 있다.

Last-Modified = "Last-Modified" ":" HTTP-date

이의 예를 아래와 같이 보일 수 있다.

Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT

10.11 Location

응답 메시지의 Location 헤더 필드는 Request-URI에 의해 지정되어 있는 대상체의 정확한 위치를 표시한다. Redirection 3xx 상태 코드의 응답을 위해 location 정보는 대상체에 대한 자동 위치 변환을 (automatic redirection) 위해 서버가 결정하는 URL로서 표시되어야 한다. Request-URI에서는 상대적인 경로로 표시될 수 있었으나, 여기서는 절대 경로만 표시되어야 한다.

Location = "Location" ":" absoluteURI

이의 예를 아래와 같이 보일 수 있다.

Location: http://www.w3.org/hypertext/WWW/NewLocation.html

10.12 Pragma

General Header의 Pragma 필드는 요구/응답의 연쇄 동작에 따라 어느 수신측에 적용되는 변수로서 구현에 관련된 것들을 포함하는 데 쓰인다. 모든 Pragma 변수는 프로토콜의 관점에서 선택적인 동작을 지정한다.

아래와 같은 형식으로 쓰인다.

Progma = "Pragma" ":" 1#pragma-directive pragma-directive = "no-cache" | extension-pragma extension-pragma = token ["=" word]

만약 "no-cache" 변수가 요구 메시지에 존재한다면 응용 프로그램에서는 해당 자원이 캐시되어 있을지라도 원래 위치하고 있는 서버로 요구 메시지를 전달해야 한다. 이것은 클라이언트가 보내는 요구에 대해 신뢰할 수 있는 응답을 받고자 할 때 쓰일 수 있으며, 또한 클라이언트에게 문제성 있는 캐시 문서를 재구성할 수 있도록 할 때 쓰일 수 있다.

10.13 Referer

요구 메시지의 Referer 헤더 필드는 서버를 위해 사용되는 것인데, 클라이언트가 요청한 Request-URI 정보를 알게 된 원래 문서의 주소를 나타낼 때 쓰인다. 즉, A라는 문서를 브라우저에서 보고 있을 때 이 문서에 포함된 링크를 이용하여 B 문서를 요청한다고 할 때, B 문서를 지시하는 Request-URI는 A라고 하는 문서에서 알려진 것이므로 B 문서를 요청하는 요구 메시지에 들어가는 Referer는 A가 된다.

이를 통해 서버는 하나의 문서에 대해 링크되어 있는 이전 문서들의 back-links를 구성할 수 있게 되고, URL 정보가 잘못 기재된 문서들을 추척할 수 있게도 된다. 만약 사용자가 직접 입력한 URI의 경우처럼 Referer가 없는 경우라면 절대 Referer를 전달해서는 안 된다.

Referer = "Referer" ":" ( absoluteURI | relativeURI )

이의 예를 아래와 같이 보일 수가 있다.

Referer: http://www.w3.org/hypertext/DataSources/Overview.html

이러한 Referer 정보가 나태내는 링크 정보를 앞서의 From 정보처럼 개인 취향이나 보안 문제 때문에 서버에게 보내지 않고자 할 수도 있다. 그러므로 브라우저에서는 Referer 정보나 From 정보를 보낼 것인지 보내지 않을 것인지 결정할 수 있는 수단을 제공하여야 한다.

10.14 Server

응답 메시지의 Server 헤더 필드는 요구 메시지를 처리하기 위해 서버가 사용하는 프로그램에 대한 정보를 담고 있다. 이 필드는 제품에 관한 여러 가지 사항을 담을 수도 있으며 서버에 대한 정보를 알리는 데에 사용된다. 이렇게 여러 가지 사항이 올 수 있으므로 제일 중요한 요소부터 먼저 나열하도록 한다. 다음과 같이 구성되어 있다.

Server = "Server" ":" 1*( product | comment )

이의 예를 아래와 같이 보일 수 있다.

Server: CERN/3.0 libwww/2.17

만약 이러한 응답 메시지가 프락시 서버를 거치게 된다면 프락시 서버는 자신에 대한 정보를 이 내용에 추가해서 보내서는 안 된다.

그런데 이런 정보를 통해 어느 소프트웨어를 사용하고 있는지 알 수 있고 이를 통해 이미 알려진 보안 취약점을 활용하여 해킹을 할 수 있으므로 서버 구현자들은 이 정보를 보낼 것인지 안 보낼 것인지 선택할 수 있도록 구현하는 것이 좋다.

10.15 User-Agent

요구 메시지의 User-Agent 필드는 사용자가 요구 메시지를 생성시키는 브라우저에 대한 정보를 나타낸다. 이것은 통계적인 목적, 프로토콜 위배에 대한 추적, 특정 브라우저의 한계를 피하기 위한 적절한 응답의 목적으로 브라우저 종류 인식 등과 같은 목적으로 쓰일 수 있다. 이 정보가 반드시 필요한 것은 아닐지라도 user agents는 요구 메시지에 이 정보를 포함하여야 한다. 이 필드에는 여러 개의 제품 명칭이 포함될 수 있으며 중요도에 따라 순서대로 나열하여야 하고 우선 순위가 높은 것을 앞에다 명시하도록 한다. 다음과 같이 구성되어 있다.

User-Agent = "User-Agent" ":" 1*( product | comment )

이의 예를 아래와 같이 보일 수 있다.

User-Agent: CERN-LineMode/2.15 libwww/2.17b3

10.16 WWW-Authenticate

사용자의 요구 메시지에 지정되어 있는 정보가 보안이 필요로 하는 것이라면 서버는 서비스를 제공해주기 위해 사용자의 인증을 요구할 것이다. 그러므로 서버는 WWW-Authenticate 필드를 포함시켜 응답 메시지를 브라우저에게 전달하도록 한다. 이러한 WWW-Authenticate 헤더 필드는 401 (unauthorized) 응답 메시지에는 반드시 포함되어야 하는 것이다. 다음과 같이 구성되어 있다.

WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge

HTTP 프로토콜에서의 사용자 인증 과정은 11장에서 설명되고 있다. 필드가 하나 이상의 challenge를 갖고 있거나 하나 이상의 WWW-Authenticate 헤더 필드가 있다면 user agents는 WWW-Authenticate 필드 값을 파싱할 때 특별한 주의를 기울여야 한다. 왜냐하면 challenge의 내용이 ","로서 구분되는 일련의 인증 파라미터 리스트를 포함할 수 있기 때문이다.

11. 접근 인증 (Access Authentication)

HTTP/1.0 프로토콜에서는 서버가 클라이언트의 요구에 대해 검사하고 (challenge) 클라이언트가 인증 정보를 보내는 단순한 검사/응답 인증 메카니즘을 (challenge-response authentication mechanism) 사용하고 있는데, 다음과 같은 표현식으로 나타낼 수 있다.

WWW-Authenticate = "WWW-Authenticate" ":" 1#challenge challenge = auth-scheme 1*SP realm *("," auth-param) auth-scheme = token realm = "realm" "=" realm-value realm-value = quoted-string auth-param = token "=" quoted-string

401 (unauthorized) 응답 메시지는 user agent의 인증 검사를 위해 서버에 의해 사용되는 것이다. 이러한 응답은 적어도 하나의 challenge를 가진 WWW-Authenticate 헤더 필드를 포함하여야 하며, 이때의 challenge는 요청받은 자원에 대해 적용할 수 있는 것이라야 한다.

realm attribute는 대소문자를 가리지 않으며 challenge를 포함하는 모든 인증 쳬계들에 대해 필요한 것이다. realm attribute에 대한 realm value는 대소문자를 구분하며 접근하고 있는 서버의 root URL과 결합하여 표시되어 보호 범위를 설정한다. 이러한 realm들은 서버에 있는 보호 자원들에 대해 보호 영역의 집합의 형태로 나눌 수 있게 해주며, 각각은 독자적인 인증 체계와 인증 데이타베이스를 가질 수 있다. realm value는 문자열로서 서버에 의해 할당되는 것이다.

user agent가 자기 자신을 서버에게 인증받고자 한다면 요구 메시지와 함께 Authorization 헤더 필드를 포함시켜서 보낸다. 이 필드의 value는 요청하는 자원에 대한 user agent의 인증 정보를 포함하는 credentials로 구성된다. (10.2 참조) user agent가 credentials을 자동적으로 적용할 수 있는 범위는 보호 범위에 의해 결정된다. 이전 요구가 이미 인정되었다면, 인증 체계, 파라미터, 및 사용자 선호도에 의해 결정되는 일정 시간 동안 같은 credentials은 보호 범위 내의 모든 요구에 대해 재사용될 수 있다. 만약 서버가 요구 메시지와 함께 전달된 credentials을 접수하지 않고자 한다면 403 (forbidden) 응답을 보내어야 한다.

프락시 서버는 user agent 인증을 위해 WWW-AuthenticationAuthorization 헤더를 원래 상태 그대로 중계해야 하고, Authorization을 포함하고 있는 요구 메시지에 대한 응답을 절대 캐시해서는 안 된다. HTTP/1.0에서는 클라이언트가 프락시와 인증하는 수단은 제공하지 않는다.

11.1 기본 인증 체계 (Basic Authentication Scheme)

"Basic" 인증 체계는 user agent가 각 보안 영역에 대해 사용자 아이디와 비밀번호로 자신을 증명하는 모델에 기반하고 있다. 서버는 Request-URI에 지정된 영역에 대한 사용자 아이디와 비밀번호를 검사하여 통과될 때만 해당 요구에 대한 인증을 허가한다. 여기서 선택 가능한 인증 파라미터는 없다.

보안 영역 내의 어느 URI에 대해 인증되지 않은 요구를 수신하게 되면 서버는 다음과 같은 challenge를 응답하여야 한다.

WWW-Authenticate: Basic realm="WallyWorld"

여기서 "WallyWorld"Request-URI의 보안 영역을 명시하기 위해 서버가 부여하는 문자열이다.

인증을 받기 위해 클라이언트는 사용자 아이디와 비밀번호를 보내는데 두 개 사이의 구분은 가운데에 ":" 문자를 넣고 based64 인코딩을 하여 credentials에 넣어서 보낸다.

basic-credentials = "Basic" SP basic-cookie basic-cookie = <base64 encoding of userid-password, except not limited to 76 char/line> userid-password = [token] ":" *TEXT

만약 사용자 에이전트가 사용자 아이디로서 "Aladdin" 비밀번호로서 "open sesame"를 넣어서 보내고자 한다면, 클라이언트의 인증 요청으로서 Authorization 헤더 필드를 사용하여 다음과 같이 될 것이다. (10.2절 참조)

Authorization: Basic QWxhZGRpbjpvcGVuIHNLc2FtZQ==

이와 같은 기본 인증 방식은 비보호 인증 방식이며 클라이언트와 서버 사이의 TCP 연결이 공격으로부터 안전하다고 신뢰할만 하다는 전제 하에 활용하는 것이다. 그러므로 이 전제가 성립하지 않으면 이 방식은 공격으로부터 안전하다고 말할 수 없다. 현재의 개방형 네트워크에서는 이 전제가 성립한다고 할 수 없으므로 기본 인증 방식은 적당히 사용되어야 하며, 클라이언트는 서버와의 기본 인증을 위해 이 방식을 구현하여야 한다.

12. 참고자료

[1]
Roy Fielding, "Hypertext Transfer Protocol - HTTP/1.0", RFC 1945, IETF HTTP WG, May 1996.

[2]
W. Richard Stevens, "TCP/IP Illustrated, Volume 1", Addison-Wesley, 1994.


HyperText Transfer Protocol - HTTP/1.1
(Korean Version 1.0)

Abstract:
HTTP는 HyperText Transfer Protocol의 약자이며, 분산환경 및 공동작업 환경에 이용할 하이퍼미디어 정보시스템의 개발을 목적으로 설계된 응용계층의 프로토콜이다. 이것은 약간의 확장을 통해 네임 서버나 분산 객체 관리 시스템과 같은 많을 일들에 활용할 수 있는 객체지향 프로토콜로서 request/response (i.e., stateless) 동작에 기반하고 있다. HTTP 프로토콜의 한 가지 특징은 데이타 표현의 형태 및 협상에 관한 것이며 전송하는 데이타에 독립적으로 시스템을 구성할 수 있게 한다. 이렇게 사용되는 HTTP는 World-Wide Web에서 사용되어 왔으며, 이 문서의 내용은 HTTP/1.0 버전 다음 단계인 HTTP/1.1 버전에 관한 것이다.[1]

Keywords:
HTTP, Protocol, BNF, Message, Header, Request, Response, Entity, Method, Proxy, Cache, Content Negotiation, Access Authentication

Status:
이 문서는 ftp://ftp.ietf.org/internet-drafts/draft-ietf-http-v11-spec-07.ps 문서에 대해 ftp://ds.internic.net/rfc/rfc1945.txt 문서의 비교 관점에서 요약 정리를 한 것이며, 본문 속에 들어있는 대부분의 내용이 빠진채 작성된 것이다. 내용을 대폭 보완한 새로운 문서는 Korean Version 2.0에서 제공될 예정이다. 본 문서인 Korean Version 1.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/http11v1.html 이며, Korean Version 2.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/http11v2.html 이다. WWW에서 사용하는 각종 프로토콜에 대한 문서 정리는 http://pec.etri.re.kr/~qkim/HTTP/에 정리되고 있으며 문서 내용의 변경에 대한 알림글이 있다.

1. 서론

HTTP/0.9로서 표기되던 초기 HTTP 프로토콜은 인터넷을 통해 데이타 그대로 송수신하기 위한 목적으로 만들어진 매우 단순한 프토토콜이다. 그래서 기능의 향상을 위해 HTTP/1.0 프로토콜을 설계하여 메시지를 MIME과 비슷한 형식으로 구성할 수 있게 하고 전송하는 데이타에 대한 외형 정보를 전달하고 요구/응답 체계에 있어서의 표현식을 보강하였다.

그러나 HTTP/1.0에는 계층적 구조의 프락시 서버와 캐싱에 대한 고려가 없고 상시 연결 (persistent connection) 및 가상 호스트에 대한 필요성에 대한 언급도 없다. 더우기 클라이언트와 서버 사이에 각각의 모든 처리 능력에 대한 협상 또는 결정에 대한 어떤 기능도 지원되지 않으므로 프로토콜 버전의 변경과 함께 기능 향상을 도모하게 되었다.

이에 따라 기능 향상되는 HTTP/1.0 프로토콜을 HTTP/1.1로 이름 붙이기로 하였다. HTTP/1.1에서는 향상된 기능을 신뢰성 있게 구현하기 위해 보다 엄밀한 요구사항들을 정의하고 있다.

2. HTTP/1.0 프로토콜의 문제점

HTTP/1.0 프로토콜의 특징은 단순성에 있다. 그래서 연결을 만들고 동작하고 연결을 해제하는 단순한 과정으로 구성되어 있으며, 하나의 URL은 하나의 TCP 연결이 되도록 만들어져 있다.

연결의 설립/동작/해제의 단순 동작이 계속 반복됨으로해서 네트워크의 congestion에 대한 정보를 확보할 수가 없었다. 연결이 계속 지속되어 있다면 정보 축적과 분석을 통해 트래픽의 혼잡을 인식할 수 있는 것이다.

또한 잦은 연결 설립과 동시에 여러 개의 연결을 설립하는 동작을 통해 bandwidth가 낮은 링크에서 congestion 문제의 가능성을 높이고 사용자에게는 불만족스런 성능을 제공해주게 된다.

캐시 모델의 미흡함도 문제이다. 캐싱에 관해 설계한 모델이 초기적인 형태로 구성되었기 때문에 동작상의 오버헤드도 만들고 캐시된 데이타 관리에도 문제를 갖고 있었던 것이다.

이러한 문제들을 해결하고, 추가적인 고려 사항을 반영한 HTTP/1.1 프로토콜을 설계하게 된 것이다.

3. HTTP/1.1 프로토콜의 특징

이 문서에서는 HTTP/1.1의 전체 규격에 대한 상세 소개는 하지 않고, HTTP/1.0 버전과의 비교에 의한 주요 차이점만 살펴보도록 한다. HTTP/1.1에 대한 상세 소개는 다음 단계의 문서 정리 때 마무리하도록 한다.

3.1 용어 정의 (Terminology)

HTTP/1.1에서 사용하고 있는 용어들은 기본적으로 HTTP/1.0에서 사용하고 있는 용어 정의를 그대로 이용하고 있으며, HTTP/1.1 추가 기능을 위한 상당수 새로운 용어 정의가 추가되었다.

HTTP/1.1의 특징 가운데 하나가 content negotiation이라고 하는 것이다. (???절 참조) 이와 관련된 용어 정의가 추가되었으며 representation, content negotiation, variant 등이다.

계층적인 프락시 및 캐시 기능이 HTTP/1.1의 특징이며 이를 위한 cachable, first-hand, explicit expiration time, heuristic expiration time, age, freshness lifetime, fresh, stale, semantically transparent, validator 등의 용어가 추가되었다.

3.2 프로토콜 파라미터

프로토콜 파라미터와 관련해서는 다음과 같은 사항들이 변경되었다.

3.3 HTTP 메시지

메시지 구성 형식을 나타내기 위한 표현식이 HTTP/1.0에 비해 달라졌다. entity-body란 이름이 message-body란 이름으로 바뀌었으나 전체적으로 표현식만 달라졌을 뿐 실제 구성 형식은 HTTP/1.0과 같다. 그러나 각 헤더 에 포함되는 헤더 필드는 다수 추가되어 있으며 HTTP/1.0과는 달리 구성되어 있다.

General Header Field만 하더라도 기존의 Data, Pragma에 더해 Cache-Control, Connection, Transfer-Encoding, Upgrade, Via 등의 필드가 추가되어 있다.

3.4 Request

HTTP/1.0에서의 Request 메시지와 기본 구성 형식은 똑같으나 request-hader의 헤더 필드가 다수 추가되었고, 사용하는 method의 종류도 많이 늘어났다.

method는 HTTP/1.0에서 쓰이던 것들이 다음과 같다.

이러한 method들에 추가하여 HTTP/1.1에는 다음과 같은 것들이 있다.

OPTIONS
Request-URI에 의해 지정되는 자원에 대한 요구/응답의 관계에 있어 통신과 관련된 선택 사항들에 대한 정보를 요청할 때 쓰인다. 이를 통해 클라이언트는 어느 것을 선택할지 결정할 수 있으며 또는 자원과 관련된 필요사항도 결정할 수 있다. 그리고 서버의 수행 능력에 대해서도 알아볼 수 있다. 그러나 자원에 대한 어떤 동작을 수행시키거나 갖고 온다든지 하는 동작은 허용되지 않는다. 해당 자원에 허용되는 접근 방법들을 나열하는 Allow 헤더 필드가 통신 선택 사항의 예가 될 것이다. Content-Type은 예로서 적당하지 않다.

PUT
메시지에 포함되어 있는 데이타를 지정한 Request-URI 장소에 그 이름으로 저장되게 한다. Request-URI 자리에 같은 것이 존재하고 있다면 메시지에 포함되어 있는 데이타 수정된 최근 자원이라고 간주하여야 한다. 만약에 존재하지 않고 있다면 새로운 자원으로서 Request-URI에 있는 URI로 저장되게 되며 브라우저에서는 이 URI로 자원을 이용할 수 있게 된다. 바로 이 점이 POST와의 차이점이다. POST에서는 이 URI로 활용 방법에 따라 이용할 수 없을 가능성도 있다.

DELETE
Request-URI에 지정되어 있는 자원을 서버에서 지울 수 있게 하는 역할을 한다.

TRACE
요구 메시지의 최종 수신처까지의 루프백 검사용으로 쓰인다. 즉, 클라이언트가 보내는 요구 메시지가 거쳐가는 프락시나 게이트웨이의 중간 경로 및 최종 수신 서버까지 이르는 경로를 알아내는 데에 쓰인다. 이와 함께 사용되는 헤더 필드는 Max-Forwards라고 하는 것이며, 중간에 거쳐갈 프락시나 게이트웨이 경로의 최대 숫자를 지정하는 것이다.

request-header의 필드에는 HTTP/1.0의 것이 다음과 같으며,

HTTP/1.1에서는 위 필드에 더해 다음과 같은 것들이 추가되었다.

3.5 Response

HTTP/1.0에서의 Response 메시지와 기본 구성 형식은 똑같으나 response-hader의 헤더 필드가 다수 추가되었고, 상태 코드의 종류도 다수 늘어났다.

response-header의 필드에는 HTTP/1.0의 것이 다음과 같으며,

HTTP/1.1에서는 위 필드에 더해 다음과 같은 것들이 추가되었다.

3.6 Entity

entity-hader의 헤더 필드가 다수 추가되었다. HTTP/1.0의 것이 다음과 같으며,

HTTP/1.1에서는 위 필드에 더해 다음과 같은 것들이 추가되었다.

3.7 Connections

TCP 연결 관점에서 데이타 송수신의 효율성을 높이기 위하여 상시 연결 (persistent connection) 기능을 HTTP/1.0에서 추가하였다. 이에 따라 HTTP/1.1 프로토콜에 기반하는 모든 HTTP 연결은 상시 연결 기능에 의해 서버에 접속하게 된다. 따라서 서버는 수립한 연결에 대해 일단 상시 연결이라고 간주해버린다.

그러므로 연결의 해제를 위한 수단을 제공해야 하는데 이것이 Connection 헤더 필드가 되며 close란 파라미터가 서버로 전달되면 설립된 상시 연결은 해제되게 된다. 반대로 서버가 응답을 하고난 후에 연결을 해제하고자 한다면 클라이언트로 전송되는 응답 메시지에 Connection 헤더 필드를 넣어서 close 파라미터를 전달하면 된다.

이 기능에 따라 클라이언트는 '파이프라인(pipeline)'이라 불리우는 연속적으로 몇 개의 요구 메시지를 각각에 대해 응답을 받지 않은 상태임에도 보낼 수 있게 된다. 이때 서버는 요구 메시지를 수신한 순서대로 응답 메시지를 전달해야 한다.

3.8 Access Authentication

HTTP/1.0 규격에는 기본 인증 체계 (Basic Access Authentication, BAA)에 대한 규정만 있었으나 HTTP/1.1에는 프락시와 사용하는 Proxy-Authentication 필드와 Proxy-Authorization 필드가 추가되어 있으며, 또한 Digest Access Authentication (DAA) 부분도 추가되어 있다.[1] (BAA와 DAA란 용어는 손쉬운 표기를 위해 이 문서에서만 쓰이는 것이므로 다른 문서 속에 혹시 있을지도 모르는 BAA 및 DAA와 혼동하지 않기 바란다.)

HTTP/1.0에서 사용되던 사용자 인증 방식은 사용자 아이디와 비밀 번호가 아무런 암호화 과정없이 네트워크를 통해 서버로 전달되던 것이어서 탈취 및 공격의 가능성이 있었으므로, 인증을 위한 정보를 보다 안전한 방법으로 전달하기 위해 Digest Access Authentication 방식을 사용한다.

DAA 방식도 BAA 방식과 마찬가지로 단순한 challenge-response 메카니즘으로 동작한다. Basic 방식에서와 같이 통신하는 양 쪽에서 둘 다 비밀번호를 공유한다는 점은 같다. 그러나 DAA 방식에서는 nonce value를 사용하고 있으며, 응답 메시지 속에 MD5 checksum 방식에 의해 인코딩된 사용자 아이디, 비밀번호, 주어진 nonce value, HTTP method, request-URI 등이 들어가지만, 비밀번호는 절대 clear text의 형태로 전달되지 않는다. 이 과정에서 서버에게 checksum이나 digest를 생성하는 데 쓰이는 알고리즘을 지정할 수 있게 하는 선택적 헤더가 있다. 여기서는 MD5 알고리즘이 기본적으로 설정되어 있으며 128-bits MD5 digest가 32개의 ASCII 문자로서 표현된다.

따라서 MD5 알고리즘에서 알려진 문제점들이 그대로 DAA 방식에서도 나타난다. 하지만 DAA는 BAA를 대치하기 위해 만들어진 것이며, 서버 측면에서의 비밀번호 시스템이 공통적으로 겪고 있는 문제점이기도 하다. 이 프로토콜은 kerberos 만큼 안전하지 못하고, client-side private-key 방식에 비해서도 안전하지 못하긴 하지만, 없는 것보다는 낫고, 또한 telnet, ftp에서 쓰이는 방식이나 BAA 방식보다는 더 좋은 방법이다.

그러므로 이것이 보안을 위한 완벽한 해결책이 될 수는 없으며, 또한 메시지 속의 실제 데이타는 암호화 되지도 않고 전달된다. DAA를 통해 달성하고자 했던 것은 BAA 방식이 가진 가장 심각한 문제점을 해결하고자 하는 단순한 목적에 있기 때문에 DAA를 통해 완벽한 보안이 이루어진다고 생각해서는 안 된다.

대부분의 다른 인증 프로토콜에서 보더라도 공격에 대한 위험은 프로토콜 자체에 있는 것이 아니라 이것을 사용하는 데 있어서의 보안 정책이나 절차에 의해 좌우된다. Digest Access Authentication을 사용하더라도 이의 보안 강도는 구현 방식에 달려 있게 된다.

이러한 DAA 방식을 위해 WWW-Authenticate 헤더 필드와 Authorization 헤더 필드를 수정하였다. 여기에다 Authentication-info라고 하는 새로운 헤더 필드 하나가 DAA를 위해 추가되었다.[2]

3.9 Content Negotiation

대부분의 응답 메시지에는 요청된 대상 자원이 entity로서 포함되어 있는데 사용자가 인식할 수 있는 정보로 표현하기 위해 적절한 변환 과정을 거칠 수 있다. 이때 사용자는 요청한 요구 메시지의 지정 사항에 가장 '적절한' 형태로 받아보고자 할 것이다.

예를 들어, gzip으로 압축되어 있는 자원을 클라이언트가 갖고 와서 압축을 풀고서 저장하게 할 수도 있고 적절한 viewer로 보여줄 수도 있으며 여러가지 viewer들 가운데 선택하게 할 수도 있다. 여기서 가장 적절하다는 것은 선호도 문제 때문에 모든 사용자들에게 똑같이 적용되는 것은 아니다. 또한 모든 브라우저가 모든 종류의 데이타 형태를 모두 처리할 수 있는 것도 아니다.

HTTP/1.1에서는 한 가지 대상 자원에 대해 몇 가지 형태의 선택 사양을 전달한다. 이 각각의 선택 정보를 'variant'라고 한다. 예를 들어 어떤 문서에 대해 다음과 같이 세 가지 선택 조건을 제시할 수 있다.

  1. HTML, Korean
  2. HTML, English
  3. Postscript, Korean
  4. Postscript, English

content negotiation이란, 해당 문서를 갖고 오고자 할 때 사용자의 선호도 지정 사항과 클라이언트의 수행 능력에 따라서 가장 최상으로 합치되는 조건의 문서를 선택하여 가져와서 사용자에게 보여줄 수 있도록 하는 과정을 말한다.[3]

그러므로 사용자가 바라는 형태로 제공하기 위해 content negotiation이라고 하는 몇 가지 메카니즘을 HTTP/1.1에서는 제공한다. 다음과 같은 메카니즘이 제안되어 있다.[1]

Server-driven Negotiation
이것은 서버에 있는 알고리즘에 의해 여러 가지 선택안들 가운데 최상의 것이 결정되도록 한 것이다. 이의 선택은 서버 응답에 허용되는 것들과 클라이언트의 요구 메시지에 포함되어 있는 특정 지정 사항에 의해 결정되거나, 또는 요구 메시지에 포함되어 있는 다른 정보들을 이용하여 서버가 결정하는 것이다.

이를 위해 클라이언트는 Accept, Accept-Language, Accept-Encoding 등의 헤더 필드를 요구 메시지에 포함시켜서 서버에게 보낸다. 서버를 이들 정보를 보고서 결정하는 것이다.[1]

Agent-driven Negotiation
최상의 선택에 대한 결정을 서버로부터 최초 응답을 받고 난 후에 클라이언트가 하는 방식이다. 응답 메시지의 Alternates 헤더 필드에 있는 정보나 최초 응답의 entity-body 정보를 보고서 클라이언트가 결정한다.[1]

Transparent Nogotiation
이것은 위 두 방식을 결합한 것이다. 협상의 분산이 가능한 잇점을 갖고 있으며 두 방식의 장점들이 결합됨으로서 가장 주목받고 있는 방식이다.[1]

HTTP/1.1 문서와는 별도로 관리되고 있으며, 안정적인 상태로 정리되면 HTTP/1.1 문서에 들어가게 될 것이다.[3]

3.10 Caching in HTTP

HTTP/1.0 규격에서도 HTTP 프로토콜 동작 상의 데이타 캐싱에 대하여 다루고 있다. HTTP/1.1에서는 이 기능이 보다 잘 동작하게 하기 위한 많은 요소들이 추가되었는데, 그 목적은 많은 경우에 있어 데이타 요청을 위한 요구 메시지의 수를 줄이기 위함이고 또 다른 경우들에 있어 서버가 보내는 응답 메시지의 수를 줄이기 위함이다.

요구 메시지의 수를 줄이게 되면 네트워크의 round-trip의 횟수가 줄어드는데 이를 위해 expiration 메카니즘을 사용한다. 만약 응답 메시지의 수가 줄어들게 되면 네트워크의 bandwidth 용량을 보존할 수 있게 되며 이를 위해 validation 메카니즘을 사용한다.

Expiration이란 서버가 요청받은 자원을 보낼 때 명확한 유효기간을 정해서 보내는 동작을 말한다. 이 날자가 지난 자원의 유효성은 보장하지 못하므로 서버로부터 새롭게 받아와야 하며, 유효기간 내의 자원이라면 요구 메시지를 보내지 않더라도 캐시되어 있는 자원을 제공할 수 있게 되는 것이다.

Validation이란 캐시되어 자원에 대한 유효성을 확인하는 것이다. 클라이언트의 요구에 대한 응답으로서 사용할 수 있는 캐시 데이타가 있다면 먼저 서버와 해당 데이타를 사용할 수 있는지 유효성 검사를 해야 한다.

3.11 헤더 필드 정의

앞에서 언급했던 많은 헤더 필드들이 HTTP/1.1에서 추가되었다. 상세한 기능 설명은 다음에 개정될 문서에서 다루도록 하고, 여기서는 주목되는 특징적 필드만 언급하도록 한다.

3.11.1 Host

이렇게 추가된 필드들 가운데 하나의 호스트 컴퓨터에 여러 개의 서버를 구성할 수 있는 Multi-Homed 기능을 프로토콜 차원에서 구현하도록 하는 것이 있다. HTTP/1.0에서는 서버 프로그램의 구현상 가능했던 기능이며 이 경우에 하나의 호스트 컴퓨터에 추가하고자 하는 서버 홈의 갯수만큼 IP 주소를 지정했어야 했다. 따라서 호스트 컴퓨터는 한 대일지라도 할당된 IP 갯수만큼의 서버 홈을 구성할 수 있었다.

그러나 HTTP/1.0에서는 하나의 호스트에 하나의 IP 주소만 가지고도 이런 기능이 가능하도록 되어 있다. 다만 DNS 시스템에 등록되는 여러 개의 이름 주소는 같은 IP 주소로 등록되어야 한다. 즉, 다양한 도메인의 다양한 이름 주소라 할지라도 모두 같은 IP 주소로 등록되어야 한다는 것이다.

이런 기능을 하는 것이 Host라고 하는 헤더 필드이다. 예를 들어,

http://pec.etri.re.kr/~qkim/HTTP/

위와 같은 URL이 요구 메시지에 포함될 때 아래와 같은 형식으로 구성된다.

GET /~qkim/HTTP/ HTTP/1.1 Host: pec.etri.re.kr

그러므로 같은 IP를 사용하는 같은 호스트라 할지라도 포함되어 있는 Host 정보를 통해 어느 홈을 가리키는지 알 수 있게 되는 것이다.

3.11.2 Range

모든 HTTP entities는 HTTP 메시지 내에 일련의 바이트열로서 포함된다. 따라서 이 가운데 일정 부분의 바이트만 요구하고 서비스받는 것은 아주 편리한 기능이다. 이를 위해 원하는 바이트 영역을 표시하여 가져올 수 있게 하며, 추가된 헤더 필드는 Range이다.

3.11.3 Upgrade

General 헤더에 속하는 헤더 필드이다. 클라이언트는 자신이 지원할 수 있는 추가적인 프로토콜이 무엇인지, 만약 서버가 프로토콜 변환을 할 수 있다면 클라이언트는 어떤 프로토콜을 사용하고자 하는지 Upgrade 헤더 필드를 통해 서버에게 알려 줄 수 있다.

만약 서버가 프로토콜 변환을 할 수 있다면, 서버는 반드시 101 (Switching Protocols) 응답 메시지 속에 Upgrade 필드를 반드시 포함시켜야 한다. 이의 형식은 아래와 같다.

Upgrade = "Upgrade" ":" 1#product

이의 예를 들자면 아래와 같다.

Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11

이러한 헤더 필드를 통해 HTTP/1.1 프로토콜에서 개정된 새로운 HTTP 프로토콜로의 변환이나, 또는 다른 종류의 프로토콜로의 변환이 손쉽게 가능하게 된다.

이때 Upgrade 헤더 필드는 클라이언트와 처음 나타나는 중간 프락시나 게이트웨이 사이에서와 같이 중간 연결에만 적용되기 때문에 메시지가 오가는 전체 연결에 대해서 적용하기 위해서는 Upgrade 헤더가 필드가 존재하는 모든 메시지에 대해 Connection 헤더 필드도 존재하여야 한다.

4. To the Future

HTTP/1.1 다음 버전에서 논의될 것들이 거론되고 있는데, 다음과 같은 것들이다.

Hit Count
캐시되어 있는 데이타에 대해 hit ratio를 파악할 수 있게 하여 캐시 관리의 효율성을 높이고자 하는 것이다.

Compressed Protocol
sticky header를 사용하는 것인데, 무엇을 목표로 하는 것인지 아직 파악되지 않았다.(1996. 11. 7. 현재)

Multiplexing
multiplexing 기법을 이용하여 여러 개의 TCP 연결을 만들지 않더라도 해당 HTTP 메시지들을 가져올 수 있도록 하자는 것이다.

PEP
HTTP 프로토콜에 사용자가 직접 설계한 프로토콜을 추가할 수 있게 하는 것이다.

5. Out of Scope of HTTP/1.1:
HTTP State Management Mechanism

[4]

HTTP 프로토콜 상의 상태 관리는 클라이언트와 서버 사이에 오가는 요구 및 응답 메시지에서 오가는 상태 정보를 일관적으로 다루기 위함이다. HTTP는 stateless로서 연속적으로 보내는 요구 메시지들 사이에 아무런 관련성을 부여할 수가 없다. 그러므로 같은 보안 영역 속에 있는 자원들을 연속적으로 요청하고자 한다면 매번 사용자 인증의 과정을 거쳐야 할 것이다. 이것이 많이 활용되고 있음에도 불구하고 HTTP/1.0이나 HTTP/1.1 규격 두 곳 모두에 아직 포함되어 있지 않으며 별도의 드래프트 문서로서 존재한다.

여기서는 동작 개념에 대한 개략만 언급하기로 한다.

5.1 State & Sessions

예를 들자면, 소비자가 상점에 가서 필요한 여러 물건들을 집어드는 동작과 장바구니에 담는 동작은 여러 번의 요구/응답 상황과 완벽하게 일치하며 각각의 물건 선택과 담는 것들은 서로 상관관계가 없다. 하지만 소비자가 필요한 물건을 구입하고자하는 한 가지 목적 하에 움직이고 있는 것이므로 이것이 세션의 의미가 된다. 저녁 반찬거리 구입이 바로 한 가지 세션의 의미인 것이다.

쿠키의 교환에 의해 생성되는 세션은 다음과 같은 특성을 가진다.

  1. 각 세션은 시작과 끝이 존재한다.
  2. 각 세션은 비교적 짧은 시간 동안만 존재한다.
  3. 클라이언트 또는 서버 어느 쪽이라도 세션을 해제할 수 있다.
  4. 세션이란 상태 정보의 교환이란 의미를 함축하고 있다.

아래에 서버와 클라이언트 사이의 상태 정보 교환에 대한 방법에 대해 설명하도록 한다.

5.2 서버의 역할

5.2.1 일반적 동작

서버는 세션을 생성시키는 역할을 한다. 이를 위해 서버는 응답 메시지에 Set-Cookie라고 하는 추가적인 헤더 필드를 보내도록 한다.

클라이언트는 세션을 지속시키자 결정할 경우에 서버를 향해 요구 메시지에 Cookie 헤더 필드를 보내도록 한다. 서버는 이 정보를 무시할 수도 있고 세션의 현재 상태를 결정하기 위해 사용할 수도 있다. 서버는 클라이언트에게 같은 정보 또는 다른 정보를 Set-Cookie 헤더 필드를 통해 보낼 수도 있고, 또흔 전혀 안 보낼 수도 있다. 서버가 세션을 해제하기 위해서는 Max-Age=0란 정보를 Set-Cookie 헤더 필드에 실어서 클라이언트에게 보내면 된다.

이때 서버는 하나의 응답 메시지에 여러 개의 Set-Cookie 헤더 필드를 포함시킬 수도 있다. 그러므로 중간 게이트웨이에서는 이런 여러 개의 헤더 필드를 하나의 필드로 하여 보낼 수 있어야 한다.

Set-Cookie 헤더 필드는 다음과 같이 구성되어 있다.

set-cookie = "Set-Cookie:" cookies cookies = 1#cookie cookie = NAME "=" VALUE *(";" cookie-av) NAME = attr attr = token VALUE = value value = word cookie-av = "Comment" "=" value | "Domain" "=" value | "Max-Age" "=" value | "Path" "=" value | "Secure" | "Version" "=" 1*DIGIT

5.2.2 캐싱 관리

서버는 클라이언트에게 전달한 자원과 Set-Cookie 헤더에 대한 캐싱 문제를 해결하여야 한다. 타인에게 보여서는 안 되는 문서나 다른 사람들과 공유해서는 안 되는 Set-Cookie 정보가 캐시로서 남아있어서는 안 되기 때문이다. 만약 다른 사람들과 공유해도 되는 Set-Cookie 헤더라면 캐시되게 할 수도 있다.

이러한 동작을 위해 서버는 응답 메시지의 헤더에 조건에 따라서 추가적인 헤더 필드를 선택적으로 보내어야 한다. 예를 들어, Set-Cookie를 캐시되지 않도록 하고자 한다면 다음과 같은 헤더 필드를 보내야 한다.

Cache-control: no-cache="set-cookie"

만약 개인적 정보라서 해당 자원을 다른 사람들과 공유하지 않게끔 할려면 다음과 같은 헤더 필드를 보내서 공유 캐시 영역에 캐시되지 않도록 해야 한다.

Cache-control: private

5.3 클라이언트 역할 (User Agent Role)

5.3.1 Set-Cookie 적용

클라이언트에서는 각기 다른 서버로부터 전달되는 Set-Cookie 응답을 통해 상태 정보를 별도로 관리하여야 한다. 그러므로 Set-Cookie 속에 있는 지정 사항들을 적절하게 인식하여 적용하여야 한다.

5.3.2 Cookie 거부

몇 가지 불일치 상황이 발생하면 보안이나 사생활 침해의 문제로 클라이언트는 쿠키를 거부할 수도 있다.

5.3.3 Cookie 관리

클라이언트가 현재 존재하는 쿠키와 같은 이름을 갖고서 이의 Domain이나 Path가 완전히 일치할 때 새로 도착한 쿠키가 기존의 것을 대치하게 된다. 하지만 새로 도착한 Set-Cookie가 Max-Age의 값을 0으로 가질 때 기존의 것이나 현재의 것이나 둘 다 삭제해버려야 한다. 이런 쿠키가 도착하지 않는다면 시스템 자원이 허용하는 한 쿠키들은 축적된다.

그러나 클라이언트가 쿠키를 저장할 수 있는 한계가 있으므로 오래된 쿠키를 지워야 하는데, 이때 least-recently-used 알고리즘을 사용할 수도 있다.

만약 Set-Cookie 헤더에 Comment를 포함하고 있다면, 클라이언트는 이 정보를 사람이 읽을 수 있는 정보의 형태로 쿠키와 함께 저장하여야 한다.

5.3.4 서버로의 쿠키 전달

클라이언트가 전송하는 요구 메시지에 대해 적용할 쿠키를 갖고 있을 때 서버에게 쿠키 요구 헤더를 다음에 따라서 보낼 수가 있다.

여기서 Cookie의 구성 형식은 다음과 같다.

cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value) cookie-value = NAME "=" VALUE [";" path] [";" domain] cookie-sersion = "$Version" "=" value NAME = attr attr = token VALUE = value value = word path = "$Path" "=" value domain = "$Domain" "=" value

6. 참고자료

[1]
Roy Fielding, "Hypertext Transfer Protocol - HTTP/1.1", Internet Draft (Text / PostScript), IETF HTTP WG, August 1996.

[2]
John Franks and others, "An Extension to HTTP: Digest Access Authentication", Internet Draft, IETF HTTP WG, September 1996.

[3]
Koen Holtman and Andrew Mutz, "Transparent Content Negotiation in HTTP", Internet Draft, IETF HTTP WG, September 1996.

[4]
David M. Kristol and Lou Montulli, "HTTP State Management Mechanism", Internet Draft (Text / PostScript), IETF HTTP WG, July 1996.


Protocol Extension Protocol (PEP)
(Korean Version 1.0)

Abstract:
PEP이란 HTTP 클라이언트, 서버, 및 프락시에게 HTTP 프로토콜의 사용자 독자적인 확장을 가능하게 해주는 시스템이다. 지금까지 HTTP 프로그램들은 추가적인 헤더 필드를 사용해서 독자적인 기능에 대한 확장된 HTTP 프로토콜 동작을 가능하게 할 수 있었다. 그러나 이런 방식의 확장에는 동작 범위나 동작 순서 등에 대한 제한이 존재하기 때문에 PEP을 이용하여 프로토콜 동작의 확장이 가능할 뿐만 아니라 확장된 동작에 대한 적용 범위, 동작의 강도, 동작 순서 등을 표현할 수 있게 하고자 하는 것이다.[1]

Keywords:
HTTP, Protocol, Message, Header, Request, Response, Entity, Protocol-Request, Protocol-Info, Protocol-Query

Status:
이 문서는 http://www.w3.org/pub/WWW/TR/WD-http-pep-960820.html 문서에 대해 개념적 요약 정리를 한 것이며, 본문에 들어있는 상당수 내용이 빠진채 작성된 것이다. 내용을 대폭 보완한 새로운 문서는 Korean Version 2.0에서 제공될 예정이다. 본 문서인 Korean Version 1.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/pepv1.html 이며, Korean Version 2.0이 위치하는 곳은 http://pec.etri.re.kr/~qkim/HTTP/pepv2.html 이다. WWW에서 사용하는 각종 프로토콜에 대한 문서 정리는 http://pec.etri.re.kr/~qkim/HTTP/에 정리되고 있으며 문서 내용의 변경에 대한 알림글이 있다.

1. 서론

HTTP 메시지는 추가적인 헤더 필드나 내용 형식의 표현을 통해 확장이 가능하다. 지금까지 이런 방식으로 프로토콜 기능의 개선이 이루어져 왔기도 하다. 그러나 이러한 방식은, 한 쌍의 클라이언트와 서버 사이에서만 이루어질 어떤 기능 확장에서 부터 전체적으로 쓰일 수 있는 기능 확장에 이르기까지 다양한 요구와 필요에 의해 만들어질 수 있는 기능 확장에는 어려움이 있는 방식이다. 이러한 HTTP 프로토콜에 대한 임의적인 기능 확장을 위해서는 다음과 같은 문제점들이 존재한다.

Naming
다른 클라이언트/서버와의 상호 연동성을 보장하기 위해서는 헤더 이름, 인코딩 종류, 응답 코드 등을 임의적으로 선정할 수는 없는 일이다. 항상 국제적인 공동 노력이 수반되어야 할 일이다.

Importance
어떤 확장 헤더를 무시했을 때 이를 알릴 수 있는 방법이 없다. 경고 메시지를 보낼 수도 있고, 오류 메시지를 보낼 수도 있는데, 어떻게 할 것인지?

Scoping
누가 확장된 헤더 기능을 사용할 것인지 범위 지정을 할 수 있는 방법이 없다. 프락시가 할 것인지, 클라이언트 또는 서버가 할 것인지. Connection 헤더 필드가 부분적인 해결책이 될 수는 있으나, 헤더의 중요도를 전달할 방법이 없으므로 근본적인 해결책이 될 수는 없다.

Ordering
확장된 기능들이 있을 때 어떤 순서로 먼저 수행시켜야 할지 알릴 수 있는 방법이 없다. 전체적인 기능 확장을 위해 개개의 확장 기능들에 대한 수행 순서 결정은 매우 중요한 요소일 수 있다.

Initiation
어느 기능에 대해 한 곳에서 다른 곳으로 지령을 내릴 수 있는 방법이 없다. 확장된 어느 기능에 대해 어떤 agent가 다른 agent에게 동작을 시작하게끔 시도할 수 있는 것이다.

Advertising
확장된 기능들에 대한 상세한 관련 사항들을 알려줄 수 있는 방법이 없다.

Inquiring
어떤 확장된 기능의 활용을 요청하기에 앞서 이 기능이 지원되는지에 대해 물어볼 수 있는 수단이 없다. 이것은 관련된 확장 기능들 가운데서의 선택에 있어 매우 중요한 사항이다.

이러한 문제점들에 대한 해결책을 제시하기 위한 시도로서 몇 개의 헤더 이름과 content-type으로서 PEP (Protocol Extension Protocol)의 개념을 제안하게 되었다. 이것을 이용함으로써 HTTP 프로그램들은 알려진 확장 기능들이든 알려지지 않은 확장 기능들이든 적절하게 동작할 수 있으며, 양쪽에 가능한 프로토콜 확장 기능을 선택할 수 있고, 특정한 수행 능력에 대해 상대방에서 물어볼 수도 있게 된다.

이를 위해 다음과 같은 네 가지 헤더 필드를 사용한다.

위에 있는 Protocol 헤더를 이용하여 확장 기능의 이름, 적용 범위, 중요도, 또는 관련한 데이타 헤더들을 나타낼 수 있고, Protocol-Request 헤더 필드를 이용하여 상대방에게 특정 확장 기능을 사용하게 요청할 수 있으며, Protocol-Query 헤더 필드를 이용하여 상대방에게 특정 확장 기능이 지원되는지에 대해 물어볼 수 있고, Protocol-Info 헤더 필드를 이용하여 어떤 사항들이 지원되는지에 대한 정보를 알려줄 수 있게 된다.

2. PEP 모델

HTTP 프로토콜의 동작은 다음의 네 가지 과정에 의해 이루어진다.

+------------+ 전송 [Request] 수신 +------------+ | | -----------------------------> | | | 클라이언트 | | 서버 | | | <----------------------------- | | +------------+ 수신 [Response] 전송 +------------+

  1. HTTP 요구 메시지의 전송
  2. HTTP 요구 메시지의 수신
  3. HTTP 응답 메시지의 전송
  4. HTTP 응답 메시지의 수신

이러한 동작 과정 속에서 클라이언트나 서버 각각은 Protocol이나 Protocol-Request 메시지를 전달하고, Protocol-Info로서 관련 정보를 응답으로 보내고, Protocol-Query를 통해 상대방에게 물어보는 동작을 취하기도 한다.

이러한 프로토콜 확장 동작은 어떤 서버나 어떤 연결에 대해 적용되는 것이 아니라 어떤 자원에 대해 적용되는 것이다. 즉, HTTP 메시지의 Request-URI에 명시되어 있는 자원에 대해 적용하는 사항이다. 이때 확장 기능에 대한 파라미터 협상 동작도 가능하다.

3. PEP의 사용법

3.1 PEP 확장 헤더의 표현식

PEP 프로토콜의 동작에 반드시 들어가야 하는 헤더는 ProtocolProtocol-Request 두 가지이며, 선택적으로 사용 가능한 것이 Protocol-QueryProtocol-Info 두 가지이고, 네 가지 모두 General 헤더에 들어가는 필드들이다. 각각의 표현식은 아래와 같다.

Protocol = "Protocol" ":" 1#bag Protocol-Request = "Protocol-Request" ":" 1#bag Protocol-Query = "Protocol-Query" ":" 1#bag Protocol-Info = "Protocol-Info" ":" 1#bag bag = "{" bagname 1*LWS *bagitem "}" bagname = token | URI bagitem = bag | token | quoted-string word = token | quoted-string token = 1*<any CHAR except CTLs or tspecials> tspecials = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT quoted-string = (<"> *(qdtext) <">) qdtext = <any CHAR except <"> and CTLs but inclung LWS>

여기서 bag은 아래와 같은 몇 가지 변수들을 가진다.

{<protocol-identifier>    {scope 
(origin | conn)}  
                        {str (opt | req | ref)} 
                        {headers *<token>}
                        {params ...} 
                        {for *<uri>}
                        {via <protocol-identifier>}}

protocol-identifier
알려져 있는 프로토콜 확장 URI 또는 IANA 등록 토큰

scope
scopeconn 또는 origin 둘 중의 하나인데, origin이 기본 설정된다. 이것은 어느 agent가 이 헤더를 처리해야 할 것인지 지정한다. conn이라면 중간의 수신측이 담당하게 되게, origin이라면 클라이언트 또는 최종 서버가 담당한다.

str
strengthreq, ref, 그리고 opt 이 세 가지 가운데 하나이며, opt가 기본 설정된다. Protocol 헤더는 reqopt만 허용하고, Protocol-RequestProtocol-Info 헤더는 세 가지 모두 허용하며, Protocol-Query 헤더는 opt만 허용한다.

headers
관련된 메시지 헤더의 목록을 나열하며, 기본 설정은 아무 것도 없는 것이다. 만약 어느 헤더 토큰이 '*'로 끝나면 이것과 일치되는 모든 메시지에 헤더에 대해 적용되어야 한다. 이때 ownership이 애매하게 되지 않도록 하기 위해 각 확장 헤더들은 자신과 관련된 모든 헤더들을 나열하여야 한다.

params
프로토콜 규격에 따라 확장 기능에 대해 설정하는 파라미터들이 나열된다. 기본 설정되는 것은 아무 것도 없는 것이다.

for
Protocol-Request가 접촉하는 relative URIs 또는 absolute URIs이 목록이 들어간다. for에 아무 것도 없을 때에 기본적으로 접촉하게 (binding on) 되는 대상은 request-URI 또는 Content-Location 응답 헤더이다.

via
Protocol-Query 또는 Protocol-Request와 같은 확장에 대해 응답할 때 agent는 via를 이용하여 또 다른 확장을 시도할 수 있다. 이때의 확장은 같은 메시지 내의 다른 부분에서 사용될 수 있다. 이것은 ProtocolProtocol-Info 헤더에만 허용되는 것이다.

3.2 PEP 프로토콜의 협상 내용 예

이상과 같은 것을 통해 PEP을 이용하여 다음과 같은 협상 내용을 전달할 수 있다.

3.3 Protocol-Query

이와 같은 협상 또는 주고 받는 메시지의 과정에서 첫 번째로 일어날 수 있는 것은 상대방이 일단 어떤 확장 기능을 제공하는지 않는지 물어보는 일일 것이다. Protocol-Query 헤더 필드는 어느 한 쪽이 다른 한 쪽에게 어느 특정 프로토콜 확장을 지원하는지 물어볼 수 있게 하고, 이에 대한 응답은 Protocol-Info 응답 헤더 필드로 돌아오게 된다.

query 헤더는 opt로 기본 설정되는 적용 범위만 명시하도록 한다. 왜냐하면 query는 항상 더 이상의 정보를 선택적으로 요청하기 위해 물어보기 때문이다. 하지만, query를 지원하는 것은 선택적인 것이기 때문에 답을 요구할 수도 없고 거절할 수도 없다.

3.3.1 클라이언트: HTTP 요구 메시지의 전송

만약 클라이언트가 어느 프로토콜 확장이 특정 URI 자원에 대해 지원될 것이라고 생각한다면, 해당 URI에 대해서 (for 목록에 아무 것도 없음) 또는 서버 전체에 대해서 ({for /*}) 확장 기능이 지원되는지 확인하기 위해 Protocol-Query 헤더를 요구 메시지에 포함시켜서 보낸다.

이때 클라이언트는 다른 HTTP 메시지에 Protocol-Query 헤더를 첨부하여 보내기 위해 잠시 기다릴 수도 있고, query 헤더 필드를 OPTIONS method를 가진 요구 메시지에 포함시켜서 보낼 수도 있다.

3.3.2 서버: HTTP 요구 메시지의 수신

query를 수신하는 즉시 agent는 확장 기능이 지원되는지 확인을 하고, 지정되어 있는 설정 사항들이 해당 URI에 모두에 대해 수용할 수 있는지 거절해야 할 것인지에 대한 응답을 보내어야 하는데, 최종 결과를 응답으로 보내기 위해 준비한다.

3.3.3 서버: HTTP 응답 메시지의 전송

서버는 응답 메시지를 보낼 뿐만 아니라 응답에 있어서의 자신의 질문(queries)도 함께 보낼 수 있다.

3.3.4 클라이언트: HTTP 응답 메시지의 수신

클라이언트에게 전달되는 응답은 Protocol-Info 헤더의 형태로 되어 있다. 서버가 자신의 queries를 포함시켰을 수도 있으므로 클라이언트는 결과를 보내주어야 하며, query의 적용 범위와 일치하는 URI에 대해 만든 HTTP 요구 메시지 속에 포함시켜 보낸다. 이러한 동작을 통해 부수적인 효과로서 클라이언트는 서버에게 call back을 가능하게 할 수도 있다.

3.4 Protocol-Info

협상 과정에 있어서의 두 번째 단계로서 한 쪽은 주어진 확장 프로토콜에 대해 일방적인 것이든 앞서 query에 대한 응답이든 {요구한다 | 허용한다 | 금지한다}는 것을 밝힐 수 있다. Protocol-Info 헤더는 어느 agent가 다른 agent에게 특정 확장 프로토콜이 지원되는지 안 되는지 알려줄 수 있게 한다. Protocol-InfoProtocol-Query에 대해 반드시 수반되는 헤더 필드이다. 이를 통해 일치되는 모든 URI들에 대해 해당 프로토콜이 필요한지 허용되는지 금지되어 있는지 알려줄 수 있다.

3.4.1 클라이언트: HTTP 요구 메시지의 전송

이것은 클라이언트가 Protocol-Info를 보내는 상황이다.

클라이언트는 앞서 서버의 query 요구에 대해 Protocol-Info를 보낼 수 있고, 또는 알리고자 하는 사항을 일방적으로 실어서 보낼 수도 있다.

3.4.2 서버: HTTP 요구 메시지의 수신

이것은 Protocol-Info 헤더를 가진 요구 메시지를 서버가 수신한 상황이다.

서버는 도착한 Protocol-Info로부터 클라이언트의 수행 능력과 같은 적절한 정보들을 확보해 두어야 한다. 이 정보는 3.5.3절과 3.6.3절에서 중요하게 활용된다.

3.4.3 서버: HTTP 응답 메시지의 전송

클라이언트가 앞서의 요구 메시지에서 요청했다면 서버는 Protocol-Info 헤더 필드를 포함시켜 응답하여야 하고, 또는 서버가 일방적으로 정보를 알릴 수도 있다.

3.4.4 클라이언트: HTTP 응답 메시지의 수신

클라이언트는 서버의 수행 능력과 같은 적절한 정보들을 확보해 두어야 한다. 이 정보는 3.5.1절과 3.6.1절에서 중요하게 쓰인다.

3.5 Protocol-Request

협상 과정에 있어서의 세 번째 단계로서 상대방에게 어떤 확장 프로토콜의 사용을 시작하도록 직접적으로 시킬 수도 있고 금지시키게도 할 수 있다. Protocol-Request은 어느 agent가 다른 agent에게 특정 확장 기능을 시작하게 만들 수 있도록 하고, 그 응답으로 Protocol 받아야 한다.

3.5.1 클라이언트: HTTP 요구 메시지의 전송

클라이언트가 서버에게 어느 특정 확장 기능을 시작하게 하고자 한다면 해당 확장 기능이 동작할 것인지 검사하기 위해 저장되어 있는 Protocol-Info 정보를 살펴본다. Protocol-Request는 원하는 프로토콜을 명시하기 위해 사용되는 것이며 수신측이 선택할 수 있게끔 파라미터 값의 범위를 전달한다.

3.5.2 서버: HTTP 요구 메시지의 수신

서버는 수신한 확장 프로토콜 요구가 적절한지 검사를 해야 한다. 만약 성공적이라면 서버는 명시된 확장 프로토콜을 사용하기 시작해야 한다. 만약 실패라면 Protocol-Request 헤더에 {str ref}를 실어서 클라이언트에게 보낸다. 처음에 수신했던 request 헤더가 {str req} 파라미터를 갖고 있었다면 해당 request 동작이 실패했음을 나타낸다.

3.5.3 서버: HTTP 응답 메시지의 전송

서버는 명시된 프로토콜의 사용을 시작하든지 금지하든지 함으로써 확장 프로토콜에 대한 요구/수용/금지 등의 응답을 보내어야 한다. 이에 따라 서버는 클라이언트에게 어느 URI에 접근할 때 확장 프로토콜을 시행하도록 자신의 요구 메시지를 보낼 수 있다.

3.5.4 클라이언트: HTTP 응답 메시지의 수신

클라이언트는 서버의 각 Protocol-Request를 점검해 보아야 하는데, 만약 유효한 것이라 판단되면 서버 Protocol-Request for 목록과 일치하는 모든 URI에 접근할 때 명시된 확장 프로토콜을 사용할 수 있도록 준비하여야 한다.

3.6 Protocol

협상 과정에 있어 마지막 절차로서 어떤 확장 프로토콜이 곧바로 사용될 수 있다. Protocol은 어느 agent에게 특정 확장 프로토콜이 현재의 메시지에 쓰이고 있는지 알려줄 수 있는 수단을 제공한다. 응답 메시지에서는 이 확장을 계속 사용할 수 있다.

3.6.1 클라이언트: HTTP 요구 메시지의 송신

클라이언트에서는 현재의 요구 메시지에 대해 어느 확장 프로토콜을 적용해야 할지 결정하여야 한다. 적용할 수 있는 각각에 대해 별도의 Protocol-Request로 응답하여야 하고, 이로써 클라이언트는 서버가 해당 request-URI에 이미 사용하고 있는 확장 프로토콜을 계속 사용할 수 있거나, 또는 다른 확장 프로토콜들 시작할 수 있게 할 수 있다. 각 확장 프로토콜이 적용되기 때문에 추가된 헤더들은 Protocol 로부터 순서대로 활용될 수 있게 된다.

3.6.2 서버: HTTP 요구 메시지의 수신

서버는 각 확장 프로토콜에 대해 Protocol 헤더에 나열되어 있는 순서에 따라서 점검해 보아야 한다. 서버가 각 프로토콜을 점검하기 때문에 서버는 잠시 중단하여 HTTP 오류 상태 코드를 보낼 수도 있다.

3.6.3 서버: HTTP 응답 메시지의 송신

서버는 클라이언트가 요청한 프로토콜들 가운데 적절한 것은 선택하여야 한다. 문제가 생기면 오류 상태 코드를 보낸다.

3.6.4 클라이언트: HTTP 응답 메시지의 수신

클라이언트는 각 프로토콜에 대해 Protocol 헤더에 나열되어 있는 순서에 따라서 점검해 보아야 한다. 클라이언트는 각 확장 프로토콜을 점검하기 때문에 여러가지 이유로 해서 실패할 수도 있다. 이때 복구 방법의 하나로서 금지하는 확장 프로토콜을 Protocol-Request 헤더에 실어서 보낼 수 있다. 확장 프로토콜을 통해 생기는 오류를 사용자에게 알려주거나 log로서 저장해야 한다.

4. 참고자료

[1]
Rohit Khare, "HTTP/1.2 Extension Protocol (PEP)", W3C Working Draft 20-Aug-96, W3 Consortium/MIT, August 1996.


HTTP Next Generation

Abstract:
HTTP는 HyperText Transfer Protocol의 약자이며 WWW에서의 하이퍼텍스트 문서의 전송을 위해 쓰이는 프로토콜이란 뜻이다. 그러나 글뜻에서 보이는 HyperText 문서만이 아니라 음성, 화상, 데이타 등과 같이 MIME에 의해 정의되는 모든 문서 형식을 전송할 수 있다. 이러한 가능성은 그만큼 사용자의 복잡 다양한 요구를 수용할 수 있어야 한다는 뜻을 함축하고 있으며, 인터넷에 존재하는 각종 서비스들을 하나로 통합하여 서비스할 수 있다는 뜻도 갖고 있다. 이에 따라 HTTP 프로토콜은 현재 HTTP/1.0의 제한적 서비스 영역을 넘어 보다 확장되고 다양한 사용자의 요구를 충족시킬 수 있도록 개발되고 있다. HTTP Next Generation에서는 프로토콜의 개발 동향을 살펴보고자 하며, 이를 통해 앞으로 가능하게 될 인터넷의 종합적 서비스 도구로서의 WWW을 전망해보고자 한다.

Keywords:
HTTP, Session, TCP, Connection, Authentication, Charging

Status:
이 문서는 HTTP-NG 관련 문서의 내용을 요약 정리한 것이며, 해당 문서들은 밑의 참고 문헌에 정리되어 있다. 이 문서의 내용을 대폭 보완한 새로운 문서의 작성 계획은 없으며, 만약 보완하여 새롭게 작성하게 된다면 아래의 장소에 공지될 것이므로 참조하기 바란다. WWW에서 사용하는 각종 프로토콜에 대한 문서 정리는 http://pec.etri.re.kr/~qkim/HTTP/에 정리되고 있으며 문서 내용의 변경에 대한 알림글이 있다. (1995. 11. 2. Kim, Yong-Woon)

1. 서론

1.1 HTTP 프로토콜의 동작

실제적인 정보시스템에서는 검색, 정보 갱신, 및 주석 등과 같은 간단한 작업보다는 보다 다양한 기능을 필요로 하고 있다. 또한 분산 환경, 공동작업 환경, 하이퍼미디어 정보시스템 등의 상황에서 필요로 하는 속도와 간편성을 제공하기 위한 프로토콜이 필요하게 되었고 이를 목적으로 HTTP 프로토콜이 설계되었다.

HTTP 프로토콜은 요구/응답 (Request/Response) 방식을 이용하여 동작하고 있다. 즉, 원하는 프로토콜 기능(예: GET, DELETE, POST, HEAD, etc.)에 대해 서비스 요구를 하면 데이타 통신을 위한 TCP 연결이 만들어지고 서버가 응답을 보내어 데이타 전송을 끝내면 자동적으로 연결이 끊어지게 되는 것이다.

FTP 프로토콜의 경우 하나의 화일을 송신 또는 수신하고 난 다음에도 그 연결은 끊어지지 않아 또 다른 요구를 할 수 있지만, HTTP 프로토콜의 경우에는 다시 연결을 만들어 요구해야 하는 방식이다.[Simon5]

1.1.1 Requests

HTTP의 Request 형식은 아주 간단하다. 첫 번째 줄 처음에 어떤 기능을 이용하려는지 지정을 한다. 가장 일반적으로 쓰이고 있는 것이 GET 이다. 이것은 브라우저가 서버에게 문서를 보내달라고 요청하는 것이다. 그 다음에는 화일 이름처럼 대상이 되는 것을 지정하고 현재 쓰이고 있는 HTTP 프로토콜의 버전을 지정한다. 이 다음에는 일련의 지정 사항들을 덧붙일 수가 있은데, 예를 들어 브라우저의 종류나 브라우저가 다룰 수 있는 데이타 형식 등이다. 아래와 같은 예를 볼 수 있다.

Request Example
GET  /index.html  HTTP/1.0
Accept: text/plain
Accept: text/html
Accept: */*
User-Agent: Netscape 1.2

1.1.2 Responses

HTTP에서의 응답 형식도 아주 간단하게 구성되어 있다. 서버에서 쓰이고 있는 프로토콜 버전, Request에 대한 실행 결과, 전달해줄 데이타의 형식, 데이타 길이 등과 같은 추가적인 정보가 전달되고, 이러한 헤더 정보의 끝을 나타내는 빈줄이 들어가고, 뒤이어 실제 데이타가 전달된다. 데이타 전달이 끝나면 서버는 연결을 끊는다. 아래와 같은 예를 볼 수 있다.

Response Example
HTTP/1.0 200 OK
Server: MDMA/0.1
MIME-version: 1.0
Content-type: text/html
Last-Modified: Thu Jul 7 00:25:33 1994
Content-Length: 2003
Right here waiting for you...

1.2 HTTP 프로토콜의 문제점

이러한 요구/응답 방식은 나름대로 장단점을 갖고 있다. URL (Uniform Resource Locator)을 이용한 하이퍼링크로 구성되어 있는 HTML 문서에서는 각종 프로토콜과 호스트 이름을 지정하여 문서 요청을 위한 연결을 만들어 데이타를 갖고 올 수 있다. FTP의 경우에서처럼 하나의 호스트에 오래 연결을 맺고서 여러 가지 문서들을 갖고 오는 것이 아니라 하이퍼텍스트 문서에 있는 하이퍼링크를 통해 전혀 다른 호스트에 접속하여 문서를 요청할 수 있기 때문에 연결이 지속적으로 유지되는 방식보다는 요구/응답의 방식으로 동작하는 것이 보다 효율적이게 된다.

하지만 많은 경우에 갖고 오는 데이타는 같은 장소에 있는 것이다. 따라서 같은 호스트에서 여러가지 문서를 갖고 올려고 한다면 각각의 문서마다 별도의 TCP 연결을 만들고 이 과정에서 추가적인 부담이 생기게 된다. FTP의 경우에는 한 번 맺어진 연결을 통해서 여러 번 문서 요청을 하면 되지만 HTTP 프로토콜에서는 문서마다 각각의 연결을 만들어야 하는 추가적인 부담이 발생하는 것이다. 따라서 같은 장소에서 많은 문서를 갖고 올려고 할 때 HTTP 프로토콜은 성능상의 저하를 발생시키고 있는 것이다.

1.3 HTTP Next Generation

이러한 문제점을 해결하고, On-Line 쇼핑과 같은 상업적인 응용들을 염두에 둔 기능들을 보완하여 새로운 프로토콜을 설계하고자 하고 있다. 이것은 두 가지 방식으로 진행되고 있는데 현재의 프로토콜을 보완하는 방법이 하나이고 아예 새로운 프로토콜을 설계해서 기존의 HTTP 프로토콜을 대체하는 방법이 나머지 한 가지이다. HTTP-NG란 명칭은 기존의 HTTP 프로토콜을 대체하는 새로운 프로토콜을 설계하고자 하는 것이다.[Simon1][Simon2]

2. HTTP-NG Activities

2.1 개요

HTTP는 인터넷에서 가장 빠르게 성장하고 있는 프로토콜이다. 구현하기도 손쉬우며 지금 이 순간에도 엄청난 양의 데이타가 이 프로토콜에 의해 전송되고 있다. 이렇게 잘 동작하고 있음에도 HTTP를 대체하는 새로운 프로토콜을 설계하고자 하는 것은 앞서 말한 성능상의 문제와 사용자 확인 및 사용료 징수 등과 같은 수단으로 상업적 응용의 목적을 달성하기 위해서이다.[Simon1]

기존의 프로토콜에다 각종 기능들을 추가하고 개선하여 활용하는 방법도 있으나 필요한 요건들이 프로토콜 동작의 기본 모델과 관련한 것이기 때문에 이를 바꾸지 않고서는 문제를 더 복잡하고 어렵게 만든다. 이에 따라 다른 동작 모델을 사용하여 새로운 프로토콜을 설계하고자 하는 것이다.[Simon2]

2.2 사용자 요구사항

새로운 프로토콜을 개발하고자 할 때 검토할 수 있는 요구사항들은 세 가지 대상에 대한 것으로 나누어볼 수 있다. 즉, 다음과 같다.

서비스 사용자
사용자들은 웹서비스를 이용하면서 문서를 갖고 오는 데 걸리는 시간 없이 즉시 받아보고자 한다.

서비스 제공자
가능한한 많은 사용자를 확보하고 등록된 사용자에게만 접근을 허용하며 이를 통해 상업적인 성공을 추구하고자 한다.

소프트웨어 개발자
구현하기가 쉽고 개발 작업이 편해야 한다.

각 대상들이 갖는 이런 요구사항들을 충족시키는 프로토콜이 개발되어야 한다. 이를 위해 필요한 사항들과 현재의 TCP/IP 프로토콜상의 문제점들을 나열해 보도록 한다.

Simplicity
HTTP-NG는 구현하기가 쉬운 프로토콜이어야 한다.

Performance
전세계에 걸친 네트워크 상에서 데이타 송수신이 효율적이어야 한다.

Asynchronicity
앞서 요청했던 서비스 요구에 상관없이 언제든지 원하는 서비스 요구를 할 수 있어야 한다. 즉, 앞서 요구한 서비스에 의해 현재의 서비스 요구가 제한받아서는 안 된다. 또한 하나의 연결 상에서 동시에 여러 개의 데이타를 수신할 수 있어야 한다.

Security
보안을 위해 암호화 되어 있는 데이타를 전송할 수 있어야 한다. 이를 위해 한 가지 메카니즘만 제공되면 안 된다.

Authentication
사용자에 대한 인증이 가능해야 한다.

Charging
사용량에 비례하는 과금을 할 수 있어야 한다. 이를 위해 한 가지 방법만 제공해서는 안 된다.

Intermediate Servers
캐시와 미러의 기능을 위해 중간 게이트웨이 역할을 할 수 있어야 하며, 서버와 서버 사이의 동작도 가능해야 한다.

Mandatory Displays
저작권 사항이나 저자에 관한 것 처럼 반드시 표시되어야 할 사항에 대해 지원할 수 있어야 한다.

Logging Information
중간 게이트웨이 역할을 하는 서버와 원래 호스트 서버 사이에서 logging information이 관리되어야 한다.

Network Requirements
TCP와 같은 전송 프로토콜에 상관없이 데이타 전송이 가능해야 한다. 다시 말해서 TCP가 아닌 다른 수송계층 프로토콜에도 적용할 수 있어야 한다는 것이다. 그러나 현재의 응용들은 전부 TCP 프로토콜 위에서 이루어지고 있으므로 TCP 상황에서도 잘 동작해야 한다.

TCP and Internet
HTTP 프로토콜은 결국 TCP 프로토콜을 이용할 수밖에 없으므로 HTTP 프로토콜 성능의 상당 부분은 TCP 프로토콜에 의해 영향을 받는다. 따라서 프로토콜의 설계에서는 TCP 프로토콜의 특성을 잘 파악해야 한다.

Connection Setup Costs
TCP 연결을 맺으면서 RTT(Round Trip Time) 만큼의 지연이 생긴다.

Slow Start limits transfer rates during start up.
하나의 데이타 패킷 속에 요구하는 정보를 전부 지정할 수 없다면 몇 개의 데이타 패킷으로 나뉘어져 요구정보가 전달될 것이고 slow start 알고리즘에 의해 추가적인 RTT 지연이 발생하게 된다.

Congestion information is not shared between connections.
브라우저와 서버 사이에 여러 개의 데이타 전송 연결이 만들어져 있을 때 각각의 연결 사이에 아무런 정보 교환이 없기 때문에 전송상의 문제가 생기더라도 대처할 방도가 없다. 이에 따라 성능상의 문제를 더 크게 한다.

2.3 프로토콜 모델

HTTP 프로토콜이 동작하는 방식은 아래 그림 1과 같이, 브라우저의 각 요구들마다 매번 새로운 연결을 만들어서 데이타를 가져오고 있다. 따라서 다섯 가지의 문서 화일을 가져오기 위해서는 다섯 개의 연결을 만들어서 갖고 오게 된다.[Simon2]


[그림 1] HTTP 프로토콜의 동작 모델

이에 비해, HTTP-NG 프로토콜 구조에서는 다른 모델을 사용하고 있다. 다음 그림 2와 같이 각 문서 요구에 대해 별도의 연결을 만들기 보다는 여러 개의 문서 요구에 대해 하나의 연결만 만들도록 한다. 이 하나의 TCP 연결 속에서 '세션(session)'이라고 불리우는 여러 개의 가상적 연결을 만들도록 한다. 이 가운데 하나는 세션 연결에서 제어 정보를 주고 받기 위해 쓰인다. 나머지 세션 연결선에 실제 데이타가 전달된다.


[그림 2] HTTP-NG 프로토콜의 동작 모델

2.4 HTTP-NG 프로토콜의 동작

HTTP-NG에서의 요구/응답은 '메시지' 단위로 처리되며, GET 요구를 통해 문서를 요구하는 경우에 원하는 문서 목록을 지정하여 요구하고, 각각의 문서들은 세션 연결을 통해 동시에 전달된다. 데이타를 수신하고 있는 동안에도 기다릴 필요없이 문서 요청을 할 수 있으며, 하나의 데이타 스트림 속에 여러 개의 문서가 사이사이에 끼어 있을 수 있다. 따라서 중간 게이트웨이 역할을 할 때도 서로 다른 브라우저가 같은 서버에 대해 요구를 할 때 효율적으로 동작할 수 있는 수단이 된다.

HTTP 프로토콜을 통해 송수신되는 데이타는 텍스트 정보 그대로여서 사람들이 이해하기 쉬운 형태이나 다양한 데이타 형식이 복합적으로 쓰일 때는 복잡한 구조로 표현되어야 하고 다루기가 어려워진다.

이에 따라 HTTP-NG에서는 전달되는 문서 정보들을 ASN.1 (Abstract Syntax Notation)과 PER (Packed Encoding Rules) 형식으로 인코딩하여 전달되도록 한다. 이미 이 방식으로 동작하는 효율적인 도구가 있기 때문이다.

2.4.1 Request/Response Ordering

HTTP-NG 메시지는 동작 레벨에 대한 협상 결과에 따라 교환된다.[Simon4]

Synchronous Level
다음 동작이 일어나기 이전에 현재 동작이 완료되어야 하며, 모든 동작은 도착되는 요구의 순서대로 이루어져야 한다.

Out-of-Order Level
서버는 어떤 순서대로 메시지 응답을 해도 가능하다. 그러나 다음 동작이 시작되기 전에 현재 동작은 완료되어야 한다.

Interleaved Level
서버는 어떤 순서대로 메시지 응답을 해도 가능하며, 현재의 응답하는 것이 완료되지 않았더라도 새로운 응답 메시지를 보낼 수 있다.

Predictive Level
interleaved level로 동작하면서도 예상되는 요구에 대해서는 요구가 들어오지 않더라도 미리 응답을 보낼 수 있다.

2.4.2 Initializing the Connection

TCP 연결이 일단 설립되고 나면 세션 연결을 위해 일단 먼저 초기화를 시켜야 한다. 브라우저는 허용 가능한 methods (Method는 브라우저가 서버에게 지정하는 문서 데이타를 어떻게 처리해 달라고 지정하는 것을 말한다. 예를 들어 GET이란 method를 사용한다면 서버가 갖고 있는 문서 데이타를 보내 달라는 뜻이고, DELETE란 method를 사용하면 지정하는 문서를 서버에서 지워달라는 뜻이다. 이처럼 몇 가지 종류의 method를 사용하여 어떤 서버 동작을 명령할 것인지 정의한다. 이런 methods의 종류로는 GET, POST, DELETE, HEAD 등과 같은 것이 있다.)와 동작 레벨을 지정하는 초기화 요구를 보내고, 서버는 허용 가능한 methods와 사용할 동작 레벨을 지정하는 초기화 응답을 한다. 이때 브라우저는 이 응답을 받지 않고서도 서버에게 요구를 보낼 수 있다. 만약 서버가 처리할 수 없는 요구 사항이라면 서버는 오류 응답을 보낸다.

이러한 초기화 요구와 응답은 반드시 연결이 설립되고 최초로 전달되어야 한다. 만약 협상이 가능하다면 초기화 요구를 보내고 나서 즉시 협상 요구를 보낼 수 있다. [Simon4]

2.4.3 Normal Message Exchange

초기화 동작이 끝나고 난 다음에는 실제적인 데이타 송수신을 위한 요구와 응답을 주고 받을 수 있다. 서버는 브라우저가 허용 가능하다고 지정한 것 이외에 다른 어떤 메시지도 보내어서는 안 된다.

데이타를 주고 받는 가운데 브라우저는 언제든지 동작 레벨과 method를 바꾸기 위해 초기화 요구를 다시 할 수 있다. 서버는 새롭게 수신한 초기화 요구에 대해, 이전에 수신한 모든 요구 사항들을 처리하고 난 다음에 초기화 응답을 해야 한다. [Simon4]

2.4.4 Error Responses

오류가 발생하게 되면 오류를 알리는 응답이 전달된다. 오류가 발생한 이유에 대해 미리 지정되어 있는 숫자 번호로 알려주고, 추가적으로 알려줄 수 있는 오류 메시지나 정보도 포함될 수 있다. [Simon4]

2.4.5 Request Cancellation

이미 보냈던 요구 사항은 언제든지 취소가 가능하다. 아직 완료되지 않는 동작에 대한 '취소요구'를 서버가 수신하면 수행하고 있던 작업을 중단한다.

만약 브라우저가 원하지 않았던 데이타를 포함하거나 원하지 않았던 응답 메시지가 도착하면 -- 이미 했던 요구 사항을 취소했지만 응답이 도착했을 경우도 포함하여 -- 수신하게 된다면, 취소요구를 서버에게 보내도록 한다. 이를 통해 보다 나은 예측 알고리즘이 동작할 수 있게끔 한다.

'취소요구'(Cancel Request)와 함께 '대기요구'(Suspend Request)도 가능하다. 이것은 서버가 전송 재개를 요청하거나 브라우저가 대기요구를 취소하기 전까지 데이타 전송을 일시적으로 중단시키고 대기 상태로 두게끔 하는 것이다. [Simon4]

2.4.6 Connection Shutdown

브라우저는 연결을 언제든지 끊을 수 있으며 서버도 언제든지 연결을 끊을 수 있다. 적절하게 '해제요구'(Shutdown Request)를 보내어 해제할 수 있다.[Simon4]

2.5 Negotiation

브라우저가 서버에게 여러 가지 문서 전송을 요구하는 것이 일반적인 경우이지만, 반대로 여러 브라우저에게 경고 메시지를 전달할 때와 같은 경우도 있다. 또는 비용 지불을 누가 담당할 것인지 서버는 여러 상대에 대해 협상을 해야할 경우도 있다. 이와 함께, HTTP-NG는 문서의 종류에 제한을 두고 있지 않고 보안 및 지불 방식의 제한도 두고 있지 않으므로 브라우저와 서버 사이에 어떤 방식을 사용할 것인지 협상이 있어야 한다.

HTTP의 경우에는 브라우저가 허용 가능한 것들을 주루룩 나열하여 서버가 선택하는 방식으로 이루어진다. 이같은 방식에서는 전달하는 요구 데이타 크기가 커지고 그만큼 송수신에 시간이 걸리고 처리 시간을 증가시키는 성능상의 문제점을 일으킨다. 이러한 정보가 브라우저 요구 패킷의 95% 부분을 차지한다.

HTTP-NG에서는 일반적으로 가장 많이 쓰이는 데이타 형식들을 목록으로 만들어 짤막한 비트맵 형식으로 인코딩을 한다. 서버와 브라우저는 이 정보와 함께 자신이 허용 가능한 것들을 지정하는 방식으로 협상의 과정을 거친다. 이를 위해 추가적인 숫자 형식의 파라미터가 추가되어야 한다. security schemes, authentication information, payment mechanisms 등에 대한 협상도 같은 방식으로 이루어진다.[Simon2][Simon4]

2.6 Security

지금까지 제안되어 있는 보안 방식들은 부지기수로 존재하기 때문에 HTTP-NG에서는 적용할 수 있는 여러 가지 보안 요소들을 결합하여 general security framework을 만들고 있다. 여기서 체계적인 선택 사안들을 제시하고 이를 선택함으로써 이용하고자 하는 보안 방식을 손쉽게 선택하게끔 하고 있다. 이를 통해 각 HTTP-NG 메시지마다 다른 보안 방식을 사용할 수도 있다. HTTP-NG에서는 중간 게이트웨이 역할을 하는 서버에서도 이런 보안 방식을 지원하므로 데이타 내용에 대해 손대지 않고 암호화 되어 있는 데이타를 그대로 중계해 줄 수 있도록 하고 있다.[Simon2]

2.7 Charging and Payment

HTTP-NG는 브라우저의 요구에 대한 응답으로 서버가 대금 지불 요청을 할 수 있게끔 하고 있다. 이를 위해 적절한 지불 방식과 사용자 인증 방식 등에 대한 상호간 협상을 하여야 한다. 또한 서버는 가격 정보도 함께 제공하여야 한다.[Simon2]

2.8 Mandatory Display & Copyright Control

브라우저가 요구한 정보에 대해 사용자에게 보여줄 때 저작권 사항과 같이 자동적으로 보여주게끔 하기 위해 추가적인 기능을 이용할 수도 있다.[Simon2]

2.9 Transition from HTTP 1.0

HTTP 1.0 프로토콜에서 HTTP-NG 프로토콜로 옮겨가기 위한 방법으로 두 가지를 활용할 수 있다. 한 가지 방법은 HTTP 1.0과 HTTP-NG를 함께 구현하여 각각의 브라우저 요구에 따라 응하는 Dual Stack approach이다. 다른 한 가지 방법은 Proxy Server로서 활용하는 방법이다.[Simon2]

두 가지를 함께 구현하는 Dual Stack 방식에서는 HTTP-NG만 사용하는 만큼의 성능 향상을 기대할 수 없다. 그러나 Proxy Server 방식에서는 캐시되는 정보가 항상 HTTP-NG 프로토콜을 이용하므로 상당한 정도의 성능 향상을 기대할 수 있다. 또한 Proxy Server는 같은 연결 속에서 여러 개의 HTTP 1.0 연결을 동시에 처리할 수 있다.

3. Session Control Protocol (SCP)의 동작

3.1 목적

FTP, GOPHER, HTTP 등과 같이 인터넷에서 폭넓게 사용되고 있는 응용들은 문서를 요청할 때마다 매번 새로운 연결을 만들어서 가져온다. 통상 브라우저는 몇 개의 문서를 같은 서버에서 가져오므로 이러한 문서 송수신 방식은 비효율적인 것임에 틀림없다. 그래서 하나의 TCP 연결에다 여러 개의 conversations, 즉 session 연결을 두어 보다 효율적으로 데이타 송수신 처리를 하고자 한다.[Simon3]

3.2 설계 목표

Unconfirmed service without negotiation
SCP는 session의 설립 절차와 함께 사용자 데이타를 전송할 수 있으며, 수신측에서는 session 설립에 대한 확인을 해주지는 않으며 문제가 발생하면 session 연결을 거절한다. 이 방식이 프로토콜 설계를 간단하게 만들고 session 연결이 설립되었다는 확인을 보내는 데에 들어가는 추가적인 시간 지연을 없앨 수 있게끔 한다.

Low Overhead
여러 개의 요구에 대해 각각의 session 연결을 만들고 하나의 TCP 연결로 요구 사항을 전달할 때, 각각의 session 연결에 대해 8 바이트의 추가적인 부담이 된다. 그러나 데이타 패킷당 한 번씩 추가되는 것이 아니라 데이타 세그먼트당 추가되므로 비교적 적은 부담이 된다.

Simple Design
구현하기가 쉽게끔 간단하게 설계되어야 한다.

3.3 프로토콜 구성

SCP에서 사용하는 헤더의 구성 형식을 보면 다음 그림과 같다.


[그림 3] 헤더 구성 형식

3.4 프로토콜 동작

Session ID 할당
여러 개로 만들어질 수 있는 세션에 대해 1024보다 작은 값으로 session ID가 각각 할당된다. 브라우저가 할당하는 값은 짝수로 구성되고 서버가 할당하는 값은 홀수로 되어 있다.

Session 설립
데이타 채널에 보내진 최초 메시지에 SYN 비트가 1로 표시되면서 세션이 설립된다.

Graceful Release
FIN 비트가 지정되어 있는 메시지를 보냄으로써 세션은 해제된다. 양 끝단은 각각 독립적으로 연결을 해제할 수 있다.

Disgraceful Release
세션은 RST 비트가 지정되어 메시지가 전달됨으로써 해제될 수도 있다. 해제되기 직전에 미치 전달되지 못한 데이타가 있다면 무시해 버린다.

메시지 경계
메시지 사이의 경계는 PUSH 비트로 나타낸다.

4. HTTP Development Issues

이미 앞서 열거했던 HTTP 프로토콜의 문제점들이 파악되어 있기 때문에 현재 프로토콜을 개선하고자 하는 논의가 이루어지고 있으며, 다양한 응용들과 사용자들의 요구사항을 반영하고자 하는 논의가 이루어지고 있다. 여기에서는 현재 HTTP 프로토콜 개발 작업에서 논의되고 있는 주요한 사항들에 대해 살펴보고자 한다. 이러한 사항들은 아직 논의 단계에 있기 때문에 향후의 HTTP 상위 버전에 반영될지는 알 수가 없다.[Archive]

Session Extension
앞서 말한 HTTP 프로토콜의 가장 대표적 문제점이 같은 서버에서 여러 문서를 가져올 때 매번 새로운 연결을 맺어서 가져온다는 것이다. 이에 대한 대처 방안이 하나의 TCP 연결 위에 여러 개의 세션연결을 두어서 해결하는 것이었다. HTTP 개발 작업에도 이 개념이 도입되어 논의되고 있다.

State Information
이것은 위에 있는 Session 연결의 개념과 관련되어 있다. 현재의 HTTP 프로토콜은 앞서 보냈던 요구 사항에 대한 아무런 정보도 갖고 있지 않다. 그래서 상호 독립성은 유지가 되나 상호 관련이 있는 요구 사항들일 경우에는 같은 정보를 매번 전달해야 하는 비효율성이 등장하게 된다. 이에 따라 상호 관련이 있는 요구 사항을 보낼 때는 이미 앞서 보낸 요구에 대한 정보를 갖고 있다가 뒤이어 도착하는 요구 사항에도 적용할 수 있게 한다. 이러한 개념은 위에 있는 세션연결과 관련시켜 적용할 수 있다.

KeepAlive or Persistent Connection
위 문제를 해결하기 위한 또 다른 방안이 바로 이것이다. KeepAlive 개념은 이미 NCSA HTTPD에 구현되어 쓰이고 있다. 다만 브라우저에 이것이 구현되어 있어야만 제대로 동작한다. 이것은 하나의 연결에 대해 여러 개의 요구를 보내도록 하고 있으며, PC 윈도우즈용 NCSA Mosaic에 구현하여 확인해본 결과 30 퍼센트 정도의 성능 향상을 보았다고 한다. 이를 위해 httpd.conf 화일 속에 세 가지의 변수를 서버에서 지정해주어야 한다. 다음과 같다. [KeepAlive]
     KeepAlive on | off
     KeepAliveTimeout N
     MaxKeepAliveRequests N
     
Color Content Negotiation
사용자가 사용하는 화면은 흑백만 지원할 수도 있고 칼라를 지원할 수도 있으며, 칼라의 경우 다양한 색 해상도가 선택될 수 있다. 이러한 경우를 위해 Accept-Color, MIME 형식에서의 파라미터, Accept-Parameter 등 갖가지 방법에 대한 논의가 이루어지고 있다.

Proxy Naming
현재의 proxy server는 중간 게이트웨이로서 firewall을 통과할 때, 또는 보다 빠른 응답을 위한 캐시로서 쓰거나 대역폭을 절약할 목적으로 쓰이고 있는데, 이것은 client 측면의 proxy로서 동작하는 것이다. 왜냐하면 사용자 브라우저에서는 이 proxy 서버의 존재를 알고 있어야 하기 때문이다. 이러한 proxy 서버 개념을 확장하여 client proxy와 server proxy의 개념 도입을 위한 토론이 이루어지고 있다. server proxy는 사용자 브라우저에서는 존재를 알 수가 없다.

HTTP/1.1
현재 W3C의 HTTP Working Group에서 closed로 논의가 이루어지고 있다. 간혹 open mail discussions으로 논의의 일부가 전달되기도 하나 상세히 파악할 수 없다.

5. 결론

현재 쓰이고 있는 HTTP 프로토콜은 성능상의 문제점을 많이 갖고 있으며 지금처럼 확대되고 있는 여러 상업적 응용들을 적절히 지원해줄 수 있을 만큼의 기능을 제공하지 있지 못하다. 이에 따라 성능을 개선하고 추가적인 기능들을 제공하기 위한 HTTP 프로토콜 개발이 한창 이루어지고 있으며, 두 가지 큰 흐름이 기존 프로토콜의 개선 및 확장의 방법과 아예 기존 프로토콜을 대체하는 새로운 프로토콜의 설계가 그것이다. 여기서는 두 가지 방향 모두를 개략적으로 살펴 보았으며, 점차 HTTP-NG 개발 작업은 중단되고 HTTP-NG의 여러 가지 개념들이 HTTP 상위 버전의 개발에 적용되면서 추가적으로 필요한 기능들이 확장되는 방식으로 개발될 것으로 추측한다.

6. 참고문헌(References)

[Simon1]
Progress on HTTP-NG, Simon Spero, UNC Sunsite/EIT
URL: http://www.w3.org/hypertext/WWW/Protocols/HTTP-NG/http-ng-status.html

[Simon2]
HTTP-NG Architectural Overview, Simon Spero, UNC Sunsite/EIT
URL: http://www.w3.org/hypertext/WWW/Protocols/HTTP-NG/http-ng-arch.html

[Simon3]
Session Control Protocol (SCP), Simon Spero, UNC Sunsite/EIT
URL: http://www.w3.org/hypertext/WWW/Protocols/HTTP-NG/http-ng-scp.html

[Simon4]
Next Generation Hypertext Transport Protocol, Internet Draft, Simon Spero

[Simon5]
Analysis of HTTP Performance Problems, Simon Spero, UNC Sunsite/EIT
URL: http://sunsite.unc.edu/mdma-release/http-prob.html

[KeepAlive]
HTTP 1.0 KeepAlive, NCSA
URL: http://hoohoo.ncsa.uiuc.edu/beta-1.5/howto/KeepAlive.html

[Archive]
HTTP Working Group's E-mail Discussions