반응형
하드디스크 또는 파티션을 두 개 이상 사용하시는 분들이라면 대부분 음악파일이나 그림파일과 같은 파일을 다른 파티션에 저장하시는 분들이 많을것 같은데요..
이런분들은 유용하게 사용할 수 있을것 같네요.

1. 먼저, 시작 > 실행 > regedit 를 입력해서 레지스트리 편집창으로 들어가세요~~
2. 다음 경로를 찾아 이동합니다.
     HKEY_CURRENT_USER \ Software \ Microsoft \
          Windows \ CurrentVersion \ Explorer \ User Shell Folders
레지스트리 편집기 화면

레지스트리 편집기 화면


3. 음악은 My Music, 내 그림은 My Pictures 를 더블클릭 후
    원하는 경로로 수정하시면 됩니다.

이 밖에도 많은 항목이 있는데요.
아직 하나하나 어떤것들인지 확인해 보지 않았지만, 경로나 이름을 보면 대충 연결이 되는것 같네요.

그리고, My Music의 항목이 없는분들도 있습니다. 빈 공백에서 마우스 오른쪽 버튼을 클릭 후
새로만들기 > 확장가능한 문자열 값 을 선택하여 추가하시면 됩니다.
새로만들기 선택화면

새로만들기 선택화면

반응형

네임드 커널 오브젝트를 사용한 중복 실행 방지법.

1. Introduction

윈도우상에서 구동되는 특정 애플리케이션들의 경우 중복 실행이 방지되어야 한다. 대표적으로 MSN 메신저등을 들 수 있다. 메신저의 경우 중복해서 실행될 필요가 없다. 이렇게 한번만 실행되어야 하는 프로그램의 경우 어떻게 구현할 수 있을까? 윈도우 핸들을 찾는 방법, 커널 오브젝트를 사용하는 방법, 공유 세그먼트를 사용하는 방법 등이 있다. 여기서 우리가 구현할 방법은 그 중에서도 커널 오브젝트를 사용한 방법이다.

2. Single Instance

커널 오브젝트를 사용해서 어떻게 중복 실행을 방지할 수 있을까? 원리는 네임드(Named) 커널 오브젝트의 경우 프로세스 사이에 공유 된다는 점 이다. 이 점을 이용하면 다음과 같은 시나리오를 생각할 수 있다. 프로그램 시작시에 네임드 커널 오브젝트를 생성한다. 그리고 프로그램이 종료할 때 해당 오브젝트를 닫는다. 이렇게 되면 한번이라도 해당 프로그램이 실행되어 있으면 그 오브젝트가 생성되어 있는 셈이 된다. 만약에 두 번째 프로그램이 실행된 경우에 또 커널 오브젝트를 생성하려고 하면 커널에서는 이미 열러진 오브젝트 핸들을 넘겨주면서 해당 오브젝트의 레퍼런스 카운트를 1증가 시킨다. 그리고 끝으로 GetLastError값으로 ERROR_ALREADY_EXISTS를 설정한다. 따라서 간단히 우리는 커널 오브젝트 생성후 GetLastError를 조사해서 ERROR_ALREADY_EXISTS면 이미 프로그램이 한번 이상 실행되었다고 간주할 수 있다.

아래는 이러한 부수적인 작업들을 한번에 처리해주는 클래스의 소스다. 해당 클래스를 전역 내지는, 프로그램의 존속 기간동안 살아있는 클래스의 멤버 변수로 만든후에 IsExist함수를 호출해서 조사하면 된다. 만약 해당 값이 TRUE를 리턴한다면 프로그램을 바로 종료시키면 된다.
 

  1. class CSingleInstance  
  2. {  
  3. private:  
  4.         HANDLE  m_hMutex;  
  5.           
  6. public:  
  7.         CSingleInstance(LPCTSTR lpszMutexName = "SingleMutex");  
  8.         ~CSingleInstance();  
  9.           
  10.         BOOL IsExist() {return m_hMutex==NULL;}  
  11. };  
  12.  
  13. CSingleInstance::CSingleInstance(LPCTSTR lpszMutexName)  
  14. {  
  15.         m_hMutex = CreateMutex(NULL, TRUE, lpszMutexName);  
  16.         if(GetLastError() == ERROR_ALREADY_EXISTS)  
  17.         {  
  18.                 CloseHandle(m_hMutex);  
  19.                 m_hMutex = NULL;  
  20.         }  
  21. }  
  22.  
  23. CSingleInstance::~CSingleInstance()  
  24. {  
  25.         if(m_hMutex)  
  26.         {  
  27.                 CloseHandle(m_hMutex);  
  28.                 m_hMutex = NULL;  
  29.         }  
  30. }     
  31.      

3. How to use it?

그럼 실제로 MFC 프로그램에서 한번 사용해 보자. 일단 위 클래스 소스를 적당한 위치에 복사한다. 그리고 app 클래스의 멤버 변수로 아래와 같이 선언한다.

  1. CSingleInstance m_inst;  

그 다음은 app 클래스의 InitInstance 제일 앞에 아래와 같이 추가해보자.

  1. if(m_inst.IsExist())  
  2. {  
  3.         AfxMessageBox("다른 곳에 실행된 놈이 있습니다.");  
  4.         return FALSE;  
  5. }     
  6.      

그리고 프로그램을 실행해보면 두번이상은 실행이 되지 않는 것을 확인할 수 있다. 주의해야 할 점은 위 클래스의 뮤텍스 이름은 클래스의 생성자로 전달된다는 것이다. 따라서 뮤텍스 이름을 지정하고 싶은 경우에는 C++의 초기화 리스트를 사용해서 초기화 해야 한다.
------------------------------------------------------------------------------------------

※ 윈도우 핸들을 찾는 방법

FindWindow(LPCTSTR lpszClassName,  LPCTSTR lpszWindowName) 함수를 이용해 찾으면 된다.(이 때, 인수 값을 NULL로 넣으면 그 인수는 검색에서 제외한다.)

app 클래스의 InitInstance 메서드에 다음과 같이 추가하면 된다.

if (pWndPrev=FindWindow(NULL,"프로그램타이틀")) {
  if (pWndPrev->IsIconic())  pWndPrev->ShowWindow(SW_RESTORE);

   pWndChild = pWndPrev->GetLastActivePopup();
  pWndChild->SetForegroundWindow();

  return FALSE;
}


※ 네임드(Named) 커널 오브젝트를 이용하는 방법

프로세스간 공유가 가능한 뮤텍스나, 세마포어와 같은 네임드 커널 오브젝트를 사용하면 된다.
프로그램 실행시에 오브젝트를 생성하고 프로그램 종료시에 오브젝트를 제거하면, 프로그램 실행 중에는 오브젝트가 생성되어 있으므로 만약에 두 번째 프로그램이 실행된 경우에 또 오브젝트를 생성하려고 하면 커널에서는 이미 열러진 오브젝트 핸들을 넘겨주면서 해당 오브젝트의 레퍼런스 카운트를 하나 증가 시킨다. 그리고 끝으로 GetLastError값으로 ERROR_ALREADY_EXISTS를 설정한다.

app 클래스의 InitInstance 메서드에 다음과 같이 추가하면 된다.

g_hMutex = CreateMutex(NULL, TRUE, "프로그램이름아무거나");  

if(GetLastError() == ERROR_ALREADY_EXISTS)  {  
   CloseHandle(g_hMutex);
   g_hMutex = NULL;

  return FALSE;
}

그리고 프로그램 종료시(OnDestroy 등)에는 뮤텍스를 해제하는 내용을 추가한다.

if (g_hMutex!=NULL)  ReleaseMutex(g_hMutex);
반응형
:: 2007년 06월 27일 ::

  Weekly Highlight
"Rational" 관련 최신 자료를 검색하고, RTube를 통해 Rational에 더욱 가까이 갈 수 있습니다.
   Local Contents
쾌속 학습팀 - 김창준 (dW Column)
멀티 패러다임 언어 D와 함께 하는 프로그래밍 - 이비오 (Open dW)
신기술 밀림 속 생존전략 Part 3: 프로젝트 현장의 이야기 - 안영회 (Special Issue)
진지한 취미가로서 즐겁게 살기 - 텔인포스 기술연구소 책임연구원, 고현철 님 (dW Interview)
   최신 기술자료 (한글)
Eclipse용 Ajax Toolkit Framework [오픈 소스]
이클립스, ATP, Dojo를 사용하여, 프레임웍을 설치하고 Ajax 애플리케이션을 구현하는 방법을 배워봅시다.
사람을 위한 자동화: 지속적인 피드백 [자바]
피드백은 Continuous Integration (CI)에 있어서 필수적인 것이며 사실상 CI 시스템의 혈액이라고 할 수 있습니다. 사람을 위한 자동화 시리즈에서는 CI 시스템에 적용할 수 있는 다양한 피드백 장치에 대해 설명합니다.
PHP 애플리케이션을 가장 빠르게, Part 3: Memcache 데몬을 사용하여 메모리에 데이터 저장(cache)하기 [오픈 소스]
Memcache 데몬(memcached)은 고성능 분산 객체 캐시로 애플리케이션과 데이터 스토어 중간에 설치되는 RAM의 객체를 보존합니다. 각각의 캐시 히트는 데이터베이스 서버의 라운드트립(roundtrip)을 대체하면서 애플리케이션의 속도를 높여줍니다.
Cell BE 프로세서의 고성능 애플리케이션 프로그래밍, Part 3: SPU [파워 아키텍처]
PPE와 통신하는 방법, CESOF 실행 파일을 만드는 방법, 16 바이트 버스 에러 의미 구분 방법 등을 설명합니다.
Graphical Editing Framework을 사용하여 이클립스 기반 애플리케이션 구현하기 [오픈 소스]
GEF를 사용하여 애플리케이션을 구현하는 초기 단계에 대해 배워봅시다. 이클립스의 그래픽 에디터를 만드는 프로세스를 시작하는 옵션에 대해서도 알아봅니다.
Real world Rails: Rails의 캐싱(Caching) [웹 개발]
일반적으로 Ruby on Rails는 캐싱에는 알맞지 않다고들 합니다. 하지만 상황이 나아졌습니다. Rails 실행 환경의 정적 캐싱, 동적 캐싱, 액션 캐싱, 부분 캐싱에 대해 알아봅시다.
   최신 튜토리얼 (한글)
이클립스용 GUI 빌더, Jigloo 시작하기 [오픈 소스]
Jigloo를 사용하여 워크플로우 애플리케이션용 UI를 구현하는 것이 얼마나 쉬운 일인지를 확인해 봅시다. 시각적 상속 같은 Jigloo의 고급 기능을 연구하고, 애플리케이션을 테스트 하며 이를 패키징 해봅니다.
WebSphere Application Server Community Edition용 Spring 애플리케이션 개발, Part 2 [WebSphere]
"이번 튜토리얼에서는 스프링(Spring)의 연결 관리 구조에 대해 살펴볼 것입니다. 이제 ContactDAOJDBC.java 클래스를 개발하는 방법과 연결 관리를 위해 연결 풀에 사용되는 널리 알려진 오픈소스만큼이나 간편한 스프링 고유의 구현 방법, WebSphere Application Server Community Edition의 연결 풀 구현을 사용하는 것이 얼마나 편리한지 배워보겠습니다.
   최신 SW 다운로드
Rational Software Architect V7.0
   로보코드 코리아컵 2007
로보코드 코리아컵 2007  

한국 IBM은 올해로 제4회를 맞는 자바 프로그램 경진대회인 로보코드 코리아컵 2007을 개최합니다. 입문자부터 전문 개발자까지 누구든지 쉽게 로봇을 만들어 참여할 수 있는 챔피언쉽에 자신만의 로봇을 만들어 친구와 동료와 실력을 겨루어 보세요! 참가하시는 모든 분께 참가상을 드립니다.
반응형

11 소켓

이 장에서는 소켓을 사용하여 프로세스간의 통신에 관한 GNU장치에 대해 서술한다.

소켓은 일반적인 프로세스간의 통신 채널이다. 파이프처럼 소켓은 파일 서술자처럼 표현된다. 그러나 파이프와는 달리 소켓은 관련 없는 프로세스간의 통신, 네트워크를 통하여 서로 다른 컴퓨터에서 수행되고 있는 프로세스간의 통신을 제공한다. 소켓은 주로 다른 컴퓨터간의 통신의 수단이다. telnet, rlogin, ftp, talk, 그리고 네트워크 프로그램들은 소켓을 사용한다. 모든 운영체제가 소켓을 지원하는 것은 아니다. GNU라이브러리에서 'sys/socket. h' 은 운영체제와 상관없이 존재한다. 그러나 만약 시스템이 소켓을 지원하지 않는다면, 소켓함수는 항상 실패한다.   미완성: 우리는 현재 인터넷 인터페이스 설정이나 브로드캐스트 메시지기능에 관하여는 문서화하지 못했다.


11. 1 소켓 개념

당신이 소켓을 만들 때, 반드시 당신이 어떤 통신 스타일을 쓸 것인지, 어떤 프로토콜을 사용할 것인지 명시해야 한다. 소켓의 통신 스타일은 소켓으로 데이터를 보내고 받는 유저레벨 구문을 정의한다. 통신 스타일을 선택하는 것은 다음과 같은 질문의 응답이 된다.

데이터 전송의 단위는 무엇인가?

어떤 통신 스타일은 큰 구조체를 가지지 않는, 바이트의 열로 된다. 다른 것들은 (패킷 같은) 레코드 안에 바이트를 묶어 놓는다.

보통 작업을 하는 동안에 데이터를 잃어버릴 수 있나?

어떤 통신 스타일에서 보내진 데이터가 (시스템이나 네트워크 충돌을 제외하고) 보내진 순서대로 모두 도달해야 한다. ; 다른 스타일은 때로는 보통 동작 시에도 데이터를 잃어버리거나, 하나 이상의 같은 패킷이 전달될 수도 있고, 순서가 뒤바뀔 수도 있다.
신뢰 있는 통신스타일을 사용하는 프로그램을 설계하는 것은 보통 데이터 손실이나, 순서가 뒤바뀌는 것을 검출하고 필요에 따라 재 전송하는 대책을 포함한다.

상대측과 완전한 통신을 하느냐?

어떤 통신스타일은 전화 거는 것과 같이 상대측과 원격 소켓 연결을 만들고 나서, 자유롭게 데이터를 교환한다. ; 다른 스타일은 편지 쓰는 것처럼 당신이 보내고자하는 메시지의 주소를 써서 보낸다.
당신은 또한 소켓의 이름공간에서 이름을 선택해야 한다. 소켓이름("주소")은 특정한 이름공간의 의미심장한 내용이 있다. 이름공간은 또한 "도메인"이라고 불린다. 그러나, 우리는 같은 용어의 다른 사용과 혼돈할 수 있어 그 말을 피하겠다. 각 이름공간은 'PF_'로 시작하는 상징적인 이름을 가진다. 'AF_'로 시작하는 유사한 상직적 이름은 그 이름공간에 주소 포맷을 가리킨다.
마지막으로, 당신은 통신을 제공하는 프로토콜을 선택해야 한다. 프로토콜은 데이터를 주고받는데 사용되는 저수준 메커니즘을 말한다. 각 프로토콜은 특정한 이름공간과 통신스타일에 대하여 유효하다. ; 이름공간은 종종 프로토콜 패밀리라고 불린다. 왜냐하면 이름 공간이 'PF_'로 시작하기 때문이다.
프로토콜의 규칙은 비록 다른 컴퓨터에서일지라도 두 프로그램간의 데이터 전송을 제공한다. 이러한 규칙의 대부분은 운영체제에 의하여 다루어지고, 당신이 그것에 대해 알 필요는 없다. 당신이 프로토콜에 대하여 알아야 할 것은 이것이다. :

두 소켓간의 통신을 위하여, 그것들은 반드시 같은 프로토콜을 나타내야 한다.

각 프로토콜은 특정한 스타일과 이름공간 결합에 의미를 가지며, 적당하지 않은 결합의 사용은 할 수 없다. 예를 들어 TCP 프로토콜은 바이트 스트림 스타일의 통신과 인터넷 이름공간에 맞추어져 있다.
스타일과 이름공간의 각 조합에서 프로토콜 번호를 0으로 나타내어 요구하면 그것은 기본프로토콜(디폴트 프로토콜)로 된다. 그리고, 당신은 보통 하는 것(디폴트를 사용하는 것)이 이런 것이다.


11. 2 통신스타일

GNU라이브러리는 각기 다른 특성을 지닌 몇 종류의 소켓을 지원하고 있다. 이 절에서는 지원되는 소켓 형태를 서술한다. 여기 나타난 심볼릭 상수는 'sys/socket. h'에 정의되어 있다.

int SOCK_STREAM Macro

SOCK_STREM스타일은 파이프와 같다. (10장[파이프와 FIFO] 을 보라). 그것은 특정한 원격 소켓과의 연결 후에 동작한다. 그리고 바이트의 스트림처럼 신뢰성 있는 데이터 전송을 한다. 이 스타일의 사용은 11. 8절에 자세히 나와 있다.

int SOCK__DGRAM Macro

SOCK_DGRAM 스타일은 개별적으로 주소가 쓰여진 패킷을 전달하는데 사용된다. 그것은 SOCK_STREAM과 정반대이다. 당신이 이 종류의 소켓에 데이터를 써넣는다. 그러면 그 데이터는 하나의 패킷이 된다. SOCK_DGRAM 소켓은 연결을 가지지 않는다. 당신은 각 패킷에 반드시 반복적으로 주소를 써넣어야 한다. 데이터를 전송하고자 하는 당신의 요구에 관하여 시스템의 책임은, 각 패킷이 가장 잘 배달될 수 있도록 시도하는 것이다. 그것은 네 번째와 다섯 번째 실패 후에 여섯 번째에 성공할 수 있다. ; 일곱 번째 패킷은 여섯 번째 전에 도착될 수도 있다. 그리고 여섯 번째 후에 두 번 도착할 수도 있다. SOCK_DGRAM은 일반적으로 응답해야할 시간내에 응답이 없을 때 간단히 패킷을 재 전송하는데 적합하다. 데이터그램 소켓을 사용하는 방법에 대한 자세한 정보는 11. 9절[데이터그램]을 보라

int SOCK__RAW Macro

이 스타일은 저수준 네트워크 프로토콜과 인터페이스를 억세스하도록 해 준다. 보통 사용자 프로그램은 이 스타일을 자주 사용할 필요가 없다.


11. 3 소켓 주소

소켓의 이름은 보통 "주소"라고 불린다. 소켓주소와 관계된 기호(symbol)와 함수들은, 때때로 "이름"이라는 말이나 "주소"를 사용되어, 어떤 규칙 없이 이름 지어진다. 당신은 소켓이 고려되는 곳에 이러한 말을 동일한 것처럼 생각할 수 있다. socket함수로 새롭게 만든 소켓은 주소를 가지지 않는다. 당신이 그것에게 주소를 주어야만, 다른 프로세스가 통신을 위한 주소를 찾을 수 있게 된다. 이것을 주소를 소켓에 묶는다고 하고, bind함수를 이용한다. 만약 다른 프로세스들이 주소일 찾고, 주소를 이용하여 통신을 시작하는 것이라면, 당신은 소켓의 주소를 생각해 볼 필요가 한다. 당신은 다른 소켓의 주소를 규명할 수 있지만, 그것은 보통 무의미하다; 처음, 소켓으로부터 데이터를 보내거나 연결을 초기화하기 위해 그것을 사용할 때, 만약 구체적으로 나타내진 것이 없다면, 시스템은 주소를 자동으로 설정한다.

서버는 주소에 기초하여 판별되기 때문에, 보통 클라이언트는 주소를 명시해야 한다. ; 예를 들어, rsh 와 rlogin 프로토콜은 클라이언트의 소켓주소를 살피고, 만약 그것이 IPPORT_RESER

VED보다 작지 않다면, 암호검사를 거쳐야 한다. ( 11.5.3절의 [포트] 을 보라)

소켓주소의 자세한 것은 당신이 사용하는 어떤 이름공간에 의존하여 변한다. 자세한 정보를 위해서는 11. 4절 [파일 이름공간] 을 보거나, 11. 5절 [인터넷 이름공간] 참조. 이름공간에 상관없이 , 소켓의 주소를 세트하고 사용하기 위해 당신은 같은 bind와 getsockname함수를 사용한다. 이러한 함수들은 주소를 받아들이기 위해 struct sockaddr *라는 위조 자료형(phony data type)을 사용한다. 실제적으로, 주소는 당신이 사용하는 주소포맷과는 다른 자료형의 구조로 되어 있다. 그러나, 당신은 그것을 bind하기 위해 넘겨줄 때, 그것의 주소를 struct sockaddr *로 자료형 변환(cast)을 해주어야 한다.


11. 3. 1 주소 포맷

bind와 getsockname함수는 소켓의 주소의 포인터를 의미하는 struct sockaddr *이라는 일반적인 자료형을 사용한다. 당신은 주소를 번역하거나 만들기 위해 이 자료형을 효율적으로 사용할 수 없다; 대신, 소켓의 이름공간을 위한 자료형을 사용해야만 한다. 그러므로, 보통 실제적인 사용은 적합한 이름공간의 형태의 주소를 만드는데 사용하고 나서, bind나 getsockname을 호출할 때 struct sockaddr *로 포인터형태를 변환한다. 당신이 struct sockaddr 자료형으로부터 얻을 수 있는 정보 중 하나는, 주소를 완전히 이해하기 위해 사용되는 자료형이 어떤 것인지 알려주는 "주소 포맷" 지정자이다. 이 절에서의 기호는 'sys/socket. h'라는 헤더파일안에 정의되어 있다.

struct sockaddr 자료형

struct sockaddr형 자체는 다음 멤버를 가지고 있다:

    short int sa_family

    이것은 이 주소의 주소 포맷용 코드이다. 그것은 다음에 나오는 데이터의 포맷을 지시한다.

    char sa_data[14]

    이것은 실제적인 소켓주소 데이터이다. 이것은 포맷에 의존한다. 그것의 길이는 또한 포맷에 의존하고 아마 14보다 클 것이다. sa_data의 14라는 길이는 원래 변할 수 있다. 각 주소포맷은 AF_로 시작하는 기호이름으로 시작된다. 그것들은 각각 이름공간에 대응되는 'PF_' 기호에 맞춰져 있다.

AF_FILE

이것은 파일 이름공간에 맞는 주소포맷이다. (PF_FILE은 이 이름공간의 이름이다. ) 이 주소 포맷의 정보를 보려면 11. 4. 2절 [파일 이름공간 구체적 내용] 을 보라.

AF_UNIX

이것은 호환성을 위한 AF_FILE과 같은 말이다. (PF_UNIX는 PF_FILE과 역시 동의어이다. )

AF_INET

이것은 인터넷 이름공간에 맞는 주소포맷이다. (PF_INET은 이 이름공간의 이름이다. ) 11. 5. 1절 [인터넷 주소 포맷] 을 보아라.

AF_UNSPEC

이것은 특정한 주소포맷을 지정하지 않는다. 그것은 "연결된" 데이터그램 소켓의 기본(default)목적지 주소를 지우는 것 같은 드문 경우에만 사용된다. 11. 9. 1절[데이터그램 보내기] 을 보아라. 여기에 맞는 이름 공간지정자 기호도 완전성을 위해 존재한다. 그러나, 그것을 프로그램에서 사용할 필요는 없다. 'sys/socket. h' 에서 대부분 실제로 구현되지 않은 많은 다른 종류의 네트워크에 'AF_'로 시작하는 기호를 정의하고 있다. 어떻게 그것을 사용하는 것에 관한 정보를 우리가 받으면, 우리는 그것을 정말로 문서화할 것이다.

11. 3. 2 소켓의 주소를 세팅하기

소켓에 주소를 할당하기 위하여 bind함수를 사용하라. bind의 프로토타입은 'sys/socket. h'헤더파일에 있다. 사용예는 11. 4절[파일 이름공간], 또는 11. 5. 7절[Inet 예제] 을 보라.

int bind (int socket, struct sockaddr *addr, size_t length) Function

bind함수는 "socket"소켓에 주소를 지정한다. addr과 length인수는 주소를 구체화한다. 자세한 주소포맷은 이름공간에 의존한다. 주소의 첫 번째 부분은 항상 포맷지정자이다. 포맷지정자는 이름공간을 명시하고, 그 주소가 그 이름공간의 포맷의 주소임을 말한다. 성공하면 0을 리턴하고, 실패하면 -1을 리턴한다.
다음은 이 함수에 정의되어 있는 errno 에러조건이다.

EBADF : 소켓 인수가 유효하지 않은 파일 지정자이다.

ENOTSOCK : 서술자 socket이 소켓이 아니다.

EADDRNOTAVAIL : 지시된 주소가 이 장치에서는 유효하지 않다.

EADDRINUSE : 또 다른 소켓이 이 주소로 이미 사용되고 있다.

EINVAL : socket소켓이 이미 주소를 가지고 있다.

EACCESS

당신은 요구된 주소를 제어할 허가권을 가지고 있지 않습니다. (인터넷 도메인에서, 단지 슈퍼유저만이 0에서 IPPORT_RESERVED-1까지 범위의 포트넘버를 사용할 수 있다. 11. 5. 3절[ports] 보라. )

추가적인 조건은 소켓의 각각 이름공간에 의존한다.

11. 3. 3 소켓의 주소 읽기

getsockname함수를 사용하여, 인터넷 소켓의 주소를 확인할 수 있다. 이 함수의 프로토타입은 'sys/socket. h'라는 헤더파일에 있다.

int getsockname (int socket, struct sockaddr *addr, size_t *length_ptr) 함수

getsockname함수는 addr과 length_ptr 인수로 명시되는 곳의 socket이라는 소켓의 주소에 관한 정보를 리턴한다. length_ptr은 포인터임을 주목하라; 당신이 addr의 크기 할당을 초기화할 것이다. 당신은 addr의 할당크기를 초기화 할 것이고, 주소데이터의 실제크기를 포함한 것이 리턴될 것이다.
주소데이터의 포맷은 소켓 이름공간에 의존한다. 정보의 길이는 주어진 이름공간에 보통 맞추어진다. 그래서, 보통 당신은 필요한 공간이 정확히 얼마인지 알 수 있고, 그것만큼 제공할 수 있다. 실제적인 사용은 소켓의 이름공간에 적합한 자료형을 사용하는 값으로 공간을 할당하고 나서, 그것을 getsockname으로 넘기기 위해 그 주소를 struct sockaddr*로 형변환(cast)한다.
리턴 값 0은 성공이고, -1은 에러이다. 다음 에러조건은 이 함수에서 정의된 것이다.

EBADF : 소켓인수가 유효한 파일 서술자가 아니다.

ENOTSOCK : 서술자 socket이 소켓이 아니다.

ENOBUFS

동작을 수행할만한 충분한 버퍼가 없다. 당신은 이름공간의 소켓의 주소를 읽을 수 없다. 이것은 시스템의 나머지 사항에 일치한다. 일반적으로, 그 파일의 서술자로부터 파일의 이름을 얻어낼 방법은 없다.


11. 4 The File Namespace

이 부분은 상징적인 이름(소켓을 만들 때 요구하는) 은 PF_FILE이라는 파일 이름공간에 대해 상세히 설명한다.


11. 4. 1 파일 이름공간 개념들

파일이름공간에서, 소켓 주소는 파일 이름들이다. 당신은 소켓의 주소처럼 당신이 원하는 어떤 파일 이름을 명시할 수 있다. 그러나 당신은 반드시 그것을 포함하는 디렉토리에 쓰기 허가를 가지고 있어야 한다. 소켓에 연결하기 위해, 당신은 그것에 대한 읽기 허가도 가지고 있어야 한다. 보통 /tmp디렉토리 안에 그러한 파일들을 넣는다.

파일이름공간의 특별한 점 하나는 연결을 할 때 그 이름이 한 번만 사용된다는 것이다. 즉, 그것을 한 번 사용하고 나면, 그 주소는 의미가 없고, 존재하지 않을지도 모른다.

또 다른 특징은 만약 소켓의 이름을 포함하는 파일시스템을 다른 기기가 공유하지 않는다면 다른 기기의 어떤 소켓으로 연결할 수 없다는 것이다. 당신은 디렉토리 리스트 안에서 소켓을 볼 수 있으나, 그것에 연결하는 것은 불가능하다. 어떤 프로그램들은 클라이언트가 자기 프로세스 ID를 보내도록 요구하는 것과 프로세스ID를 사용하여 클라이언트간을 식별하는 것을 이용하는 것 등을 이용한다. 그러나, 우리는 당신이 설계하는 프로토콜들 안에서 이 방법을 사용하지 말기를 원한다. 우리는 같은 파일시스템을 사용하는 다른 기기로부터의 연결들을 허락해야 할지도 모르기 때문이다. 대신에, 만약 그것을 가지는 것을 원한다면, 각 클라이언트에게 식별번호를 보낸다.

파일 이름공간안의 소켓을 닫은 후에, 당신은 파일시스템으로부터 파일이름을 지워야 한다. unlink나 remove를 사용하여 이것을 하라. 9. 5절 [파일 삭제하기] 을 보라.

파일 이름공간은 단지 어떤 통신 스타일에 대해 하나의 프로토콜만 지원한다. 그것은 프로토콜 번호 0이다.


11. 4. 2 파일이름 공간의 자세한 것

파일 이름 공간에 소켓을 만들려면, socket또는 sockerpair의 이름공간 인수에 상수 PF_FILE을 사용하라. 이 상수는 'sys/socket. h'에 정의되어 있다.

int PF__FILE Macro

이것은 소켓주소가 파일이름인 파일이름 공간과 그것이 연합된 프로토콜 패밀리를 가리킨다.

int PF__UNIX Macro

이것은 호환성을 위한 PF_FILE의 동의어이다.
파일이름공간의 소켓이름을 명시하는 구조체는 'sys/un. h'라는 헤더파일에 정의되어 있다.

struct sockaddr__un Data Type

이 구조체는 파일이름공간을 소켓 주소로 명시하는데 사용된다.

short int sun_family

이것은 소켓주소를 위한 형태나 주소패밀리를 명시한다. 당신은 파일이름공간을 지정하기 위하여 AF_FILE값을 저장해야 한다. 11. 3절 [소켓주소] 을 보라.

char sun_path[108]

이것은 사용되는 파일이름이다.
미완성: 왜 108이 매직넘버인가? RMS는 이것을 길이가 0인 배열을 만드는 것과 파일이름의 길이에 기초하여 적합한 저장공간을 할당하기 위해 allocate를 사용하는 것과 같은 예를 꼬집어 제안한다.

당신은 sun_family요소의 크기와 파일이름문자열의 (할당 크기가 아닌)문자열 길이의 합인, 파일이름공간에 소켓주소를 위한 길이 매개변수를 계산해야 한다.


11. 4. 3 파일-이름공간 소켓의 예

여기 있는 것은 파일이름공간의 소켓을 만들고 이름지어주는 방법을 보여주는 예이다.

#include <stddef. h>
#include <stdio. h>
#include <errno. h>
#include <stdlib. h>
#include <sys/socket. h>
#include <sys/un. h>
int
make_named_socket (const char *filename)
{
struct sockaddr_un name;
int sock;
size_t size;
/* 소켓 만들기 */
sock = socket (PF_UNIX, SOCK_DGRAM, 0);
if (sock < 0) {
perror ("socket");
exit (EXIT_FAILURE);
}
/* Bind a name to the socket. */
name. sun_family = AF_FILE;
strcpy (name. sun_path, filename);
/* The size of the address is the offset of the start of the filename, plus its length, plus one for the terminating null byte. */
size = (offsetof (struct sockaddr_un, sun_path) + strlen (name. sun_path) + 1);
if ( bind (sock, (struct sockaddr *) &name, size) <0) {
perror ("bind");
exit (EXIT_FAILURE);
}
return sock;
}


11. 5 인터넷 이름공간

이 장에서는 프로토콜과 소켓이 인터넷 이름공간에서 사용되는 이름짓는 방법에 대해 서술한다. 인터넷 이름공간에서 소켓을 만들려면, socket이나 socketpair의 이름 공간인수로 이 이름공간의 PF_INET 기호를 사용한다. 이 매크로는 'sys/socket. h'에 정의되어 있다.

int PF__INET Macro

이것은 인터넷 이름공간을 지정하고 프로토콜의 연합된 패밀리를 지정한다.

인터넷 이름공간의 소켓 주소는 다음과 같은 성분을 포함한다:

당신이 연결하기 원하는 장치의 주소. 인터넷 주소는 몇 가지 방법으로 표현될 수 있다. 이러한 방법들은 11. 5. 1절 [호스트 주소]11. 5. 2. 4절 [호스트 이름] 에서 논의한다.

그 장치의 포트 번호. 11. 5. 3절 [포트] 을 보라

당신은 주소와 포트번호가 네트워크 바이트 순서라고 불리는 정규화 된 포맷으로 표현된다는 것을 알아야 한다. 이에 관한 정보는 11. 5. 5절 [바이트 순서] 을 보라


11. 5. 1 인터넷 소켓 주소 포맷

인터넷 이름공간에서, 소켓주소는 호스트의 주소와 그 호스트의 포트를 포함한다. 추가적으로 당신이 선택한 프로토콜은 주소의 일부분처럼 효과적으로 제공된다. 왜냐하면 지역적인 포트번호는 특정한 프로토콜 안에서 의미를 가지기 때문이다. 인터넷 이름공간안의 소켓 주소의 표현에 관한 자료형은 'netinet/in. h' 헤더파일에 정의되어 있다.

struct sockaddr__in Data Type

이것은 인터넷 이름공간안의 소켓주소를 표현하는데 사용되는 자료형이다. 그것은 다음 멤버를 가진다.

short int sin_family

이것은 소켓주소의 포맷이나 주소 패밀리를 지시한다. 당신은 이 멤버내에 AF_INET값을 저장해야 한다. 11. 3절 [소켓주소] 을 보라

struct in_addr sin_addr

이것은 호스트 장치의 인터넷 주소이다. 어떻게 여기에 넣을 값을 얻는지에 관하여는 11. 5. 2절 [호스트 주소]11. 5. 2. 4 [호스트 이름] 을 보라.

unsigned short int sin_port

이것은 포트번호이다. 11. 5. 3절 [포트] 을 보라.

당신이 bind나 setsockname을 호출할 때, 만약 당신이 인터넷 이름공간 소켓 주소를 사용한다면, '길이' 매개변수로 sizeof (struct sockaddr_in)을 명시해야 한다.


11. 5. 2 호스트 주소

인터넷의 각 컴퓨터는 하나 또는 그 이상의 인터넷 주소를 가진다. 주소는 인터넷의 모든 것들 사이에서 그 컴퓨터를 지시하는 숫자이다. 사용자는 통상 숫자로된 호스트 주소를 사용한다. 그것은 '128. 52. 46. 32'처럼 네 숫자로 되어 있고 점으로 나뉘어져 있다. 각 컴퓨터는 또한 하나 또는 그 이상의 호스트 이름을 가진다. 그것은 'churchy. gnu. ai. mit. edu'처럼 점으로 나뉘어진 단어의 문자열이다.

사용자가 호스트를 명시하게 하는 프로그램은 전형적으로 숫자주소와 호스트 이름 모두를 수용한다. 그러나 프로그램은 연결을 위해 숫자로된 주소를 필요로 한다. 즉 호스트 주소를 사용하기 위해, 당신은 그것이 상징하고 있는 숫자 주소로 변환해야 한다.


11. 5. 2. 1 인터넷 호스트 주소

인터넷 호스트 주소는 데이터의 4바이트를 포함하는 숫자이다. 그것들은 두부분으로 나뉘는데, 네트워크 번호와 그 네크워크내의 지역 네트워크 주소 번호가 그것이다. 네트워크 숫자는 처음 하나, 둘 또는 세 개의 바이트를 포함한다. 나머지 바이트는 지역 주소이다.

네트워크 번호들은 네트워크 정보 센터 (NIC, Network Information Center)에 등록되어 있다. 그것들은 세 개의 클래스 A, B, C로 분할된다. 각각 컴퓨터마다의 지역네트워크 주소는 각 네트워크의 관리자에 의해 등록되어 있다.

클래스 A 네트워크는 0에서 127범위의 한 바이트 숫자를 가진다. 클래스 A 네트워크의 수는 매우 작지만, 각각은 굉장히 많은 수의 호스트를 지원한다. 중간크기의 클래스 B 네트워크는 두바이트의 네트워크 번호를 가진다. 첫 번째 바이트의 범위는 128에서 191까지이다. 클래스 C 네트워크는 가장 작다. 그것들은 세 바이트의 네트워크 번호를 가지며, 첫 번째 바이트의 범위는 192에서 255까지이다. 그러므로, 인터넷 주소의 처음 1, 2, 3바이트는 네트워크를 명시하는 것이다. 인터넷 주소의 나머지 바이트는 네트워크 안에서의 주소를 명시한다. 클래스 A네트워크 0은 모든 네트워크에 브로드캐스트용으로 예약되어 있다. 추가적으로 각 네트워크 내에서의 호스트 번호가 0인 것은 그 네트워크 내의 모든 호스트들에게 방송(broadcast)하기 위해 예약되어 있다. 클래스 A 네트워크 127은 루프백(loopback)용으로 예약되어 있다. 당신은 그러므로 인터넷 주소 '127. 0. 0. 1'을 사용하면 자신의 호스트장치를 참조 할 수 있다.

단일 장치는 여러 개의 네트워크의 멤버가 될 수 있으므로, 그것은 여러 개의 호스트 주소를 가질 수 있다. 그러나, 같은 호스트 주소를 가진 장치가 하나 이상 있어서는 안 된다.

인터넷 주소를 위한 숫자와 이름 표현은 네 가지 형태가 있다.

  • a. b. c. d 이것은 각개별적으로 주소의 모든 네 개의 바이트를 나타낸다.
  • a. b. c 주소의 마지막 부분인 c는 2바이트로 취급된다. 이것은 네트워크 번호 a. b를 가진 클래스 B의 호스트 주소를 나타내는데 유용하다.
  • a. b 주소의 마지막 부분인 b는 3바이트로 취급된다. 이것은 네트워크 주소 a를 가진 클래스A의 호스트 주소를 표시하는데 유용하다.
  • a 만약 하나의 부분만 주어진다면, 이것은 호스트 주소에 직접 일치하게 된다.

주소의 각부분에서, 기수를 표시하기 위해 보통 C관례를 사용한다. 다른 말로 하면, '0x' 또는 '0X'로 시작하는 것은 16진수 기수를 내포한다. '0'으로 시작하는 것은 8진수를 내포하고, 다른 것은 10진수 기수로 가정한다.


11. 5. 2. 2 호스트 주소 자료형

인터넷 호스트 주소는 정수 형들(unsigned long int형)같은 형식으로 표현된다. 다른 말로 하면, 정수들은 struct in_addr의 형태의 구조체 안에 들어가게 된다. 만약 용법이 일치되면 좋을 것이나, 그렇지 못하다면, 구조체로부터 정수를 뽑아 내거나, 정수를 구조체에 넣는 것이 쉽지 않을 것이다. 다음 인터넷 주소에 관한 기본적인 정의는 'netinet/in. h'헤더 파일 안에서 볼 수 있다:

struct in_addr 자료형

이 자료형은 인터넷 주소를 포함하는 정확한 문맥에 사용된다. 그것은 단지 s_addr이라는 하나의 필드를 가진다. 그것은 unsigned long int 처럼 호스트 주소번호를 저장한다.

unsigned long int INADDR__LOOPBACK Macro

당신은 이 장치의 실제주소를 찾는 대신에, 이 상수를 사용할 수 있다. 그것은 보통 'localhost(로컬호스트)'라 불리는 인터넷 주소 '127. 0. 0. 1'이다. 이 특별한 상수는 당신의 장치의 주소를 살피는데 생기는 문제를 해결해 준다. 또한, 시스템은 한 장치에서 자기자신으로 전송하는 경우 어떤 네트워크전송을 피하기 위해, 주로 INADDR_LOOPBACK을 특별히 구현하고 있다.

unsigned long int INADDR__ANY Macro

주소를 바인딩할 때, "어떠한 오는 주소(any incoming address)"에 대한 것을 이 상수를 사용할 수 있다. 11. 3. 2절 [주소 설정] 를 보라. 이것은 당신이 인터넷 연결을 받아들이길 원할 때, sockaddr_in구조체의 sin_addr멤버에 주로 들어가는 주소이다.

unsigned long int INADDR__BROADCAST Macro

이 상수는 방송메시지를 보내는데 사용되는 주소이다.

unsigned long int INADDR__NONE Macro

이 상수는 어떤 함수들이 에러를 지시하기 위해 반환된다.

11. 5. 2. 3 호스트 주소 함수들

인터넷 주소를 조작하는 추가적인 함수들은 'arpa/inet. h'안에 선언되어 있다. 그것들은 네트워크 바이트 순서로 인터넷 주소를 표현한다. 즉 그것들은 네트워크 번호와 네트워크 안에서의 지역 주소를 호스트 바이트 순서로 표현한다. 네트워크와 호스트 바이트 순서에 관한 설명은 11. 5. 3절 [바이트 순서] 을 보라.

int inet__aton (const char *name, struct in_addr *addr) 함수

이 함수는 인터넷 호스트 주소 이름을 표준 숫자와 점 표시형식에서 이진데이터 형으로 변환한다. 그리고, 그것을 addr이 지시하고 있는 struct in_addr안에 저장한다.

unsigned long int inet__addr (const char *name) 함수

이 함수는 인터넷주소 이름을 숫자와 점으로 된 것에서 이진 데이터로 변환한다. 만약 입력이 유효하지 않으면, inet_addr은 INADDR_NONE를 반환한다. 이것은 위에서 서술한 inet_aton의 구식의 인터페이스이다. INADDR_NONE은 유효한 주소 ( 255. 255. 255. 255 ) 이기 때문에 그것은 쓸모 없이 되었다. 그리고 inet_aton 은 에러 반환을 지시하는 더 깔끔한 방법을 제공한다.

unsigned long int inet__network (const char *name) 함수

이 함수는 숫자와 점으로 표현되는 주소이름으로 부터 네트워크 번호를 뽑아낸다. 만약 입력을 제대로 하지 않으면, inet_network는 -1을 반환한다.

char * inet__ntoa (struct in_addr addr) 함수

이 함수는 인터넷 호스트 주소 addr을 숫자와 점으로 표현되는 문자열로 변환한다. 반환되는 값은 정적으로 할당된 버퍼의 포인터이다. 계속 호출하면 같은 버퍼에 덮어쓰기를 하므로, 만약 그것을 저장하기 위해서 그 문자열을 복사해두어야 한다.

struct in_addr inet__makeaddr (int net, int local) 함수

이 함수는 지역 네트워크 내의 지역 주소 local과 네트워크 번호 net를 묶어 인터넷 호스트 주소를 만든다.

int inet__lnaof (struct in_addr addr) 함수

이 함수는 인터넷 호스트 주소 addr의 일부인 네트워크 내에서의 지역 주소를 반환한다.

int inet__netof (struct in_addr addr) Function

이 함수는 인터넷 호스트 주소의 일부인 네트워크 번호를 반환한다.

 

11. 5. 2. 4 호스트 이름들

인터넷 주소를 위한 숫자와 점으로 표현하는 것 외에, 당신은 의미 있는 이름을 사용하여 호스트를 참조할 수 있다. 의미 있는 이름을 사용하는 것의 장점은 역시 외우기 쉽다는 것이다. 예를 들어 인터넷 주소 '128. 52. 46. 32'를 가진 장치는 'churchy. gnu. ai. mit. edu'로도 표현된다. 또한 'gnu. ai. mit. edu' 도메인내의 다른 컴퓨터들은 간단하게 'churchy'로 이 장치를 참조할 수 있다.

내부적으로, 시스템은 호스트 이름과 호스트 번호 사이의 매핑의 정보를 유지하는 데이터베이스를 사용한다. 이 데이터베이스는 보통 '/etc/hosts'이거나 네임서버에 의해 제공된다. 이 데이터 베이스에 접근하기 위한 함수와 기호들은 'netdb. h'에 선언되어 있다. 만약 당신이 'netdb. h'를 포함한다면, 그것들은 무조건적으로 정의되어 있는 BSD들의 특징이다.

struct hostent 자료형

이 자료형은 호스트 데이터베이스 안의 내용을 표현하는 데 사용된다. 그것은 다음 멤버를 가진다.

char *h_name

이것은 호스트의 "사무적인" 이름이다.

char **h_aliases

스트링의 null로 끝나는 벡터로 표현된 호스트의 또다른 이름이다.

int h_addrtype

이것은 호스트 주소의 형태이다. 실제적으로, 이것의 값은 항상 AF_INET이다. 원래 다른 종료의 주소도 인터넷 주소처럼 데이터베이스 안에 표현될 수 있다. 만약 그렇게 한다면, 당신은 이 필드에 AF_INET이 아닌 어떤 값을 찾아야 한다. 11. 3[소켓 주소들] 을 보라.

int h_length

이것은 각 주소의 바이트 길이다.

char **h_addr_list

이것은 호스트의 주소들의 벡터이다. (호스트들은 다중 네트워크에 연결되고 각각 여러 개의 다른 주소를 가진다는 것을 회상하라) 벡터는 널 포인터로 종료된다.

char *h_addr

이것은 h_addr_list[0]과 동의어이다. 다른 말로, 이것은 첫 번째 호스트 주소이다.
호스트 데이터베이스가 고려되는 것과는 달리, 각 주소는 h_length 바이트 길이의 메모리 블록이다. 그러나 다른 문맥에서, 그것들은, 당신이 이것을 in_addr 또는 unsigned long int로 변환할 수 있는 암시적인 가정이다. struct hostent 구조체의 호스트 주소들은 항상 네트워크 바이트 순서로 주어진다. 11. 5. 5절 [바이트 순서] 을 보라. 당신은 특정한 호스트에 관한 정보를 찾기 위해 호스트 데이터베이스를 검색하려면 gethostbyname 또는 gethostbyaddr를 사용할 수 있다. 그 정보는 정적으로 할당된 구조체에 반환된다. 만약 당신이 그것을 호출로부터 저장하기 위해서는 정보를 복사해야 한다.

struct hostent * gethostbyname (const char *name) 함수

gethostbyname함수는 name으로 이름지어진 호스트에 관한 정보를 반환한다. 만약 검색에 실패하였으면, 널 포인터를 반환한다.

struct hostent * gethostbyaddr (const char *addr, int length, int format) 함수

gethostbyaddr함수는 인터넷 주소 addr의 호스트에 관한 정보를 반환한다. 인수의 length는 addr 주소의 (바이트 단위의)크기이다. format는 주소형식을 명시한다. 즉 인터넷 주소라면 AF_INET값으로 명시하면 된다. 만약 검색에 실패를 하면, gethostbyaddr는 널 포인터를 반환한다. 만약 gethostbyname 또는 gethostbyaddr을 이용한 이름검색이 실패하면, 당신은 변수h_errno의 값을 살펴보고 그 원인을 찾을 수 있다. (그것은 그러한 함수가 errno를 세팅하도록 더 깔끔하게 설계되어 있다. 그러나 h_errno의 사용은 다른 시스템에 대해 호환성 있게 되어 있다. )
h_erro사용하기 전에, 당신은 다음과 같이 그것을 선언해 주어야 한다.

extern int h_errno; 아래는 h_errno안에서 찾을 수 있는 error코드들이다:

HOST_NOT_FOUND

어떤 호스트가 data base안에 없다.

TRY_AGAIN

이 상태는 네임서버에 연결되지 않을 때 발생한다. 만약 당신이 나중에 다시 시도한다면, 성공할 수도 있다.

NO_RECOVERY

복구할 수 없는 에러 발생.

NO_ADDRESS

호스트 데이터베이스는 이름에 대한 항목을 포함하나, 그것은 적합한 인터넷 주소를 가지지 않았다.
당신은 또한 sethostent, gethostent, endhostnet를 사용하여 한 번에 한 항목씩 전체 호스트 데이터베이스를 죽 살펴본다. 이러한 함수들을 사용할 때는 주의해야 한다. 왜냐하면 그것들은 재진입성을 가지지 않기 때문이다. (즉, 스케줄을 점유한다)

void sethostent (int stayopen) 함수

이 함수는 데이터베이스를 살펴보는 것을 시작하기 위해서 호스트 데이터베이스를 연다. 당신은 항목들을 읽기 위해 그러고 나서 gethostent를 호출해야 한다. 만약 stayopen인수가 0이 아니면, 다음으로 gethostbyname 또는 gethostbyaddr를 호출하는 것이 데이터베이스를 닫지 않도록 (그것들이 그래야 하는 것처럼) 이것은 플래그를 세트한다.

struct hostent * gethostent () 함수

이 함수는 호스트 데이터베이스 안의 다음 항목을 반환한다. 만약 더 이상 항목이 없으면, 널 포인터를 리턴한다.

void endhostent () 함수

함수는 호스트 데이터 베이스를 닫는다.

11. 5. 3 인터넷 포트

인터넷 이름공간에서의 소켓주소는, 장치의 인터넷 주소에 추가적으로 주어진 장치의 소켓을 구별하는 포트번호로 구성된다. 포트번호는 0에서 65535번까지의 범위이다. IPPORT_RESERVED보다 작은 포트번호는 표준서버에서 finger나 telnet과 같은 것을 위해 예약되어 있다. 시스템 내부에 이러한 것들을 유지하고 있는 데이터베이스가 있고, 당신은 getservbyname함수를 사용하여 서비스 이름과 포트번호의 맵을 만들 수 있다. ; 11. 5. 4절 [서비스 데이터베이스] 을 보라.

만약 데이터베이스 안에 정의된 표준 중의 하나가 아닌 서버를 작성하려면, 그것을 위한 포트번호를 선택해야 한다. IPPORT_USERRESERVED 보다 더 큰 숫자를 사용하라. 어떤 번호들은 서버들을 위해 예약되어 있고 시스템에 의해 자동으로 생성되지 않을 것이다. 다른 사용자들에 의한 서버사용과의 충돌을 피하는 것은 당신에게 달렸다.

당신이 그것의 주소를 명시하지 않고 소켓을 사용할 때, 시스템은 포트번호를 하나 생성한다. 이 번호는 IPPORT_RESERVED와 IPPORT_ USERRESERVED사이의 값이다.

인터넷에서, 같은 소켓주소(호스트 주소 + 포트주소)로 통신을 시도하지 않는다면, 같은 포트번호로 두 개의 다른 소켓을 가지는 것은 실제로 적당한 방법이다. 상위프로토콜이 그것을 요구할 때, 특별한 상황을 기대하고 같은 포트번호를 복사하지 말아라. 보통, 시스템은 그러한 일을 수행하지 않을 것이다. bind는 보통 다른 포트번호를 요구한다. 포트번호를 다시 사용하기 위해서는, 소켓옵션 SO_REUSEADDR를 세트하라. 11. 11. 2절 [소켓-수준 옵션]을 보라.

다음 매크로들은 'netinet/in. h'에 정의되어 있다.

 int IPPORT__RESERVED 매크로

IPPORT_RESERVED 보다 작은 값의 포트는 슈퍼유저용으로 예약되어 있다.

int IPPORT__USERRESERVED 매크로

명백히 사용하기 위해 예약된, IPPORT_USERRESERVED보다 크거나 같은 포트이다. 그것들은 보통 자동으로 할당된다.

 

11. 5. 4 서비스 데이터베이스

유명한 서비스의 경로를 유지하는 데이터베이스는 보통 '/etc/services'파일이거나 네임서버의 동등한 파일이다. 이 서비스 데이터베이스를 억세스하기 위해 'netdb. h'에 선언되어 있는 다음 유틸리티들을 사용할 수 있다.

struct servent 자료형

이 자료형은 서비스 데이터베이스로부터의 항목에 관한 정보를 나타낸다.

char *s_name

이것은 서비스의 "공식적"인 이름이다.

char **s_aliases

문자열의 배열로 표현된 서비스의 또다른 이름들이다. 이 배열은 마지막에 널 포인터가 들어간다.

int s_port

이것은 서비스의 포트 번호이다. 포트번호는 네트워크 바이트 순서로 되어 있다. ; 11. 5. 5절 [바이트 순서]를 보라.

char *s_proto

이것은 이 서비스와 사용되는 프로토콜의 이름이다. 11. 5. 6절 [프로토콜 데이터베이스]을 보라.

특정한 서비스에 관한 정보를 얻으려면, getservbyname이나 getservby port 함수를 사용하라. 이 정보는 정적으로 할당된 구조체 안으로 반환된다. 즉 그것을 여러 번 호출하는 것으로부터 보호하려면 그 정보를 복사해 놓아야만 한다.

struct servent * getservbyname (const char *name, const char *proto) 함수

getservbyname함수는 name이라고 proto라는 프로토콜을 사용하고 이름지어진 서비스에 관한 정보를 반환한다. 만약 그러한 서비스를 찾지 못하면, 널 포인터를 반환한다.
이 함수는 클라이언트들뿐만 아니라 서버들에서도 유용하다. 서버에서는 듣고자 할 때 어떤 포트를 사용할 것인가를 결정할 때, 이 함수를 사용한다. (듣는 것에 관하여서는 11. 8. 2절[듣기] 을 보라)

struct servent * getservbyport (int port, const char *proto) 함수

getservbyport함수는 proto프로토콜을 사용하고 port라는 포트를 사용하는 서비스에 관한 정보를 반환한다. 당신은 또한 setservent, getservent, endservent를 사용하여 서비스 데이터베이스를 조사할 수 있다. 이러한 함수들은 재진 입성을 가지지 않기 때문에, 사용할 때 주의해야 한다.

void setservent (int stayopen) 함수

이 함수는 당신이 조사하려는 서비스 데이터베이스를 연다.
만약 stayopen 인수가 0이 아니면, getservbyname또는 getservbyport를 다음에 호출을 하였을 때 데이터베이스를 닫지 않도록(보통은 닫는다), 플래그를 세트한다. 여러 번의 호출이 데이터베이스를 여러 번 열지 않도록 할 때, 이것은 더욱 효율적이다.

struct servent * getservent (void) 함수

이 함수는 서비스 데이터베이스 안의 다음 항목을 반환한다. 만약 더 이상의 항목이 없으면, 널 포인터를 반환한다.

void vndservent (void) 함수

이 함수는 서비스 데이터베이스를 닫는다.

11. 5. 5 바이트 순서 변환

컴퓨터의 종류가 틀리면, 한 워드 내에서 바이트의 순서가 틀리게 사용 될 수 있다. 어떤 컴퓨터들은 워드안에 상위 바이트가 먼저 오기도 하고 (이를 "큰 종결자(big-endian)"라 부른다), 다른 것들은 상위 바이트가 나중에 오기도 한다. (이를 "작은 종결자(little-endian)"라 한다)

다른 바이트 수를 사용하는 장치들이 통신하기 위해, 인터넷 프로토콜들은 네트워크 상에서 전송되는 데이터를 위해 규정된 바이트 수 명시하고 있다.

인터넷 소켓 연결을 설정할 때, 당신은 sockaddr_in구조체의 sin_port와 sin_addr멤버를 네트워크 바이트 수로 표현해야만 한다. 소켓을 통해 전송되는 정수 데이터를 코딩할 때 역시 그것을 네트워크 바이트 순서로 변환해야 한다. 만약 그렇게 하지 않는다면, 프로그램은 다른 종류의 장치와 통신을 하는데 실패할 것이다.

포트번호나 호스트 주소를 얻기 위해 getservbyname, gethostbyname, inet_addr를 사용한다면, 사용되는 값들은 이미 네트워크 바이트 순서로 되어 있는 것이다. 당신은 그것들을 sockaddr_in에 직접 복사할 수 있다.

그렇지 않은 경우, 값들을 정확히 변환하지 않으면 안 된다. sin_port멤버로 사용하기 위해 htons와 ntohs를 사용하여 값들을 변환하라. sin_addr멤버로 사용하기 위해 htonl과 ntohl를 사용하여 값들을 변환하라. (struct in_addr은 unsigned long int와 같은 것임을 기억하라) 이러한 함수들은 'netinet/in. h'안에 선언되어 있다.

unsigned short inthtons (unsigned short int hostshort) 함수

이 함수는 호스트 바이트 수 된 short형 정수 hostshort를 네트워크 바이트 순서로 변환한다.

unsigned short int ntohs (unsigned short int netshort) 함수

이 함수는 네트워크 바이트 수 된 short형 정수 netshort를 호스트바이트순서로 변환한다.

unsigned long int htonl (unsigned long int hostlong ) 함수

이 함수는 호스트 바이트순서로된 long형 정수 hostlong을 네트워크 바이트 수 변환한다.

unsigned long int ntohl (unsigned long int netlong ) 함수

이 함수는 네트워크 바이트 수 된 long형 정수 netlong을 호스트 바이트 수 변환한다.

 

11. 5. 6 프로토콜 데이터베이스

소켓에서 사용되는 통신 프로토콜은 어떻게 데이터를 교환할 것인가에 대한 저수준 세부사항을 제어한다. 예를 들면, 프로토콜은, 전송상의 에러검출을 위한 검사합계(checksum)같은 것이나, 메시지의 경로설정 명령 같은 것들을 구현한다. 일반 사용자 프로그램들은 이러한 세부사항들에 대해서 직접적인 영향을 받지는 않는다.

인터넷 이름공간의 기본 통신 프로토콜은 통신스타일에 의존한다. 스트림 통신의 기본 프로토콜은 TCP("전송 제어 프로토콜")이다. 데이터그램 통신의 기본 프로토콜은 UDP("유저 데이터그램 프로토콜")이다. 신뢰성 있는 데이터그램 통신의 기본 프로토콜은 RDP("신뢰성 있는 데이터그램 프로토콜")이다. 당신은 아마 거의 대부분 기본 프로토콜을 사용할 것이다.

인터넷 프로토콜은 일반적으로 숫자 대신 이름으로 명시된다. 호스트가 알고 있는 네트워크 프로토콜은 데이터베이스 안에 저장되어 있다. 이것은 보통 '/etc/protocols'파일 이에서 얻어지거나 , 네임서버에 의해 동등하게 제공될 수 있다. 당신은 getprotobyname함수를 사용하여 데이터베이스 내에서 프로토콜 이름에 연계된 프로토콜 번호를 찾아 낼 수 있다.

여기에 프로토콜 데이터베이스를 억세스하기 위한 유틸리티들의 자세한 정의가 있다. 이것들은 'netdb. h'에 선언되어 있다.

struct protoent 자료형

이 자료형은 네트워크 프로토콜 데이터베이스의 항목들을 표현하는데 사용된다. 그것은 다음 멤버를 가진다.

char *p_name

이것은 프로토콜의 공식적인 이름이다.

char **p_aliases

이것들은 프로토콜의 또다른 이름들이다. 문자열의 배열로 되어 있으며, 배열의 마지막 요소는 널 포인터이다.

int p_proto

이것은 (호스트 바이트 수 된) 프로토콜 번호이다. 소켓의 protocol인수로 이 멤버를 사용하라

구체적인 프로토콜에 관하여 프로토콜 데이터베이스를 검색하기 위해 getprotobyname과 getprotobynumber를 사용할 수 있다. 정적으로 할당된 구조체에 정보가 반환된다. 여러 번 호출되는 것으로부터 정보를 보호하기 위해 그것을 복사해야 놓아야 한다.

struct protoent * getprotobyname (const char *name) 함수

getprotobyname함수는 name이라는 이름의 네트워크프로토콜에 관한 정보를 반환한다. 만약 같은 이름의 프로토콜이 없으면, 널 포인터를 반환한다.

struct protoent * getprotobynumber (int protocol) 함수

getprotobynumber함수는 protocol이라는 숫자를 가진 네트워크 프로토콜에 관한 정보를 반환한다. 만약 이러한 프로토콜이 없다면 널 포인터를 반환한다. setprotoent, getprotoent, endprotoent를 사용하여 전체 프로토콜 데이터베이스를 한 번에 한 프로토콜씩 조사할 수 있다. 이들 함수는 재진 입성을 가지지 않기 때문에 주의해서 사용해야 한다.

void setprotoent (int stayopen) 함수

이 함수는 검색을 위해 프로토콜 데이터베이스를 연다. 만약 stayopen인수가 0이 아니면, getprotobyname 또는 getproto-bynumber의 호출이 데이터베이스를 (보통 닫는데) 닫지 않도록 플래그를 세트한다. 이것은 여러 번의 호출로 데이터베이스가 여러 번 열리지 않도록 하는데 더욱 유용하다

struct protoent * getprotoent (void) 함수

이 함수는 프로토콜 데이터베이스의 다음 정보를 반환한다. 만약 더 이상의 항목이 없으면 널 포인터를 반환한다.

void endprotoent (void) Function

이 함수는 프로토콜 데이터베이스를 닫는다.

11. 5. 7 인터넷 소켓 예제

여기에 인터넷 이름공간 안에 소켓을 만들고 이름짓는 방법을 보여주는 예제가 있다. 프로그램이 수행되는 장치에 새로 소켓이 만들어진다.

장치의 인터넷 주소를 찾고 사용하는 것 대신, 호스트 주소에는 INADDR_ANY를 명시하였다. 시스템은 장치의 실제주소로 그것을 대치한다.

#include <stdio. h>
#include <stdlib. h>
#include <sys/socket. h>
#include <netinet/in. h>
int
make_socket (unsigned short int port)
{
int sock;
struct sockaddr_in name;
/* 소켓을 만든다 */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror ("socket");
exit (EXIT_FAILURE);
}
/* 소켓에 이름을 준다 */
name. sin_family= AF_INET;
name. sin_port = htons (port);
name. sin_addr. s_addr = htonl (INADDR_ANY);
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
{
perror ("bind");
exit (EXIT_FAILURE);
}
return sock;
}
여기에 또다른 예제가 있다. 이것은 주어진 호스트 이름문자열과 포트번호를 sockaddr_in구조체 안에 어떻게 넣는 지를 보여준다:
#include <stdio. h>
#include <stdlib. h>
#include <sys/socket. h>
#include <netinet/in. h>
#include <netdb. h>
void
init_sockaddr (struct sockaddr_in *name, const char *hostname,
unsigned short int port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL) {
fprintf (stderr, "Unknown host %s. \n", hostname);
exit (EXIT_FAILURE);
}
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
}


11. 6 다름 이름공간들

다른 이름공간과 프로토콜패밀리들도 지원되지만 별로 사용되지 않으므로 아직 문서화되지 않았다. PF_NS는 Xerox 네트워크 소프트웨어 프로 콜에 관련된 것이다. PF_ISO 는 개방시스템상호연결(OSI)에 관련된 것이다. PF_CCITT는 CCITT의 프로토콜들에 관련된 것이다. 'socket. h'에 실제로 구현되지 않은 기호와 다른 이름의 프로토콜이 정의되어 있다.

PF_IMPLINK는 호스트와 인터넷 메시지 처리기와의 통신에 사용된다. 이에 관한 정보와 가끔 사용되는 지역 경로설정 프로토콜인 PF_ROUTE에 관하여는 (미래에 나올) GNU Hurd Manual을 보라.


11. 7 소켓 열고 닫기

이 절에서는 소켓을 열고 다는 실제적인 라이브러리 함수에 관하여 서술한다. 모든 이름공간과 연결스타일에 대해 같은 함수가 사용된다.

11. 7. 1 소켓 만들기

소켓을 만들기 위해서는 'sys/socket. h'에 선언되어 있는 소켓함수를 사용한다.

int socket (int namespace, int style, int protocol) 함수

이 함수는 소켓을 만들고 통신스타일 style을 명시한다. 통신스타일은 11. 2절[통신스타일4] 에 열거된 소켓 스타일중 하나를 사용하여야 한다. namespace인수는 이름공간을 명시하고, PF_FILE이거나 PF_INET이어야 한다( 11. 4절[파일 이름공간], 11. 5절[인터넷 이름공간]을 보라). protocol은 프로토콜을 정한다 (11. 1절 [소켓개념]을 보라); protocol에는 보통 0이 사용된다.
socket으로부터의 반환 값은 새로운 소켓의 파일서술자이다. 에러가 발생하면 -1이 반환된다.
다음은 이 함수가 정의해 놓은 에러 상황 errno이다:

EPROTONOSUPPORT

The protocol or style is not supported by the namespace specified.

EMFILE : 프로세스가 이미 너무 많은 파일서술자들을 열어 놓았다.

ENFILE : 시스템이 이미 너무 많은 파일서술자들을 열어 놓았다.

EACCESS : 프로세스가 명시된 style이나 protocol에 맞는 소켓을 만들 권한을 갖고 있지 않다.

ENOBUFS : 시스템 내부 버퍼 공간이 부족하다.

socket 함수에 의해 반환되는 파일서술자는 읽기와 쓰기 기능 모두를 지원한다. 그러나 파이프 같은 소켓들은 파일 위치에 관한 동작은 하지 못한다. socket함수를 어떻게 호출하는 지에 대한 예는 11. 4절 [파일 이름공간], 또는 11. 5. 7절 [Inet 예제]을 보라.


11. 7. 2 소켓 닫기

소켓의 사용이 끝나면, 간단히 그 파일서술자를 close함수를 이용해 닫으면 된다. 8. 1절 [파일 열고 닫기]을 보라. 만약 연결을 통하여 전송되기를 기다리는 데이터가 여전히 있으면, 보통 close는 이 전송이 완료되도록 시도한다. SO_LINGER소켓 옵션을 사용하여 시간제한 주기를 명시해 주면, 이 과정을 제어할 수 있다. 11. 11절 [소켓 옵션] 을 보라.

당신은 'sys/socket. h'에 서술되어 있는 shutdown을 호출하므로 써 연결하의 송신만 또는 수신만을 종료시킬 수 있다.

int shutdown (int socket, int how ) 함수

shutdown함수는 socket이라는 소켓의 연결을 종료시킨다. how인수는 어떤 기능을 수행할 것인가를 명시한다.
0. 이 소켓으로부터 데이터 수신을 중단한다. 만약 더 이상의 데이터가 도착하면, 그것을 무시한다.
1. 이 소켓으로의 전송을 중단한다. 보내기 위해 대기중인 데이터는 취소된다. 이미 보낸 데이터의 응답을 기다리는 것도 중단한다. 만약 그것을 잃어버릴지라도 재전송하지 않는다.
2. 수신과 송신 모두를 중단한다.
성공하면 반환 값이 0이고, 실패면 -1이다. 다음은 이 함수에 정의되어 있는 errno 에러 상 황이다.
EBADF : socket이 유효한 파일 서술자가 아니다.
ENOTSOCK : socket이 소켓이 아니다.
ENOTCONN : socket이 연결되어 있지 않다

11. 7. 3 소켓 쌍

소켓 쌍은 연결된 (그러나 이름없는) 소켓의 쌍으로 구성된다. 그것은 pipe와 유사하고 무척 같은 방법으로 사용된다. 소켓 쌍은 'sys/socket. h'에 선언된 socketpair함수로 만들어진다. 소켓 쌍은 파이프와 대단히 유사하다:

주된 차이점은 소켓 쌍은 양방향이라는 것이다. 파이프는 하나의 입력만 되는 쪽과 출력만 되는 한 쪽만을 가지고 있다. (10장[Pipe와 FIFO]를 보라 )

int socketpair (int namespace, int style, int protocol, int filedes[2]) 함수

이 함수는 소켓 쌍을 만들며, filedes[0]과 filedes[1]안에 파일서술자를 반환한다. 소켓 쌍은 전이중(full-duplex)성 통신 채널이기 때문에 한쪽에서 읽거나 쓰기가 가능하다. namespace, style, protocol인자는 socket함수에서처럼 해석된다. style은 11. 2절[통신스타일]에 나열된 것이다. namespace인자는 이름공간을 명시하며, 반드시 AF_FILE이어야 한다. (11. 4절[파일이름공간] 을 참조하라); protocol은 통신 프로토콜을 서술하고 0도 의미 있는 값이다. 만약 style 이 비연결 통신스타일을 명시하면, 당신이 얻게 되는 두 소켓은 연결되지 않는다. 엄밀히 말해, 그들 각각은 서로의 목적지 주소를 알고 있어, 서로에게 패킷을 보낼 수 있게 된다.
socketpair함수는 성공시에 0을, 실패시에 -1을 반환한다. 다음은 이 함수에 정의되어 있는 errno에러 상황이다:

EMFILE : 프로세스가 너무 많은 파일 서술자를 열어 놓고 있다.

EAFNOSUPPORT : 명시된 이름공간이 지원되지 않는 것이다.

EPROTONOSUPPORT : 명시된 프로토콜이 지원되지 않는 것이다.

EOPNOTSUPP 명시된 : 프로토콜이 소켓 쌍을 만드는 것을 지원하지 않는다.


11. 8 연결하는데 소켓사용

대부분의 통신 스타일은 특정한 다른 소켓과 연결을 만들고 소켓과 소켓을 통하여 데이터를 교환한다. 연결을 만드는 것은 비대칭이다. ; 한쪽(클라이언트)은 다른 쪽(서버)이 소켓을 만들고 연결요구를 기다릴 때까지 연결을 요구하도록 되어 있다.

11. 8. 1절 [연결하기] 은 클라이언트 프로그램이 서버와 연결을 초기화하기 위해 무엇을 해야 하는지를 서술한다.

11. 8. 2절 [듣기]11. 8. 3[연결을 수락하기] 에서는 서버 프로그램이 클라이언트로부터 연결요구를 기다리고 받아들이는 것에 대한 서술을 한다.

11. 8. 5[데이터전송]은 어떻게 연결된 소켓을 통하여 데이터를 전송하는 방법을 서술한다.


11. 8. 1 연결 만들기

연결을 만들 때, 클라이언트는 서버가 연결을 기다리고 수락하는 동안 연결을 만들어야 한다. 여기에 클라이언트가 'sys/socket. h'에 선언된 connect함수를 이용하여 무엇을 해야 할 것인지를 논의하고 있다.

int connect (int socket, struct sockaddr *addr, size_t length) 함수

connect함수는 addr와 length의 길이로 명시된 주소를 가지는 소켓의 socket이라는 파일서술자를 이용하여 소켓으로부터 연결을 초기화 한다. (이 소켓은 전형적으로 다른 장치의 것이다. 그것은 서버처럼 이미 설정되어야 한다. ) 이 인수들이 어떻게 해석되는지에 관한 정보는 11. 3절[소켓주소]을 보라
보통, connect는 서버가 요구에 응답할 때까지 기다린 후 반환하게 된다. 응답을 기다리지 않고 즉시 반환하도록 소켓 socket을 블록킹되지 않도록(non-blocking) 설정할 수 있다. 블록킹되지 않는 모드에 관한 정보는 8. 10절 [파일 상태 플랙]을 보라.
connect로부터의 반환치는 보통 0이다. 만약 에러가 발생 시에는 -1을 반환한다.  
이 함수에 선언되어 있는 errno에러 상황은 다음과 같다.

EBADF : 소켓socket이 유효한 파일 서술자가 아니다.

ENOTSOCK : 소켓socket이 소켓이 아니다.

EADDRNOTAVAIL : 명시된 주소가 원격장치(상대방기기)에 사용할 수 없는 것이다.

EAFNOSUPPORT : addr의 이름공간이 이 소켓에서 지원하지 않는 것이다.

EISCONN : 소켓socket이 이미 연결되어 있다.

ETIMEDOUT : 연결설정을 시도하다가 시간을 초과하였다.

ECONNREFUSED : 서버가 연결설정을 직접 거절하였다.

ENETUNREACH : 주어진 addr의 네트워크는 이 호스트로부터 도달할 수 없다.

EADDRINUSE : 주어진 addr의 소켓주소가 이미 사용 중이다.

EINPROGRESS : 소켓socket이 블록 킹되지 않는 것이고, 연결을 즉시 설정할 수 없었다.

EALREADY : 소켓socket이 블록 킹되지 않는 것이고, 이미 진행중인 미결정의 연결이 있다.


11. 8. 2 연결 듣기

이제 서버프로세스가 소켓에서 연결을 수락하기 위해 무엇을 해야 하는지 고려해보자. 이것은 listen함수를 사용하여 소켓에서 연결요구를 가능하게 하고 나서, accept함수 (11. 8. 3절 [연결수락]을 보라)를 사용하여 요구를 받아들이는 것을 포함한다. listen함수는 비연결 통신 스타일을 지원하지 않는다. 연결 요구가 있을 때까지 수행을 시작하지 않도록 네트워크 서버를 작성할 수 있다. 11. 10. 1절[Inetd 서버들]을 보라.

인터넷 이름공간에서, 한 포트로의 연결에 접근을 제어하는 보호 메커니즘이 없다. 어떤 장치에서 어떤 프로세스가 당신의 서버에 연결을 만들 수 있다. 만약 당신이 당신의 서버에 접근을 제어하기를 원한다면, 연결요구에 연계된 주소를 검사하거나, 다른 협상과정이나 식별기능이 있는 프로토콜을 구현하면 된다.

파일 이름공간에서, 보통 파일 보호 비트는 소켓 연결에 접근하는 사람을 제어할 수 있다.

int listen (int socket, unsigned int n) 함수

listen함수는 소켓socket을 연결을 수락이 가능하도록 하여, 그것을 서버소켓으로 만든다.
인수 n은 미결된 연결의 큐의 길이를 명시한다.
listen함수는 성공시에 0을 실패시 -1을 반환하며, 이 함수에 정의된 errno에러 상황은 다음과 같다.

EBADF : 인수socket는 유효한 파일서술자가 아니다.

ENOTSOCK : 인수socket이 소켓이 아니다.

EOPNOTSUPP : 소켓socket는 이 기능을 지원하지 않는다.


11. 8. 3 연결 수락

서버가 연결요구를 수신하였을 때, 연결요구를 수락함으로써 연결이 끝날 수 있다. accept함수를 사용하여 그것을 수행한다. 서버로 설정된 소켓은 여러 클라이언트로부터의 연결요구를 수락할 수 있다. 서버의 원 소켓(original socket)은 연결의 부분이 되지 않는다. 대신에, accept는 연결에 특정한 새로운 소켓을 만든다. accpect는 이 소켓에 대한 서술자를 반환한다. 서버의 원 소켓은 다음 연결요구를 듣기 위하여 계속 남아있다.

서버소켓의 비결된 연결요구의 수는 제한되어 있다. 만약 클라이언트들로 부터의 연결 요구가 서버가 그것을 처리할 수 있는 거 보다 더 빠르다면, 큐가 가득 채워 질 것이고, 추가적인 요구는 ECONNREFUSED에러로 거절된다. 비록 시스템 내부의 큐가 제한되어 있을 지라도 listen함수의 인수로 이 큐의 최대 길이를 명시할 수 있다.

int accept (int socket, struct sockaddr *addr, size_t *length_ptr) 함수

이 함수는 서버소켓 socket의 연결요구를 수락하는데 사용된다. 만약 미결된 연결이 없고 소켓socket이 블록킹되도록 세트되어있으면 accept함수는 계속 기다린다. (블록킹 안되는 소켓으로 기다리게 하도록 선택할 수도 있다. ) 블록킹 안되는 모드에 관한 정보는 8. 10절 [파일 상태 플랙] 을 보라. addr과 length_ptr인수는 초기화된 연결의 클라이언트 소켓의 이름에 관한 정보를 반환하는데 사용된다. 11. 3절 [소켓주소]에 정보포맷에 관한 정보가 있다. 연결을 수락하는 것은 socket부분을 연결의 일부로 만들지 않는다. 대신에, 연결될 새로운 소켓을 생성한다.
accept의 정상적인 반환치는 새로운 소켓의 파일서술자이다. accept후에, 원래의 소켓인 socket은 열려 있고, 연결되지 않은 상태로 남아있게 된다. 그리고 그것이 닫힐 때까지 듣기를 계속할 것이다. accept를 호출하여 이 소켓을 통하여 추가적인 연결을 수락할 수 있다.
만약 에러가 발생하면 accept는 -1을 반환한다.
다음은 이 함수에 정의되어 있는 errno에러조건이다:

EBADF : socket인수가 유효한 파일서술자가 아니다.

ENOTSOCK : 서술자 socket인수가 소켓이 아니다.

EOPNOTSUPP : 서술자 socket이 이 기능을 지원하지 않는다.

EWOULDBLOCK : socket이 블록킹안되는 모드로 세트되어 있고, 즉시 연결될 수 있는 미결의 연결이 없다.

accept함수는 비연결성 통신 스타일의 소켓에는 사용될 수 없다.


11. 8. 4 누가 나에게 연결되어 있나

int getpeername (int socket, struct sockaddr *addr, size_t *length_ptr) 함수

getpeername함수는 socket이 연결되어 있는 소켓의 주소를 반환한다; addr과 lengh_ptr에 의해 명시된 메모리 공간에 그 주소가 저장된다. *length_ptr안에 주소의 길이를 저장한다.
주소의 포맷에 관하여는 11. 3절 [소켓 주소]을 보라. 어떤 운영체제에서, getpeername은 단지 인터넷 도메인의 소켓에서만 동작한다.
성공시에 0을 실패시에 -1을 반환한다. 다음은 이 함수에 정의된 errno에러조건이다:

EBADF : socket인수가 유효한 파일 서술자가 아니다.

ENOTSOCK : socket서술자가 소켓이 아니다.

ENOTCONN : socket소켓이 연결되어 있지 않다.

ENOBUFS : 충분한 내부 버퍼가 없다.


11. 8. 5 데이터 전송

일단 소켓이 상대측과 연결이 되면, 데이터를 전송하는 일반적인 write와 read 동작을 수행할 수 있다. (8. 2절 [I/O 추상]을 보라) 소켓은 양방향 채널이므로 한쪽에서 읽고 쓰기가 가능하다. 소켓의 동작을 명시하는 몇 가지 I/O모드가 있다. 그러한 모드를 명시하려면, 더 일반적인 read와 write대신에 recv와 send 함수를 사용해야 한다. recv와 send함수는 특별한 I/O모드를 제어하기 위한 여러 가지 플랙을 명시하는데 사용되는 추가적인 인수를 필요로 한다. 예를 들어 out-of-band 데이터를 읽거나 쓰기 위하여 MSG_OOB플랙을 명시할 수 있고, 입력을 엿보기 위하여 MSG_PEEK를 세트하거나, 출력시 라우팅정보의 포함을 제어하기 위하여 MSG_DONTROUTE플랙을 명시할 수 있다.


11. 8. 5. 1 데이터 보내기

send함수는 'sys/socket. h'에 선언되어 있다. 만약 flag인수를 0으로 하는 경우면, send대신에 write를 쓸 수 있다. 8. 2절 [I/O 추상]을 보라. 만약 소켓이 연결되어 있는 상태라면, send나 write를 사용할 때 SIGPIPE라는 시그널을 얻을 것이다. (21. 2. 6절 [여러 가지 시그널]을 보라)

int send (int socket, void *buffer, size_t size, int flags) 함수

send함수는 write와 비슷하지만, 추가적인 flags라는 플랙을 가지고 있다. flags에 가능한 값들은 11. 8. 5. 3절[소켓 데이터 옵션]에 서술되어 있다. 이 함수는 전송된 바이트의 수를 반환하며, 실패시 -1을 반환한다. 만약 소켓이 블록 킹되지 않는 모드라면, send가 (write처럼) 데이터의 일부만 전송한 뒤 반환될 것이다. 블록 킹되지 않는 모드에 관하여는 8. 10절 [파일 상태 플랙] 을 보라. 어쨌거나, 성공시의 반환치는 에러 없이 전송된 메시지를 가리킬 뿐, 에러 없이 수신되는 것처럼 필수적인 것이 아님에 주의하라.
다음은 이 함수에 정의된 errno에러 조건이다.

EBADF : socket인수가 유효한 파일 서술자가 아니다.

EINTR

데이터를 보내기 전에, 시그널에 의해 인터럽트가 걸렸다. 21. 5절 [인터럽트 추상]을 보라.

ENOTSOCK : socket서술자가 소켓이 아니다.

EMSGSIZE : 소켓종류가 메시지를 작게 보낼 것을 요구하는데, 이 메시지가 너무 크다.

EWOULDBLOCK

블록 킹되지 않는 모드가 소켓에 세트되어 있으나, 쓰기 동작이 블록 킹될 것이다. (보통 send는 동작이 끝날 수 있을 때까지 블록 킹된다. )

ENOBUFS : 충분한 내부버퍼공간이 없다.

ENOTCONN : 당신은 이 소켓에 연결되어 있지 않다.

EPIPE

이 소켓은 연결되어 있지만, 연결이 깨져있다. 이 경우 send는 SIGPIPE시그널을 먼저 생성한다. 만약 시그널이 무시되거나 블록 킹되거나, 핸들러가 반환된다면, send는 EPIPE로 실패를 알리게 된다.

11. 8. 5. 2 데이터 수신하기

recv함수는 'sys/socket. h' 헤더 파일에 선언되어 있다. 만약 flags인수가 0이면 recv대신에 read를 써도 된다. 8. 2절 [I/O추상] 을 참조하라.

int recv (int socket, void *buffer, size_t size, int flags) 함수

recv함수는 read와 유사하지만, 추가적으로 flags라는 플랙을 가지고 있다. flags에 가능한 값은 11. 8. 5. 3절 [소켓 데이터 옵션] 에 서술되어 있다.
만약 블록 킹되지 않는 모드로 소켓에 세트되어 있고, 읽을 데이터가 없으면, recv는 기다리지 않고 즉시 실패로 끝난다. 블록 킹하다 않는 모드에 관한 정보는 8. 10절 [파일 상태 플랙]을 보라.
이 함수는 수신된 바이트 수를 반환하거나, 실패시 -1을 반환한다.
다음은 이 함수에 선언된 errno에러 조건이다.

EBADF : socket인수가 유효한 파일서술자가 아니다.

ENOTSOCK : socket서술자가 소켓이 아니다.

EWOULDBLOCK

소켓에 블록 킹하다 않는 모드가 세트되어 있고, 읽기 동작이 블록될 것이다. (보통 recv는 읽기 가능한 입력이 있을 때까지 블럭킹된다. )

EINTR

데이터를 읽기도 전에 시스널에 의해 인터럽트가 걸렸다. 21. 5절[인터럽트 추상]을 보라.

ENOTCONN : 당신은 이 소켓에 연결되어 있지 않다.


11. 8. 5. 3 소켓 데이터 옵션

send와 recv에 사용되는 flags인수는 비트마스크이다. 당신은 이 인수에 값을 얻기 위해 아래 매크로로 비트별-OR연산을 수행할 수 있다. 'sys/socket. h'헤더파일에 모두 정의되어 있다.

int MSG__OOB 매크로

out-of-band데이터를 송신하거나 수신한다. 11. 8. 8절 [Out-of-band 데이터]을 보라.

int MSG__PEEK 매크로

수신된 큐로부터 데이터를 보기만 하고 그것을 지우지는 말아라. 이것은 send가 아닌 recv같은 입력함수에서만 의미가 있다. send.

int MSG__DONTROUTE 매크로

이 메시지에 라우팅정보를 포함하지 마라. 이것은 출력 함수에서만 의미를 갖는다. 그리고 분석이나 라우팅 프로그램에서만 흥미롭게 사용된다. 그것에 대하여는 여기서 더 이상 설명하지 않는다.

11. 8. 6 Byte Stream 소켓 예제

이것은 인터넷 이름공간의 byte stream을 위한 연결을 만드는 프로그램의 예제이다. 한 번 서버에 연결하고 특별한 일을 하지 않는다. 그것은 단지 텍스트 문자열을 서버에게 보내고 종료한다.

#include <stdio. h>
#include <errno. h>
#include <stdlib. h>
#include <unistd. h>
#include <sys/types. h>
#include <sys/socket. h>
#include <netinet/in. h>
#include <netdb. h>
#define PORT 5555
#define MESSAGE "Yow!!! Are we having fun yet?!?"
#define SERVERHOST "churchy. gnu. ai. mit. edu"
void
write_to_server (int filedes)
{
int nbytes;
nbytes =write (filedes, MESSAGE, strlen (MESSAGE) + 1);
if (nbytes < 0) {
perror ("write");
exit (EXIT_FAILURE);
}
}
int
main (void)
{
extern void init_sockaddr (struct sockaddr_in *name,
const char *hostname,
unsigned short int port);
int sock;
struct sockaddr_in servername;
/* 소켓 만들기 */
if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
perror ("socket (client)");
exit (EXIT_FAILURE);
}
/* 서버에 연결 */
init_sockaddr (&servername, SERVERHOST, PORT);
if (connect (sock,(struct sockaddr *) &servername,sizeof (servername)) < 0) {
perror ("connect (client)");
exit (EXIT_FAILURE);
}
/* 서버에 데이터 보내기 */
write_to_server (sock);
close (sock);
exit (EXIT_SUCCESS);
}

11. 8. 7 Byte Stream Connection 서버 예제

서버 쪽은 좀더 복잡하다. 여러 클라이언트가 동시에 서버에 연결할 수 있도록 하기를 원하므로, 간단히 하나의 read나 recv를 호출하여 하나의 클라이언트로부터 입력을 기다려서는 안 된다. 대신에, 모든 열린 소켓으로부터 입력을 기다리도록(8. 6절 [I/O 기다리기]), select를 사용하는 것이 올바른 것이다. 이것은 또한 추가적인 연결 요구를 다루도록 허락한다.

이 특별한 서버는 클라이언트로부터 메시지를 한 번 받는 다는 것 외에 특별히 흥미로운 일을 하지 않는다. 그것은 (클라이언트가 연결을 종료하는 결과로써) 파일의 끝(end-of-file)조건을 검출하였을 때, 그 클라이언트에 대한 소켓을 닫는다.

이 프로그램은 소켓주소를 세트하기 위해 make_socket과 init_sockaddr를 사용하였다. ; 11. 5. 7 [Inet 예제]을 보라

#include <stdio. h>
#include <errno. h>
#include <stdlib. h>
#include <unistd. h>
#include <sys/types. h>
#include <sys/socket. h>
#include <netinet/in. h>
#include <netdb. h>
#define PORT 5555
#define MAXMSG 512
int
read_from_client (int filedes)
{
char buffer[MAXMSG];
int nbytes;
nbytes = read (filedes, buffer, MAXMSG);
if (nbytes < 0) { /* 읽기 에러 */
perror ("read");
exit (EXIT_FAILURE);
} else if (nbytes == 0) /* 파일의 끝 */
return -1;
else { /* 데이터 읽기 */
fprintf (stderr, "Server: got message: `%s'\n", buffer);
return 0;
}
}
int
main (void)
{
extern int make_socket (unsigned short int port);
int sock;
int status;
fd_set active_fd_set, read_fd_set;
int i;
struct sockaddr_in clientname;
size_t size;
/* Create the socket and set it up to accept connections. */
sock = make_socket (PORT);
if (listen (sock, 1) < 0) {
perror ("listen");
exit (EXIT_FAILURE);
}
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sock, &active_fd_set);
while (1)
{
/* Block until input arrives on one or more active sockets. */
read_fd_set = active_fd_set;
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0)
{
perror ("select");
exit (EXIT_FAILURE);
}
/* Service all the sockets with input pending. */
for (i = 0; i < FD_SETSIZE; ++i) {
if (FD_ISSET (i, &read_fd_set)) {
if (i == sock) {
/* Connection request on original socket. */
size = sizeof (clientname);
if (accept (sock,(struct sockaddr *) &clientname, &size) < 0) {
perror ("accept");
exit (EXIT_FAILURE);
}
fprintf (stderr,
"Server: connect from host %s, port %hd. \n",
inet_ntoa (clientname. sin_addr),
ntohs (clientname. sin_port));
FD_SET (status, &active_fd_set);
} else {
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0) {
close (i);
FD_CLR (i, &active_fd_set);
}
} /* if 의 끝 */
} /* if 의 끝 */
} /* for 의 끝 */
} /* while 의 끝 */
} /* main 의 끝 */

11. 8. 8 Out-of-Band 데이터

연결을 가진 스트림은 일반 데이터보다 높은 우선 순위로 배달되는 데이터인 out-of-Band데이터를 가능하게 한다. 전형적으로 out-of-band데이터를 전송하는 이유는 예외적인 상황의 통보 때문이다. out-of-band데이터를 보내는 방법은 MSG_OOB플랙을 세트한 (11. 8. 5. 1절[데이터 전송]참고) send를 사용하는 것이다.

수신 프로세스가 순서대로 그것을 받지 않으므로, out-of-band 데이터는 더 높은 우선 순위로 받아진다. 즉, 다음 가능한 out-of-band 데이터를 읽으려면, MSG_OOB플랙을 세트하여 recv를 사용한다. (11. 8. 5. 2절 [데이터 수신]을 보라). 보통 읽기 명령은 out-of-band데이터를 읽지 않는다. 그것들은 단지 일반 데이터만 읽는다. 소켓이 out-of-band데이터가 있음을 알게 되면, 소유프로세스나 소켓의 프로세스 그룹에 SIGURG시그널을 보낸다. F_SETOWN명령으로 fcntl함수를 사용하여 소유자를 명시할 수 있다. 8. 12절 [인터럽트 입력]을 보라. 또한 이 시그널의 핸들러를 설정할 수 있는데, out-of-band데이터를 읽는 등의 적절한 동작을 취하기 위해, 21장[시그널 핸들링]을 보라.

다른 것으로, select함수를 사용하여, 미결의 out-of-data를 검사하거나 out-of-band데이터가 있을 때까지 기다릴 수 있다. ; 그것은 소켓 예외 조건을 기다릴 수 있다. select에 관한 많은 정보는 8. 6절 [I/O를 기다리기]을 보라.

(SIGURG를 사용하거나 select를 사용할 것이던지) out-of-band 데이터의 통고는 out-of-band데이터가 진행 중에 있음을 가리킨다. ; 즉 데이터는 아직 실제로 도착하지 않았다. 만약 그것이 완전히 도착하기 전에 out-of-data를 읽으려고 하면, recv 는 EWOULDBLOCK에러로 실패하게 된다.

out-of-band데이터 전송은 자동으로 일반 데이터의 흐름 안에 "마크"를 둔다. 그것은 어디에 out-of-band데이터가 어디에 있을지를 보여준다. out-of-band 데이터가 먼저 보내진 모든 것들을 취소시킨다는 의미를 가질 때 유용하다. 여기에 수신 프로세스에서 마크전에 보내진 보통 데이터인지 아닌지 어떻게 테스트하는지가 나와있다.

success = ioctl (socket, SIOCATMARK, &result);

이 함수는 out-of-band 마크 앞의 일반 데이터를 무시하는 것이다.
int
discard_until_mark (int socket)
{
while (1)
{
/* This is not an arbitrary limit; any size will do. */
char buffer[1024];
int result, success;
/* If we have reached the mark, return. */
success = ioctl (socket, SIOCATMARK, &result);
if (success < 0)
perror ("ioctl");
if (result)
return;
/* Otherwise, read a bunch of ordinary data and discard it This is guaranteed not to read past the mark if it starts before the mark. */
success = read (socket, buffer, sizeof buffer);
if (success < 0)
perror ("read");
}
}

만약 마크앞의 일반 데이터를 무시하지 않으려면, 그것을 어떻게든 읽기 위해, out-of-band데이터를 위한 내부시스템버퍼 공간을 만들어야 한다. 만약 out-of-band데이터를 읽으려 하는데 EWOULDBLOCK에러를 받는다면, 약간의 일반데이터를 (그것을 얻었을 때 사용할 수 있도록 저장을 하며) 읽기를 시도하라. 그리고 그것이 공간을 만드는지를 보아라. 여기 예제가 있다.

struct buffer
{
char *buffer;
int size;
struct buffer *next;
};
/* Read the out-of-band data from SOCKET and return it as a `struct buffer', which records the address of the data and its size.
It may be necessary to read some ordinary data in order to make room for the out-of-band data. If so, the ordinary data is saved as a chain of buffers found in the `next' field of the value. */
struct buffer *
read_oob (int socket)
{
struct buffer *tail = 0;
struct buffer *list = 0;
while (1) {
/* This is an arbitrary limit. Does anyone know how to do this without a limit? */
char *buffer = (char *) xmalloc (1024);
struct buffer *link;
intsuccess;
int result;
/* Try again to read the out-of-band data. */
success = recv (socket, buffer, sizeof buffer, MSG_OOB);
if (success >= 0) {
/* We got it, so return it. */
struct buffer *link
=(struct buffer*) xmalloc(sizeof(struct buffer));
link->buffer = buffer;
link->size = success;
link->next = list;
return link;
}
/* If we fail, see if we are at the mark. */
if (ioctl (socket, SIOCATMARK, &result) < 0)
perror ("ioctl");
if (result) {
/* At the mark; skipping past more ordinary data cannot help. So just wait a while. */
sleep (1);
continue;
}
/* Otherwise, read a bunch of ordinary data and save it. This is guaranteed not to read past the mark if it starts before the mark. */
if (read (socket, buffer, sizeof buffer) < 0) /* Save this data in the buffer list. */
{
struct buffer *link
= (struct buffer *) xmalloc(sizeof (struct buffer));
link->buffer = buffer;
link->size = success;
/* Add the new link to the end of the list. */
if (tail)
tail->next = link;
else
list = link;
tail = link;
} /* if 의 끝 */
} /* while 의 끝 */
}


11. 9 데이터그램 소켓 명령

이번 절에서는 어떻게 연결 없는 통신스타일(SOCK_DGRAM과 SOCK_RDM스타일)을 사용하는지에 대해 서술한다. 이러한 스타일을 사용하여 패킷 안에 데이터를 묶어 넣고, 각 패킷은 독립적인 통신을 하게 된다. 그리고 각 패킷마다 목적지를 명시해야 한다.

데이터그램 패킷은 편지와 같다. 당신은 개별적으로 하나씩 목적지를 명시하여 보낸다. 그것들은 순서가 바뀌어 도착할 수도 있다.

listen과 accept함수는 비연결 통신 스타일을 사용하는 소켓에서 사용할 수 없다.

11. 9. 1 데이터그램 전송

데이터그램소켓으로 데이터를 보내는 보통 방법은 'sys/socket. h'에 선언되어 있는 sendto함수를 사용하는 것이다. 데이터그램 소켓에 connect를 호출할 수 있지만, 나중에 데이터전송을 위해 기본경로를 한 번 명시한다. 소켓이 기본경로를 가지면, send를 사용할 수 있다. (11. 8. 5. 1절 [데이터 전송]을 보라) 또한 패킷을 전송하기 위해 write를 사용할 수 있다. (8. 2절 [I/O 추상] 을 보라) addr인수에 AF_UNSPEC의 주소포맷을 사용하여 connect를 호출함으로써 기본경로를 취소할 수 있다. connect함수에 관한 더 많은 정보는 11. 8. 1절 [연결하기] 을 보라.

int sendto (int socket, void *buffer size_t size, int flags, struct sockaddr *addr, size_t length) 함수

sendto함수는 목적지가 addr과 length인수로 명시되어 있는 socket을 통하여 버퍼에 있는 데이터를 전송한다. size인수는 전송할 바이트 수를 말한다.
flags는 send에서와 같은 방법으로 해석된다. 11. 8. 5. 3절 [소켓 데이터 옵션]을 보라.
반환치와 에러상태도 역시 send와 비슷하다. 그러나 시스템이 에러를 검출하게 할 수는 없다. 대부분의 에러는 패킷이 없어지거나 수신할 주소가 명시되어 있지 않은 것이다. 그래서 당신의 OS는 보통 에러가 난 것을 알지 못할 것이다. 예전의 호출에 관련된 문제 때문에 sendto는 에러가 났다고 할 수도 있다.

11. 9. 2 데이터그램 수신

recvfrom함수는 데이터그램 소켓으로부터 패킷을 읽고 또한 어디서부터 온 것인지 알려준다. 이 함수는 'sys/socket. h'에 선언되어 있다.

int recvfrom(int socket, void *buffer, size_t size, int flags, struct sockaddr *addr, size_t *length_ptr)함수

recvfrom함수는 socket소켓으로부터 패킷하나를 읽어 buffer라는 버퍼에 넣는다. size인수는 한 번 읽을 때 최대의 바이트 수이다. 만약 패킷이 size바이트보다 더 크면, 패킷의 앞부분만 얻을 수 있고 specify flags를 원하지 않으면 사용된다. (8. 2절[I/O Primitives]를 보라).
만약 (어디서부터 올 것인지 아는 경우, 누가 보냈던지 똑같이 취급하기 때문에) 누가 패킷을 보냈는지 알 필요가 없다면 recvfrom대신에 평탄한 recv를 쓸 수 있다. (11. 8. 5. 2절 [데이터 수신] 을 보라)

11. 9. 3 데이터그램 소켓 예제

여기에 파일이름공간의 데이터그램 스트림을 통해 메시지를 보내는 예제프로그램의 세트가 있다. 클라이언트와 서버프로그램들 모두가 소켓을 만들고 이름짓기 위하여, 11. 4절 [파일 이름공간]에 설명되어 있는 make_named_socket 함수를 사용한다.

먼저 여기 서버프로그램이 있다. 그것은 메시지가 도착할 때까지 계속 기다리고 메시지가 오면 다시 송신자에게 되돌려주는 것을 반복한다. 분명히 특별히 유용한 프로그램이 아니지만, 일반적인 아이디어를 보여준다.

#include <stdio. h>
#include <errno. h>
#include <stdlib. h>
#include <sys/socket. h>
#include <sys/un. h>
#define SERVER "/tmp/serversocket"
#define MAXMSG 512
int
main (void)
{
int sock;
char message[MAXMSG];
struct sockaddr_un name;
size_t size;
int nbytes;
/* Make the socket, then loop endlessly. */
sock = make_named_socket (SERVER);
while (1)
{
/* Wait for a datagram. */
size = sizeof (name);
nbytes = recvfrom (sock, message, MAXMSG, 0,
(struct sockaddr *) & name, &size);
if (nbytes < 0)
{
perror ("recfrom (server)");
exit (EXIT_FAILURE);
}
/* Give a diagnostic message. */
fprintf (stderr, "Server: got message: %s\n", message);
/* Bounce the message back to the sender. */
nbytes = sendto (sock, message, nbytes, 0, (struct sockaddr *) & name, size);
if (nbytes < 0)
{
perror ("sendto (server)");
exit (EXIT_FAILURE);
}
}
}

11. 9. 4 데이터그램 읽기 예제

여기 위에 있는 서버프로그램에 맞는 클라이언트 프로그램이 있다.

그것은 서버에게 데이터그램을 송신하고 나서 응답을 기다린다. 클라이언트를 위한 소켓에는 (서버와 같이) 주어진 이름을 가지고 있음을 주시하라. 그것은 서버가 메시지를 바로 클라이언트에게 되돌리게 한다. 소켓이 연계된 연결상태를 가지지 않기 때문에, 서버는 클라이언트의 이름을 참조하여 그렇게 할 수 있는 것이다.

#include <stdio. h>
#include <errno. h>
#include <unistd. h>
#include <stdlib. h>
#include <sys/socket. h>
#include <sys/un. h>
#define SERVER "/tmp/serversocket"
#define CLIENT "/tmp/mysocket"
#define MAXMSG 512
#define MESSAGE "Yow!!! Are we having fun yet?!?"
int
main (void)
{
externint make_named_socket (const char *name);
int sock;
char message[MAXMSG];
struct sockaddr_un name;
size_t size;
int nbytes;
/* Make the socket. */
sock = make_named_socket (CLIENT);
/* Initialize the server socket address. */
name. sun_family = AF_UNIX;
strcpy (name. sun_path, SERVER);
size = strlen (name. sun_path) + sizeof (name. sun_family);
/* Send the datagram. */
nbytes = sendto (sock, MESSAGE, strlen (MESSAGE) + 1, 0,
(struct sockaddr *) & name, size);
if (nbytes < 0) {
perror ("sendto (client)");
exit (EXIT_FAILURE);
}
/* Wait for a reply. */
nbytes = recvfrom (sock, message, MAXMSG, 0, NULL, 0);
if (nbytes < 0) {
perror ("recfrom (client)");
exit (EXIT_FAILURE);
}
/* Print a diagnostic message. */
fprintf (stderr, "Client: got message: %s\n", message);
/* Clean up. */
remove (CLIENT);
close (sock);
}

데이터그램소켓 통신은 비신뢰성임을 명심하라. 이 예제에서, 메시지가 서버에 도달하지 못하거나 서버가 응답을 하지 않을 지라도, 클라이언트 프로그램은 막연히 기다린다. 만약 원한다면, 그것을 종료시키고 리셋 시키는 프로그램을 유저가 수행하여야 한다. 자동적인 해결법은 select(8. 6절 [I/O기다리기])를 사용하여 응답의 시간제한을 설정하여, 시간제한이 초과되면 메시지를 재 전송하거나 소켓을 끝내고 종료하는 것이다.


11. 10 inetd 데몬

위에서 듣기를 하는 서버프로그램을 작성하는 법을 설명했다. 어떤 서버는 그것에 접속하기 위해 미리 수행되고 있어야 한다. 인터넷포트를 위한 서비스를 제공하는 다른 방법은 inetd 데몬 프로그램을 이용하여 듣기를 하도록 하는 것이다. inetd는 명시된 포트의 세트에서의 메시지를 (select를 사용하여) 기다리며 수행되는 프로그램이다. 그것이 메시지를 받았을 때, (만약 소켓스타일이 연결이 필요하면) 연결을 수락하고 나서, 해당 서버프로그램을 수행하도록 자식프로세스를 만들어 낸다. '/etc/inetd. conf'파일 내에 포트들과 프로그램들을 명시한다.


11. 10. 1 inetd 서버들

inetd에 의해 수행되는 서버프로그램을 작성하는 것은 매우 간단하다. 누군가 해당 포트로 연결을 연결하려는 때마다, 새로운 서버 프로세스가 시작된다. 연결은 단지 이 순간에만 존재한다. 소켓은 서버프로세스에서 표준 입력 서술자와 표준 출력 서술자 (서술자 0과 1)처럼 된다. 가끔은 프로그램이 일반적인 I/O기능을 필요로 할 때도 있다. ; 실제로, 소켓에 대해 아무 것도 모르는 범용 필터 프로그램도 inetd에 의해 바이트 스트림 서버처럼 동작할 수 있다.

비연결성 통신 스타일의 서버에도 inetd를 사용할 수 있다. 연결이 필요 없으므로, 이러한 서버들을 위해 inetd는 연결을 수락하려는 시도를 하지 않는다. 그것은 바로 서술자 0으로부터 수신된 데이터그램패킷을 읽을 수 있는 서버프로그램을 시작한다. 서버프로그램은 한 요구를 다룰 수 있고 종료할 수 있다. 또는 더 이상의 도착이 없을 때까지 요구를 읽는 것을 계속하고 나서 종료할 수도 있다. inetd를 설정할 때, 위의 두 가지 기술 중 어떤 것을 사용할 것인지 명시해야 한다.


11. 10. 2 inetd 설정

'/etc/inetd. conf'파일은 inetd에게 들을 포트번호와 수행될 서버프로그램이 무엇인지 말해준다. 보통 이 파일의 각 요소는 한 줄씩이다. 그러나, 그것을 화이트스페이스로 시작하는 요소의 첫 번째 줄을 제외한 모든 줄로 나눌 수 있다. '#'로 시작하는 줄은 주석 문이다.

여기 '/etc/inetd. conf'안의 두 기본적인 요소가 있다.

ftp stream tcp nowait root /libexec/ftpd ftpd
talk dgram udp wait root /libexec/talkd talkd

한 요소는 다음 형식을 가진다.

서비스 스타일 프로토콜 대기 사용자명 프로그램 인수

서비스 부분은 이 프로그램이 어떤 서비스를 제공하는 지를 말한다. 그것은 '/etc/services'안에 서비스의 이름이 정의되어 있을 것이다. inetd는 이 요소를 위해 들을 어떤 포트를 사용할 것인가 결정하는데 서비스를 사용한다.

스타일과 프로토콜 부분은 통신스타일과 소켓을 듣는데 사용되는 프로토콜을 명시한다. 스타일은 'SOCK_'이 빠지고, 소문자로 변환된 통신스타일의 이름이다. 예를 들면 stream 또는 dgram이다. 프로토콜은 '/etc/protocols'에 나열된 프로토콜 중 하나이다. 전형적인 프로토콜이름은 바이트 스트림 통신을 위한 'tcp'와 비신뢰성 데이터그램을 위한 'udp'가 있다.

대기 부분은 'wait' 또는 'nowait' 중 하나이다. 만약 통신스타일이 비연결성이고, 서버가 시작시에만 많은 다중 요구를 다룬다면 'wait'을 사용하라. 만약 inetd가 각 메시지나 요구가 들어 올 때마다 새로운 프로세스를 시작할 경우 'nowait'를 사용하라. 만약 스타일이 연결성이면 대기 부분은 'nowait'를 써라.

사용자명은 서버를 수행하는 사용자의 이름이다. inetd는 root로서 수행된다. 그래서 마음대로 그 자식의 사용자ID를 세트할 수 있다. 가능하면 사용자명에 'root'를 피하는 것이 좋다. ; 그러나 telnet과 ftp같은 어떤 서버는 사용자 이름과 암호를 읽는다. 이러한 서버들은, 네트워크로부터 오는 데이터에 의한 명령 같이 로그인 을 할 수 있도록 처음에 root가 될 필요가 있다.

프로그램 부분과 인수 부분은 서버를 시작할 때 수행되는 명령어를 명시한다. 프로그램은 수행 가능한 파일의 절대 경로의 파일이름이어야 한다. 인수는 화이트스페이스로 구분된 단어로 구성되어, 프로그램의 명령어라인 인수가 된다. 인수의 첫 번째 단어는 인수 0으로 (디렉토리 없이) 프로그램의 이름 그 자체로 된다.

만약 '/etc/inetd. conf'를 수정하면, inetd프로세스에게 SIGHUP신호를 inetd에게 파일을 다시 읽고, 새로운 내용을 얻게 하여야 한다. ps를 사용하여 inetd의 프로세스ID가 바뀌었는지 확인하면 된다.


11. 11 소켓 옵션

이 장에서는 소켓의 행동과 그 밑에 있는 통신 프로토콜을 변경하는 여러 가지 옵션을 설정하고 읽는 방법을 서술한다. 소켓옵션을 다룰 때, 옵션이 속하는 레벨을 명시해 주어야 한다. 이것은 옵션이 소켓인터페이스에 적용되는 지, 저수준 통신 프로토콜 인터페이스에 적용되는 지를 서술한다.


11. 11. 1 소켓 옵션 함수

여기에 소켓옵션을 변경하고 시험하는 함수가 있다. 'sys/socket. h'안에 그것들이 선언되어 있다.

int getsockopt (int socket, int level, int optname, void *optval, size_t *optlen_ptr) 함수

getsockopt함수는 socket소켓의 level레벨의 optname 옵션의 옵션 값에 대한 정보를 얻는다.
옵션 값은 optval이 가리키는 버퍼에 저장된다. 호출 전에, 이 버퍼의 크기인 *optlen_ptr안에 제공해야 한다. 반환할 때, 실제로 버퍼에 저장된 정보의 바이트 수를 담고 있다.
대부분의 옵션은 optval버퍼를 정수 값으로 해석된다.
성공시 getsockopt의 실제반환값은 0이고 실패시 -1이다.  
다음에 errno에러조건이 정의되어 있다.

EBADF : socket인수가 유효한 파일 서술자가 아니다.

ENOTSOCK : 서술자 socket이 소켓이 아니다.

ENOPROTOOPT : optname이 주어진 레벨에 맞지 않다.

int setsockopt (int socket, int level, int optname, void *optval, size_t optlen) 함수

이 함수는 socket소켓의 level레벨에 소켓옵션 optname을 설정하는데 사용된다. 옵션의 값은 optlen크기를 가진 optval버퍼에 전달된다. setsockopt의 반환치와 에러코드는 getsockopt과 같다.

11. 11. 2 소켓-레벨 옵션

int SOL__SOCKET 상수

이 절에 서술되어 있는 소켓레벨 옵션을 다루려면, getsockopt 나 setsocket의 level인수로 이 상수를 사용하라. 여기에 socket-level 옵션 이름의 표가 있다. 모두 'sys/socket. h'헤더 파일에 정의되어 있다.

SO_DEBUG

하위 프로토콜 모듈의 디버깅 정보의 저장할 것인가 여부를 설정한다. 그 값은 int형을 가진다. 0이 아닌 값은 저장하겠다는 것을 의미한다.

SO_REUSEADDR

이 옵션은 bind( 11. 3. 2절 [주소 설정]을 보라)가 이 소켓의 지역주소를 재 사용하는 것을 허락할 것인지 여부를 제어한다. 만약 이 옵션을 가능하도록 한다면, 같은 인터넷 포트로부터 두 소켓을 가질 수 있게 된다; 그러나, 시스템은 인터넷을 혼란시키는 두 별개의 이름을 가진 소켓을 사용하는 것을 허락하지 않는다. 이 옵션이 있는 이유는 FTP같은 상위 프로토콜이 같은 소켓번호의 재사용을 유지하기를 원하기 때문이다. 값은 int형을 가지며, 0이 아닌 수는 "그렇다(yes)"를 의미한다.

SO_KEEPALIVE

이 옵션은 하위 프로토콜이 주기적으로 메시지를 연결된 소켓으로 전송할 것인지 여부를 제어한다. 만약 서로 이러한 메시지의 응답을 실패하면 연결이 끊어지도록 한다. 값은 int형이고 0이 아닌 값은 "그렇다"를 의미한다.

SO_DONTROUTE

이 옵션은 송신하는 메시지가 일반 메시지 라우팅 기능을 우회할 것인지 여부를 제어한다. 만약 설정되면, 메시지는 직접 네트워크 인터페이스로 보내진다. 값은 int형이며 0이 아닌 값은 "그렇다"의 의미이다.

SO_LINGER

이 옵션은 신뢰도 있는 전달을 보장하는 어떤 형태의 소켓이 닫힐 때 여전히 전송되지 못한 메시지들을 가지고 있을 때, 무엇이 일어날 것인지를 명시한다. 11. 7. 2절 [소켓 닫기]을 보라. 값은 구조체 linger이다.

struct linger 자료형

이 구조체는 다음 멤버를 가진다:
int l_onoff
이 부분은 참거짓으로 해석된다. 만약 0이 아니면, close는 데이터가 전달되거나 시간제한이 경과될 때까지 프로그램의 수행이 중단된다.
int l_linger
이것은 초단위로 시간제한을 명시한다.

SO_BROADCAST

이 옵션은 데이터그램이 소켓으로부터 브로드캐스트될 것인지 여부를 제어한다. 값은 int형이고 0이 아닌 값은 "그렇다"를 의미한다.

SO_OOBINLINE

만약 이 옵션이 설정되면, 소켓에 수신된 out-of-band 데이터가 보통 입력 큐에 위치하게 된다. 이것은 MSG_OOB플랙 명시 없이 read나 recv를 사용하여 그것을 읽을 수 있도록 한다. 11. 8. 8절 [Out-of-Band 데이터]을 보라. 값은 정수형이며 0이 아닌 값은 "그렇다"를 의미한다.

SO_SNDBUF

이 옵션은 출력버퍼의 크기를 얻거나 설정한다. 값은 size_t형이고, 바이트 크기이다.

SO_RCVBUF

이 옵션으 입력버퍼의 크기를 얻거나 설정한다. 값은 size_t형이고, 바이트 크기이다.

SO_STYLE, SO_TYPE

이 옵션은 getsockopt에만 사용될 수 있을 것이다. 그것은 소켓의 통신 스타일을 얻는데 사용된다. SO_TYPE은 전통적인 이름이고 SO_STYLE은 GNU에서 채택한 이름이다. 값은 int형이고, 통신스타일을 나타낸다. 11. 2절 [통신 스타일]을 보라.

SO_ERROR

이 옵션은 getsockopt에만 사용할 수 있을 것이다. 소켓의 에러상태를 리셋 하는데 사용된다. 값은 int형이고 전번의 에러 상태를 나타낸다.


11. 12 네트워크 데이터베이스

많은 시스템은 시스템 개발자들에게 알려진 네트워크 리스트를 기록하는 데이터베이스를 가지고 있다. 이것은 보통 '/etc/networks' 또는 네임서버의 같은 파일을 유지한다. 이 데이터베이스는 route같은 라우팅 프로그램에서 유용하다. 그러나 네트워크를 통해 단순히 통신하는 프로그램에게는 별 필요가 없다. 우리는 'netdb. h'에 선언된 이 데이터베이스 접근 함수를 볼 것이다.

struct netent 자료형

이 자료형은 네트워크 데이터 베이스의 요소에 관한 정보를 표현하는데 사용된다. 그것은 다음 멤버를 가진다.

char *n_name

이것은 네트워크의 공식적인 이름이다.

char **n_aliases

네트워크의 또다른 이름들이 문자열의 벡터처럼 표현되어 있다. 널 포인터로 배열이 끝난다.

int n_addrtype

이것은 네트워크 번호의 종류이다. ; 이것은 인터넷 네트워크에 대해 항상 AF_INET이다.

unsigned long int n_net

이것은 네트워크 번호이다. 네트워크 번호는 호스트 바이트 순서로 반환된다. 11. 5. 5절 [바이트 순서]을 보라.

특정 네트워크에 관한 정보를 위해 네트워크 데이터베이스를 검색하기 위해 getnetbyname 또는 getnetbyaddr함수를 사용하라. 정보는 정적으로 할당된 구조체에 정보가 반환된다. ; 만약 그것을 저장할 필요가 있으면 그 정보를 복사해두어야 한다.

struct netent * getnetbyname (const char *name) 함수

getnetbyname함수는 name이라는 네트워크에 관한 정보를 반환한다. 만약 그와 같은 네트워크가 없으면 널 포인터를 반환한다.

struct netent * getnetbyaddr (long net, int type) 함수

getnetbyaddr함수는 type라는 종류와 net라는 숫자를 가진 네트워크에 관한 정보를 반환한다. 인터넷 네트워크의 종류를 위해서 AF_INET값을 명시해야 한다. getnetbyaddr은 만약 그러한 네트워크가 없으면 널 포인터를 반환한다. 또한 setent, getnetent 와 endnetent를 사용하여 네트워크 데이터 베이스를 일일이 살필 수 있다. 이러한 함수를 사용할 때는 주의하라. 그것들은 재진입성이 없기 때문이다.

void setnetent (int stayopen) 함수

이 함수는 네트워크 데이터베이스를 맨 앞부터 읽을 수 있도록 한다. 만약 stayopen인수가 0이 아니면, 플랙을 세트하여 추후의 getnetbyname이나 getnetbyaddr 호출이 (보통 그 함수들이 닫으므로)데이터베이스를 닫지 않도록 한다. 만약 각 호출시 데이터베이스를 다시 여는 것을 피하여 그러한 함수를 여러 번 호출할 때 매우 유용하다.

struct netent * getnetent (void) 함수

이 함수는 네트워크 데이터베이스의 다음 요소를 반환한다. 만약 더 이상의 요소가 없으면 널 포인터를 반환한다.

void endnetent (void) 함수

이 함수는 네트워크 데이터 베이스를 닫는다.
반응형

bugzilla에 대해서

bugzilla는 [http]mozilla.org에서 개발하고 제공하는 버그 추적(bug-tracking)시스템이다. 버그 트래킹 시스템은 개인이나 그룹이 어떤 프로제트를 진행함에 있어서 어느 부분에서 언제 버그가 발생했는지, 버그가 얼마나 치명적인지, 어떤 우선순위로 해결해야 하는지, 해결되었다면 누구에 의해서 언제 어떻게 해결되었는지를 DB에 남김으로써 발생된 버그에 대해서 체계적으로 관리 할 수 있도록 도와 준다.

bugzilla를 이용한 버그 관리

버그관리의 중요성

특히 팀단위로 개발을 할 경우 서로가 서로의 버그를 발견하는 경우가 있는데, 많은 경우 구두로 이러한 과정이 이루어진다. 간단하면서도 심각한 버그라면 발견시 바로 해결하기도 하지만, 많은 버그들이 뒤로 미루거나 다른일과 겹치거나 하면서 잊혀져 버린다. 그결과 버그가 계속적으로 누적되고, 발생했던 버그가 또다시 발생하고 이 버그가 해결했던 버그인지 아닌지도 헷갈리고 해결해야 되는건지 아닌건지도 헷갈리는 최악의 상황에 도달하게 된다. 때에 따라서는 소모적인 책임공방도 벌어지게 된다.

메일로 발견된 버그를 보고하면 그나마 좀 낳긴 하지만 임시방편일 뿐이라는건 사용해본 사람은 안다.

결국 프로젝트는 이런저런 자잘한 버그들 때문에 문제가 계속되고 어찌어찌해서 급하게 출시를 하더라도 완성도가 떨어지는 제품을 고객에게 내놓게 된다.

이런 문제를 해결하기 위해서 전문제품을 구입하거나, 팀이나 회사차원에서 나름대로 고심해서 시스템을 구축하기도 하는데, 솔직히 왠만한 규모의 개념있는 회사가 아닌다음에야 이런건 신경도 쓰지 않는다. 다행히도 공개되었으면서도 사용하기 편하고 강력한 버그트래킹 시스템이 있으니 바로 bugzilla다.

bugzilla의 설치

bugzilla는 영어권에서 개발된 프로그램이라서 모든 메시지가 영어로 되어있다. 그러나 한글화된 버젼이 있으니 이걸 받아서 설치하면 된다. [http]bugzilla 한국어 프로젝트를 방문해서 최신버젼을 다운받도록 한다. 여기에서는 2.16.3 한글 버젼을 기준으로 설치하도록 하겠다.

다음은 bugzilla설치를 위한 기본 환경이다.
  1. bugzilla는 웹기반 프로그램으로 Apache(12)나 IIS서버가 설치되어 있어야 한다.
  2. Perl(12) CGI(12)프로그램이다. 반드시 Perl이 설치되어 있어야 한다.
  3. 버그관련 정보를 DB에 저장하기 위해서 Mysql을 이용한다.

웹서버설치와 Mysql(12)설치는 여기에서 다루지 않을 것이다. 이와 관련되어서는 다른 사이트들을 참고하기 바란다.

Perl 모듈 설치
bugzilla는 상당히 방대한 시스템이며, 대부분이 perl로 이루어져 있기 때문에 perl 내부적으로 많은 모듈을 사용한다. 이런 이유로 제대로 bugzilla를 설치하기 위해서는 다음과 같은 모듈이 필수 적으로 설치되어 있어야 한다. 물론 Perl은 당연히 설치되어 있어야 하며 5.6.1 이상을 권장한다. 대부분 5.8이상이 설치되어 있으니 perl이 문제되는 경우는 없을 것이다.
  1. Template(2.07)
  2. AppConfig(1.52)
  3. Text::Wrap(2001.0131)
  4. Data::Dumper
  5. DBD::mysql(1.2209)
  6. DBI(1.13)
  7. Date::Parse
  8. CGI::Carp
다음은 반드시 필요하진 않지만 부가적인 기능을 위한 옵션 모듈들이다.
  1. GD(1.10) 버그 차트기능
  2. Chart::Base(0.99c) 버그 차트기능
  3. XML::Parser Xml
  4. MIME::Parser email기능

위의 모든 모듈들은 [http]CPAN에서 구할 수 있다. 모듈을 일일이 다운받아서 컴파일하고 설치해도 되겠지만 다음과 같이 자동으로 설치할 수도 있으니 활용해보기 바란다.(필자는 그냥 일일이 받아서 설치했다)
# perl -MCPAN -e 'install "Bundle::Bugzilla"'
위의 방법을 이용하더라도 GD, Chart::Base, MIME:Parser은설치가 되지 않는다.

bugzilla 설치
bugzilla를 다운받아서 웹서버의 cgi(12)디렉토리에 압축을 풀도록 한다.

그다음 checksetup.pl을 실행해서 bugzilla의 환경을 설정한다. mysql계정등의 정보를 설정하게 되는데, 간단하게 설정을 마칠 수 있을 것이다.
# ./checksetup.pl

이제 버그질라 페이지에 접근하도록 한다. 만약 에러메시지를 출력한다면 서버에서 직접 ./index.cgi를 실행시켜서 제대로 작동이 되는지 확인해보자. 문제없이 작동하는데도 에러가 떨어진다면 파일권한 문제인 경우가 대부분이다. cgi파일들이 실행권한으로 되어 있는지, 각 디렉토리가 nobody권한으로 읽을 수 있도록 되어있는지 확인해 보자.

bugzilla를 설치하기 전에 간단하게 테스트해보고 싶다면 [http]joinc bugzilla에서 테스트해보기 바란다.

bugzilla 상태 정보

버그를 관리하고 감시하기 위해서 버그질라는 발생된 버그에 대해서 심각도와 우선순위등을 할당하게 된다. 다음은 이들 버그의 상태정보에 대한 정보들이다. 아래의 용어들에 대해서 명확히 이해를 하고 있어야 버그관리가 제대로 이루어질 수 있을 것이다.
버그 심각도 (serverity)
  • Blocker : 개발 혹은 테스트 작업을 진행할 수 없게 만듦
  • Critical : 프로그램이 깨지거나, 데이터 손상및 메모리 누수가 발생함
  • Major : 기능상의 중요한 결점이 발견됨
  • Normal : 일반적인 문제로 반드시 고쳐야할 버그
  • Minor : 기능상 그리 중요하지 않은 결점, 혹은 쉽게 해결할 수 있는 문제
  • Trivial : 오탈자, 텍스트 정렬문제와 같은 외형적 문제
  • Enhancement : 기능 및 성능개선 관련 사항

버그 처리 우선순위 (Priority)
수정해야할 버그들의 중요도와 순서를 기술한다. 프로그래머 혹은 엔지니어가 자신들이 해야할 일에 대한 우선순위를 결정할 수 있도록 정보를 제공한다.
버그 상태정보(Status)
  +-----------+       +-------------+        +------+       +-------------+
  | 버그 발생 | ----> | UNCONFIRMED | -----> | NEW  | ----> | ASSIGNED    | 
  +-----------+       +-------------+        +------+       +-------------+
                            |                   |                | | |
                            |                   |                | | |
        +-------------+     |                   |                | | |
        | RESOLVED    | <---+                   |                | | |
        |             | <-----------------------+                | | |
   +----|             | <----------------------------------------+ | |
   |    |             | <---------------------------------+        | |
   |    |             | <---+                             |        | |
   |    +-------------+     |                             |        | |
   |                        |                             |        | |
   |    +-------------+     |                             |        | |
   +--->| VERIFIED    | ----+                             |        | |
   +----|             | ----------------->>---------------|--------+ |
   |    +-------------+                                   |          |
   |                                                      |          |
   |                                                      |          |
   |    +-------------+             +----------+          |          |
   +--->| CLOSE       | ----------> | REOPENED | ---------+          |
        |             |             |          | ------------>>------+  
        +-------------+             +----------+ 
버그의 상태를 나타낸다.
  • UNCONFIRMED(승인되지 않음)
    최근에 데이터베이스에 등록된 버그로, 아무도 이 버그에 대해서 확인을 해보지 않았다. 즉 아직 버그인지 아닌지도 검증이 되지 않은 상태다. 등록된버그를 Confirm할수 있는 사용자는 이 버그를 승인할 수 있으며, New(새로운버그)로 하거나 해결될 경우 (RESOVED)등의 상태로 변경이 가능하다.
  • NEW(신규버그)
    이 버그는 최근에 버그를 할당받은 담당자에 의해서 버그로 인정되었으며, 이에 대한 처리가 이루어져야 한다. 이 상태의 버그는 수락(accept)될 수 있으며, 필요한 경우 다른 사람에게 전달될 (ASSIGNED) 있다. 만약 다음 단계로 더 이상 진행이 안된다면 계속 NEW상태로 남아 있을 것이고, 문제가 해결된다면 RESOLVED 상태로 전이될 수도 있을 것이다.
  • ASSIGNED(할당됨)
    이 버그는 아직 해결되지 않았지만, 버그를 처리할 수 있는 적합한 사람에게 할당되어져 있음을 의미한다.
  • REOPENED(다시 오픈됨)
    이전에 해결(CLOSED)되었던 버그라고 하더라도 다시 재현될 수 있고, 혹은 담당자가 봤을때 버그처리가 명확하게 되어있지 않음을 인지할 수도 있을 것이다. 이경우 REOPENED 상태가 될수 있을 것이다. 이상태의 버그들은 ASSIGNED 혹은 RESOLVED 상태로 전이될 수 있다.
  • RESOLVED(처리됨)
    처리가 되었으며, QA(품질보증)담당자의 검증을 기다린다. 이 상태의 버그들은 REOPEND, VERIFIED 상태로 혹은 CLOSED 상태로 전이될 수 있다.
  • VERIFIED(검증)
    QA담당자가 버그와 처리결과를 보고 적절하게 처리가 완료되었는지를 검증하게 된다.
  • CLOSED(닫힘)
    버그가 완전히 사라졌다고 간주되는 상태다. 그러나 불행히도 다시 살아나는 경우가 발생할 수 있는데, 이때는 REOPENED 상태가되어야 한다.

버그 처리결과
버그에 어떤 일이 발생했는지를 나타낸다.
  • FIXED(해결됨)
    테스트가 완료되었으며 버그트리에 해결되었다고 표시된다.
  • INVALID(버그아님)
    기술된 문제는 버그가 아니였음
  • WONTFIX(해결불가)
    기술된 문제는 해결될 수 없는 버그이다.
  • LATER(나중에)
    기술된 문제는 본 제품에서는 수정될 수 없다. 차후 제품에 수정이 가능할 수 있다.
  • REMIND(기억할 것)
    기술된 문제는 본 제품의 현재 버젼에서는 수정할 수 없는 버그이지만, 앞으로 계속 영향을 끼칠 것으로 예상된다.
  • DUPLICATE(중복됨)
    기술된 문제는 기존의 버그와 중복되었다(혹은 유사한 버그가 이미 존재함). 버그를 중복되었다고 표시하기 위해서는 기존버그 번호를 필요로 한다.
  • WORKSFORME(파악할 수 없음)
    버그를 재연해 보려고 많은 노력을 기울였지만 실패했으며, 생성된 코드를 분석해봐도 왜 보고된 문제가 발생했는지를 파악할 수 없는 상태이다. 이 문제를 해결하기 위해서는 추가적인 정보가 필요하고, 그럴경우 이 버그는 다시 할당될 수 있다. 혹은 문제를 파악할 수 있을 만한 다른 개발자에게 할당할 수 있을 것이다.

플랫폼
버그가 보고된 대상 하드웨어 플랫폼 정보를 기록
OS
버그가 보고된 대상 운영체제 정보를 기록한다.

버그 등록하기

이제 버그를 등록해야될 차례다. 그런데 버그를 등록한다고 해서 바로 등록되는게 아니다. 버그를 관리해야할 제품(Products)와 구성되는 컴포넌트(Component)를 먼저 만들어야 한다. (하나의 제품은 여러개의 컴포넌트로 구성되어 있고, 각 컴포넌트 별로 버그를 관리할 필요가 있기 때문이다.)

Products메뉴를 이용해서 Products를 생성할 수 있으며, Products가 생성이 되었다면, Component를 입력할 수 있다. Component까지 만들어졌다면 버그관리를 위한 기본적인 환경이 만들어 졌다고 볼 수 있다.

이제 발생한 버그들을 그때 그때 기록하고 관리하기만 하면 된다.
반응형

사용자 삽입 이미지

술취한듯 비틀거리던 때가 바로 어제 같지만

오늘 하루도 맨정신으로 버티질 못하네요...

무엇이 그렇게 잃은 것이 많은 지..

무엇이 그렇게 갖지 못한 것이 많은지..

또 한번 소리를 질러 봅니다...

나는 사랑도 배우고 싶고...

인생도 배우고 싶습니다..

더이상 좌절이나 쓰러짐 따윈 다신 하고 싶지 않지만..

자꾸만 어깨위에 짖눌러진 무게가 늘어만 가네요..

마음 둘 곳이 없어서 방황한다고 자신을 위로해 봅니다...

반응형
1] Visual Assist?

* Visual Assist 는 Visual Studio를 사용하여 소스를 코딩할 때
여러가지 도움을 주는 프로그램이다.

[2] 사용방법

1. 이 문서는 Visual Assist version 6.0.0.1092 를 기준으로 작성되었다.
이 version은 Visual Studio 6.0에 대응된다.
2. 설치는 VA6SETUP1090.exe 를 실행시키고 안내문에 따르면 된다.
3. Visual Studio를 실행시키면 자동으로 Visual Assist가 실행된다.
4. "ToolBar*" 라는 이름으로 Visual Assist ToolBar가 생성되므로,
이를 통해 여러가지 설정이나 각종 기능을 사용할 수 있다.

[3] 기능 소개

* 이 문서에서 "Symobl"이라 함은 변수, 상수, 함수를 의미한다.
* 각 단락의 제목은 Visual Assist Homapage에서 참조하였다.
(http://www.wholetomato.com)

1. 자동 완성(Auto Completion)
- 소스 내에서 언제라도 Symbol의 앞글자만 치고 Tab 키를 누르면
해당하는 글자로 시작하는 Symbol들의 리스트 박스가 뜬다.
- 어떤 Symbol을 타이핑 하려고 할 때 글자를 치면 글자 위에 Symbol을
추측해서 보여준다. 맞는 Symbol이 나왔을 때 Tab 키를 누르면
자동으로 Symbol을 완성해준다.
- t 만 치고 Tab 키를 누르면 자동으로 true 가 타이핑 된다.
- f 만 치고 Tab 키를 누르면 자동으로 false 가 타이핑 된다.
- a Tab assert()
- b Tab break
- c Tab case
- d Tab default
- r Tab return
- T Tab TRUE, F Tab FALSE, A Tab ASSERT()
- 위와 같이 C 예약어는 상황에 맞게 자동으로 타이핑 된다.

2. 자동 수정(Auto Correction)
- Symbol을 타이핑할 때 대문자, 소문자를 틀릴 경우 자동으로 수정된다.
- 스펠링을 틀릴 경우 Symbol에 밑줄이 그어진다.
- 포인터 변수에 "."을 타이핑 할 경우 자동으로 "->"로 수정된다.
- {}과 ()에 대해 짝이 맞는 지 자동으로 검사해서 색깔로 표시해 준다.

3. 자동 형 정보(Auto Type Info)
- Symbol을 클릭하면 소스 창 위에 자동으로 Symbol의 정보가 표시된다.
- 위 상황에서 정보표시 창 옆의 "goto"를 클릭하면 Symbol 선언부로
자동 이동한다.
- 클릭하지 않아도 Symbol 위에 마우스를 대고 있으면 정보가 표시된다.

4. 자동 인자 정보(Auto Parameter Info)
- 함수뿐만 아니라 메쏘드와 매크로에 대해서도 인자 정보가 표시된다.

5. 변환(Formatting)
- 클래스와 메쏘드에도 색을 지정할 수 있으며 일단 Visual Assist를
실행시키면 자동으로 색 변환이 되어진 소스를 보여준다.
- 컬럼 표시줄을 표시할 수 있다. 기본 값은 꺼져 있으므로 옵션에서
활성화 시키면 점선으로 된 컬럼표시줄을 볼 수 있다.
- 칼라를 사용하여 소스를 프린트 할 수 있다.

6. 기타(Miscellaneous)
- 멀티플 클립보드 버퍼를 지원한다. Shift+Ctrl+V 키를 이용하면
클립보드에 카피한 내용이 나오고 그 중 선택해서 paste 할 수 있다.
- 오른쪽 마우스 클릭으로 불러지는 메뉴가 강화된다. 예를 들면
블럭을 지정해서 /* */ 자동으로 넣기 등이 가능해진다.
- { 를 타이핑 하면 자동으로 } 가 타이핑 된다.

* 이외에도 여러 기능들이 있다.

[4] Visual Assist ToolBar

* ToolBar의 왼쪽부터 차례대로 설명한다. 괄호 안은 단축키이다.

1. Option(단축키 없음) : Visual Assist의 여러 기능들을 변경, 설정할 수 있다.
2. Goto Method(Alt+M) : 메쏘드의 리스트를 보여준다.
3. Back(Alt+Left Arrow) : 브라우져에서처럼 뒤로 돌아가기를 실행한다.
4. Forward(Alt+Right Arrow) : 브라우져처럼 앞으로 가기를 실행한다.
5. Open Project File(Alt+Shift+O) : 현재 프로젝트에 해당하는 파일들을
보여주고 Open할 수 있게 해준다.
6. Open h or cpp(Alt+O) : 현재 파일이 h이면 해당 cpp를, cpp면 해당 h 파일을
Open한다.
7. Paste Multiple(Shift+Ctrl+V) : 멀티플 클립보드 버퍼 내용을 보여주고
paste할 수 있게 한다.
8. Insert Code Template(없음) : 템플릿 코드를 삽입시킨다.
9. Context Menu(Shift+오른쪽 마우스 버튼) : 확장 Context 메뉴를 실행시킨다.
10. Find Previous(없음) : 현재 마우스커서가 가르키고 있는 Symbol을 이전에서
찾는다.
11. Find Next(Alt+Shift+F3) : 현재 마우스커서가 가르키고 있는 Symbol을
이후에서 찾는다.
12. Comment Selection(없음) : 선택된 부분의 앞뒤에 자동으로 /* */ 를 넣는다.
13. Comment Selection(없음) : 선택된 부분의 앞에 자동으로 // 를 넣는다.
14. Spell Check(없음) : 선택된 부분에서 스펠링 체크를 한다.
15. Reparse(없음) : 현재 파일을 Reparse한다. (정확한 기능을 모르겠으나
현재 파일을 Visual Assist에 맞게 다시 변경하는 것으로 추측된다)
16. Enable/Disable(없음) : Visual Assist를 활성화/비활성화 한다.

반응형
사용자 삽입 이미지

"오다 노부나가는 성미가 급해 앵무새를 잡아놓고 울지 않으면 바로 그 자리에서 죽여버린다. 토요토미 히데요시는 앵무새가 울 때까지 달래보다가 그래도 울지 않으면 죽여버린다. 그러나 도쿠가와 이에야스는 앵무새가 스스로 울 때까지 인내심을 갖고 기다린다."

나는 천하통일을 이룬 도쿠가와 이에야스의 인내심을 갖고 있다...

때를 기다리면 반드시 기회는 온다.. 참고 인내할 뿐이다..
반응형

하이퍼텍스트 전송규약 1.1표준(안)





한국전자통신연구소


요약

하이퍼텍스트 전송 규약(HTTP)은 분산 정보 시스템, 종합 정보시스템 및 하이퍼미디
어 정보시스템에서 사용하는 응용 계층 규약으로서 요구 방법의 확장을 통해서 네임
서버와 분산 객체 관리 시스템과 같은 수많은 작업에 사용될 수 있는 보편적인
지향형 규약이다. HTTP는 어떤 문서의 데이터 표현 형식을 규정하고 협상하여 전송
중인 데이터와 무관하게 시스템을 구축할 수 있게 한다.

HTTP는 1990년 이후 World-Wide Web 범 세계 정보 이니셔티브에 의하여 사용되고
있다. 이 규격은 "HTTP/1.1"로 언급되는 규약을 정의하고 있다.


목차

 1 도입...........................................................  7
  1.1 목적 ...................................................  7
  1.2 필요 사항 .........................................  7
  1.3 용어 ...................................................  8
  1.4 전반적인 운영 ........................... 11
 2 기호 관례 및 일반적인 문법..............  13
  2.1 추가된 BNF .......................................  13
  2.2 기본적인 규칙 ..................................  15
 3 규약 파라미터...............................  17
  3.1 HTTP 버전 ........................................  17
  3.2 보편적 자원 식별자(Uniform Resource Identifiers) ........................  18
   3.2.1 일반적 형식 .............................  18
      3.2.2 http URL .........................................  19
      3.2.3 URI 비교   ..................................  20
  3.3 날짜/시간 형식...................................  21
      3.3.1 완전한 날짜 .................................  21
      3.3.2 Delta Seconds .................  22
     3.4 문자 집합 ..........................................  22
    3.5 내용 코딩 (Content Coding).............  23
    3.6 전송 코딩 (Transfer Coding)............  24
    3.7 미디어 타입 ......................................  25
     3.7.1 정형화(Canonicalization) 및 텍스트 기본값 ...............  26
     3.7.2 Multipart Type  ....................................  27
    3.8 제품 토큰 ......................................  28
    3.9 품질 등급 값..................................  28
    3.10 언어 태그......................................  28
    3.11 엔터티 태그.......................................  29
    3.12 영역 단위 .....................................  30
 4 HTTP 메시지.........................................  30
    4.1 메시지 유형 ...................................  30
    4.2 메시지 헤더 ...................................  31
    4.3 메시지 본문 ...................................  32
    4.4 메시지 길이 ...................................  32
    4.5 일반적인 헤더 필드 .....................  34
 5 요구........................................................  34
    5.1 Request-Line ........................................  34
     5.1.1 Method .........................................  35
     5.1.2 Request-URI ......................................  35
    5.2 요구에 의해 식별되는 자원 .........  37
    5.3 요구 헤더 필드 ...............................  37
 6 응답..........................................................  38
    6.1 상태-라인 ..........................................  38
     6.1.1 상태 코드 및 이유 문구 ..........  39
    6.2 응답 헤더 필드 ...............................  41


[Page 1]


 7 엔터티(Entity)..........................................................  41
    7.1 엔터티 헤더 필드 ................................  41
    7.2 엔터티 본문 .........................................  42
     7.2.1 유형 ..............................................  42
     7.2.2 길이 ............................................………………………………………………………...  43
 8 접속..........................................................  43
    8.1 지속적인 접속 .................................  43
     8.1.1 목적 ..............................................  43
     8.1.2 전반적인 운영..............................  44
     8.1.3 프락시 서버(Proxy Servers) ........  45
     8.1.4 실제적인 고려 사항 ..................  45
    8.2 메시지 전송 필요 조건 .................  46
 9 Method 정의.............................  48
    9.1 안전 및 멱등원(冪等元) method ..  48
   9.1.1 안전 method.....................................  48
      9.1.2 멱등원 method.................................  49
  9.2 OPTIONS ...............................................  49
    9.3 GET ........................................................  50
    9.4 HEAD ....................................................  50
    9.5 POST ......................................................  51
    9.6 PUT ........................................................  52
    9.7 DELETE .................................................  53
    9.8 TRACE ...................................................  53
 10 상태 코드 정의.......................................  53
  10.1 Informational 1xx (정보를 알려 주는 1xx) ..................................  54
     10.1.1 100 Continue (계속).....................................................................  54
     10.1.2 101 Switching Protocols (규약 전환)..................................  54
    10.2 Successful 2xx (성공을 알려 주는 2xx) .......................................................  54
     10.2.1 200 OK .........................................................................................  54
     10.2.2 201 Created (생성 되었음) .........................................................  55
     10.2.3 202 Accepted (접수 되었음).......................................................  55
     10.2.4 203 Non-Authoritative Information (비 인증 정보) ..................  55
     10.2.5 204 No Content (내용이 없음) ......................... ...... ...... ...........  55
     10.2.6 205 Reset Content (내용을 지움)............................ ...... ............  56
     10.2.7 206 Partial Content (부분적 내용)....................... ...... ...............  56
    10.3 Redirection 3xx (방향을 재설정하는 3xx).....................................  56
     10.3.1 300 Multiple Choices (복수 선택).......................... ...... .... ........  57
     10.3.2 301 Moved Permanently (영구 이동).............. ...........................  57
     10.3.3 302 Moved Temporarily (임시 이동)..........................................  58
     10.3.4 303 See Other (다른 것을 참조).................................................  58
     10.3.5 304 Not Modified (변경되지 않았음).........................................  58
     10.3.6 305 Use Proxy (프락시를 사용할 것)........................................  59
    10.4 Client Error 4xx (클라이언트 에러 4xx).........................................  59
     10.4.1 400 Bad Request (잘못된 요구)...................................................  60
     10.4.2 401 Unauthorized (인증되지 않았음)..........................................  60
     10.4.3 402 Payment Required (요금 지불 요청)....................................  60
     10.4.4 403 Forbidden (금지되었음)........................................…………………………..............  60


[Page 2]


     10.4.5 404 Not Found (찾을 수 없음).....................................................  60
     10.4.6 405 Method Not Allowed (Method를 사용할 수 없음)..............  61
     10.4.7 406 Not Acceptable (접수할 수 없음).........................................  61
     10.4.8 407 Proxy Authentication Required (프락시 인증이 필요함)....  61
     10.4.9 408 Request Timeout (요구 시간 초과).......................................  62
     10.4.10 409 Conflict (충돌).......................................................................  62
     10.4.11 410 Gone (내용물이 사라졌음)..................................................  62
     10.4.12 411 Length Required (길이가 필요함)........................................  63
     10.4.13 412 Precondition Failed (사전 조건 충족 실패)........................  63
     10.4.14 413 Request Entity Too Large (요구 엔터티가 너무 큼).............  63
     10.4.15 414 Request-URI Too Long (Request-URI이 너무 김)..................  63
     10.4.16 415 Unsupported Media Type (지원되지 않는 media type)..  63
    10.5 Server Error 5xx (서버 에러 5xx)......................................................  64
     10.5.1 500 Internal Server Error (서버 내부 에러)..................................  64
     10.5.2 501 Not Implemented (구현되지 않았음).....................................  64
   10.5.3 502 Bad Gateway (불량 게이트웨이) ....................................................  64
      10.5.4 503 Service Unavailable (서비스를 사용할 수 없음) .........................  64
      10.5.5 504 Gateway Timeout (게이트웨이 시간 초과)....................................  64
      10.5.6 505 HTTP Version Not Supported (지원되지 않는 HTTP 버전) ........  65
 11 접속 인증 ....................................................................  65
  11.1 기본 인증 scheme ........................................  66
    11.2 요약 인증 scheme .......................................................  67
 12 내용 협상(Content Negotiation)....................................  67
  12.1 서버가 주도하는 협상 .........................................  68
    12.2 에이전트가 주도하는 협상...................................  69
    12.3 투명한 협상(Transparent Negotiation ) ..................  70
 13 HTTP에서의 캐시........................................................  70
   13.1.1 캐시의 정확성 ..................................................  72
      13.1.2 경고 ....................................................................  73
      13.1.3 캐시-제어 메커니즘 .........................................  74
      13.1.4 명백한 사용자 에이전트 경고 ......................  74
      13.1.5 규칙 및 경고의 예외 사항 ............................  75
      13.1.6 클라이언트가 제어하는 행태 ........................  75
  13.2 유효일 모델 ...........................................................  75
     13.2.1 서버가 명시한 만기일 ....................................  75
     13.2.2 스스로 만기일을 찾음(Heuristic Expiration) ..  76
      13.2.3 경과 시간 계산(Age Calculations) ...................  77
      13.2.4 만기일 계산 ......................................................  79
      13.2.5 만기일 값을 명확하게 하기 .........................  80
      13.2.6 복수의 응답을 명확하게 하기 ......................  80
    13.3 검증 모델 ...............................................................  81
      13.3.1 최종 갱신 날짜 ................................................  82
      13.3.2 엔터티 태그 캐시 검증자(Validators) ................  82
      13.3.3 약한/강한 검증자 .............................................  82
      13.3.4 엔터티 태그와 최종 갱신 날짜를 사용할 때를 결정하는 규칙.......  85
      13.3.5 검증을 하지 않는 조건 법 .................................................................  86
    13.4 응답을 캐시할 수 있는 정도(Cachability) .....................……………................…..…....  86


[Page 3]


    13.5 캐시에서 응답을 구축하기 ..........................  87
     13.5.1 End-to-end 및 Hop-by-hop 헤더 ...............  88
      13.5.2 변경할 수 없는 헤더 ...............................  88
      13.5.3 헤더의 결합 ...............................................  89
      13.5.4 바이트 영역(Byte Ranges)의 결합............  90
    13.6 협상을 통한 응답을 캐시하기 ....................  90
    13.7 공유/비공유 캐시.............................................  91
    13.8 에러 또는 불완전한 응답 캐시 행태 .......  91
    13.9 GET 및 HEAD의 부작용 .............................  92
    13.10 갱신 또는 삭제 후의 무효화 ....................  92
    13.11 의무적으로 서버를 통하여 기입................  93
    13.12 캐시 대체 ......................................................  93
    13.13 History List ................................  93
 14 헤더 필드 정의.....................................................  94
  14.1 Accept .....................................................  95
  14.2 Accept-Charset.............................  97
    14.3 Accept-Encoding................................  97
    14.4 Accept-Language....................................  98
    14.5 Accept-Ranges ......................................  99
    14.6 Age...........................................................  99
    14.7 Allow...........................................  100
    14.8 Authorization.........................................  100
    14.9 Cache-Control....................................  101
   14.9.1 무엇을 캐시할 수 있는가................................  103
      14.9.2 캐시에 의해 무엇을 저장할 수 있는가........  103
      14.9.3 기본적인 만기일 메커니즘의 변경 ..............  104
      14.9.4 캐시의 재검증 및 Reload 제어 ...................  105
      14.9.5 비 변경 지시어 ................................................  107
      14.9.6 캐시 제어 확장..................................................  108
  14.10 Connection...............................................  109
    14.11 Content-Base................................  109
    14.12 Content-Encoding....................  110
    14.13 Content-Language........................  110
    14.14 Content-Length..............................  111
    14.15 Content-Location.........................  112
    14.16 Content-MD5..............................  113
    14.17 Content-Range.......................  114
    14.18 Content-Type..........................  116
    14.19 Date................................................  116
    14.20 ETag .........................................................................  117
    14.21 Expires.......................................................  117
    14.22 From.......................................................  118
    14.23 Host.....................................................  119
    14.24 If-Modified-Since ....................................................  119
    14.25 If-Match ...................................................................  121
    14.26 If-None-Match .........................................................  122
    14.27 If-Range ...................................................................  123
    14.28 If-Unmodified-Since ................................................  124
    14.29 Last-Modified ..................……………………………………………………………........... 124


[Page 4]


    14.30 Location...........................................  125
    14.31 Max-Forwards.............................  125
    14.32 Pragma ......................................................................  126
    14.33 Proxy-Authenticate.................  127
    14.34 Proxy-Authorization................  127
    14.35 Public ........................................................................  127
    14.36 Range........................................................  128
   14.36.1 Byte Ranges................  128
      14.36.2 Range Retrieval Requests  130
  14.37 Referer............................................  131
    14.38 Retry-After..............................  131
    14.39 Server.......................................................  132
    14.40 Transfer-Encoding..............  132
    14.41 Upgrade.......................................  132
  14.42 User-Agent........................  134
    14.43 Vary.........................................................  134
    14.44 Via.........................................................  135
    14.45 Warning...............................................  137
    14.46 WWW-Authenticate......................  139
 15 보안에 대한 고려 사항...............................................  139
  15.1 클라이언트의 인증 ...............................................  139
    15.2 인증 scheme을 선택할 수 있도록 함 ...................................  140
    15.3 서버 로그 정보의 남용 .......................................  141
    15.4 민감한 정보의 전송 .............................................  141
    15.5 파일 및 경로 이름에 기초한 공격 ...................  142
    15.6 개인적인 정보 ...........................................................  143
    15.7 Accept 헤더와 연결된 사생활 보호의 이슈 ...........  143
    15.8 DNS Spoofing(속이기) ............................................  144
    15.9 Location 헤더와 Spoofing(속이기) ........................  144
 16 감사의 말......................................................................  144
 17 참고 문헌......................................................................  146
 18 저자의 주소..................................................................  149
 19 부록................................................................................  150
  19.1 Internet Media Type message/http......................  150
    19.2 Internet Media Type multipart/byteranges ............  150
    19.3 Tolerant Applications.............................  151
    19.4 HTTP 엔터티와 MIME 엔터티의 차이점.........................................................  152
   19.4.1 규범적인 폼으로 변환 ....................................  152
     19.4.2 날짜 형식의 변환 ............................................  153
     19.4.3 Content-Encoding 소개...............................................  153
     19.4.4 No Content-Transfer-Encoding ........................................  153
      19.4.5 Multipart Body-Part의 HTTP 헤더 필드 .......  153
     19.4.6 Transmit-Encoding 소개 .............................................  154
     19.4.7 MIME-Version ..................................................………………………………………...... 154


[Page 5]


  19.5 HTTP/1.0 이후 변경 사항 ....................................  154
     19.5.1 복수의 홈을 가진 웹 서버를 단순하게 하기 위한 변경 사항 및 
           IP 주소 보존 .....................................................  155
  19.6 추가 기능 ...............................................................  156
     19.6.1 추가적인 요구 method ............................................  156
     19.6.2 추가 헤더 필드 정의 ......................................  156
    19.7 이전 버전과의 호환성 .........................................  160
     19.7.1 HTTP/1.0 지속적인 연결과의 호환성.............  161








[Page 6]


1 서론

1.1 목적

하이퍼텍스트 전송 규약(HTTP)은 분산 정보시스템, 종합 정보시스템 및 하이퍼미디어 정보시
스템에서 사용하는 응용계층의 규약이다. HTTP는 1990년 이후 World-Wide Web 범 세계 정보
이니셔티브에 의하여 사용되고 있다.  "HTTP/0.9"로 언급되는 HTTP의 첫 버전은 인터넷 상에
서 저장되어 있는 원래 데이터(raw data)를 전송하기 위한 단순한 규약이었다. RFC 1945 [6]이
규정한 HTTP/1.0은 메시지를 전송되는 문서 데이터에 대한 메타 정보 및 요구/응답 용어의
변경자를 포함하는 MIME과 유사한 메시지의 형식으로 사용할 수 있도록 함으로써 규약을 향
상시켰다. 그러나 HTTP/1.0은 계층적 프락시(hierarchical proxies), 캐시, 지속적인 연결의 필요
성 및 가상 호스트(virtual host) 등의 영향을 충분히 고려하지 않았다. 또한 "HTTP/1.0"을 지원
한다고 하면서도 규약의 불완전 구현 및 오해에 의한 잘못된 구현 등에 의해 응용 프로그램
사이에 종종 문제가 발생하였기에 상호 협상할 수 있는 응용 프로그램이 상대방의 진정한 성
능을 파악할 수 있도록 규약 버전을 갱신할 필요가 생겼다.

이 규격은 "HTTP/1.1"로 불리우는 하이퍼텍스트 전송 규약을 정의한다. 이 규약은 기능을 신
뢰할 수 있도록 구현하기 위해 HTTP/1.0보다 더 엄격한 필요 조건을 포함하고 있다.

실제적인 정보 시스템은 단순한 조회보다 검색, 프런트-엔드(front-end) 갱신 및 주석 달기 등
많은 기능을 필요로 한다. HTTP는 요구의 목적을 표시하는 일련의 개방된 method를 (open-
ended set of methods) 허용한다. 이 규약은 보편적 자원 식별자(URI) [3][20], 자원 위치 (URL) [4]
또는 자원 이름(URN)이 제공하는 참고 방법에 따라 method를 적용할 자원을 지칭하는 데 사
용한다. 메시지는 다용도 인터넷 메일 확장(MIME)에서 정의된 것처럼 인터넷 메일에서 사용
되는 것과 유사한 형식으로 전송된다.

HTTP는 사용자 에이전트, 프락시/게이트웨이와 SMTP [16], NNTP [13], FTP [18], Gopher [2], 및
WAIS [10] 등을 지원하는 다른 인터넷 시스템 사이의 통신을 위한 범용 규약으로서 사용된다.
이러한 방식으로 HTTP는 기본적인 하이퍼미디어가 다양한 애플리케이션의 자원에 접근할 수
있도록 한다.

1.2 필요 조건

이 규격은 각각의 특별한 필요 조건의 중요도를 정의할 때 RFC 1123 [8]와 동일한 용어를 사
용한다. 이러한 용어는 다음과 같다.

   MUST
이 단어 또는 "요구된"이라는 형용사는 해당 항목이 규격의 절대적인 필요 조건임을 의미
한다.

[Page 7]


   SHOULD
이 단어 또는 "추천된"이라는 형용사는 특정 상황에서 해당 항목을 무시할 합당한 이유가
있을 수 있다는 것을 의미한다. 그러나 충분히 함축적 의미를 이해해야 하고 다른 방법을
선택하기 전에 사례를 충분히 검토해야 한다.

   MAY
이 단어 또는 "선택적"이라는 형용사는 해당 항목이 진정으로 선택적이라는 것을 의미한
다. 한 판매회사는 특정 항목을 특정 시장이 요구하기 때문에 또는 예를 들어 제품의 기능
을 향상시켜 주기 때문에 다른 판매 회사와 달리 동일한 항목을 포함할 수 있다.

구현 방법이 하나 또는 그 이상의 MUST 규약 필요 조건을 충족시켜 주지 못하면 규약에 따
르지 않는 것이다. 구현 방식이 모든 MUST 및 SHOULD 필요 조건을 충족한다면 "무조건적으
로 충족한다"고 할 수 있고, 모든 MUST 필요 조건을 충족하지만 모든 SHOULD 필요 조건을
충족하지 못한다면 "조건적으로 충족한다"고 할 수 있다.

1.3 용어

이 규격은 HTTP 통신의 참여자 및 객체가 수행하는 역할을 지칭하는 몇몇 용어를 사용하고
있다.

   connection(연결)
통신을 목적으로 두 프로그램 간에 설정된 전송 계층의 가상적 회로

   message(메시지)
HTTP 통신의 기본 전송 단위. 4 장에 규정된 의미론을 따르는 구조적인 데이터 표현 형태
이며, 일련의 8 비트(octets)로 구성되어 있고 연결을 통하여 전송된다.

   request(요구)
       5 장에 규정된 HTTP 요구 메시지.

   response(응답)
       5 장에 규정된 HTTP 응답 메시지.

   resource(자원)
3.2절에 규정되어 있는 URI에 의하여 식별되는 네트워크 데이터 객체 또는 서비스. 자원
은 다양한 표현 형태 (예를 들어 언어, 데이터 형식, 크기 및 해상도)를 지닐 수 있으며 다
양한 방법으로 변형될 수 있다.

[Page 8]


   entity(엔터티)
요구나 응답 메시지의 페이로드(payload)로서 전송되는 정보. 엔터티는 7 장에서 설명된 대
로 Entity-Header 필드 형태의 메타 정보 및 Entity-Body 형태의 내용으로 구성되어 있다.

   representation(표현)
12 장에서 기술한 내용 협상의 통제를 따르는 응답에 포함된 엔터티. 특정한 응답 상태와
연관된 다수의 표현 방법이 있을 수 있다.

   content negotiation(내용 협상)
12 장에서 기술한 대로 요구를 처리할 때 적절한 표현 방법을 선택하는 메커니즘. 어떠한
응답에서는 엔터티의 표현은 협상할 수 있다.(에러 응답 포함)

   variant(변형자)
자원은 특정한 경우에 자원과 관련된 하나 이상의 표현 방식을 가질 수 있다. 이러한 각각
의 표현 방식을 "변형자"라고 부른다. "변형자"라는 용어를 사용한다고 해서 자원이 반드
시 내용 협상의 대상인 것은 아니다.

   client(클라이언트)
요구 메시지를 전송할 목적으로 연결을 설정하는 프로그램.

   user agent(사용자 에이전트)
요구 메시지를 시작하는 클라이언트. 이것은 종종 브라우저, 편집기, 스파이더(웹을 탐색하
는 로봇) 또는 다른 사용자 툴(tool)일 수 있다.

   server(서버)
요구 메시지를 처리하기 위해 접속을 수신하는 애플리케이션으로서 응답 메시지를 전송한
다. 어떤 프로그램이든 동시에 클라이언트와 서버가 될 수 있다. 이 규격에서 이 용어를
사용하는 것은 프로그램의 일반적인 능력을 참조하기보다는 특정한 연결을 위해 프로그램
이 수행하는 역할만을 참조하는 것이다. 마찬가지로 어떠한 서버도 원서버, 프락시, 게이트
웨이, 터널 등 각 요구의 성격에 따라 동작을 전환하는 역할을 할 수 있다.

   origin server(원서버)
해당 자원이 보관되어 있거나 자원을 생성할 수 있는 서버.

[Page 9]


   proxy(프락시)
다른 클라이언트를 대신하여 요구를 작성할 목적으로 서버와 클라이언트의 역할을 모두
수행하는 중간 프로그램. 요구는 내부적으로 처리되어 가능하면 해석되어 다른 서버로 전
달된다. 프락시는 이 규격의 클라이언트와 서버의 필요 조건을 모두 구현해야만 한다.

   gateway(게이트웨이)
다른 서버를 위해 중간 역할을 하는 서버. 프락시와는 달리 게이트웨이는 요구 메시지를,
요청받은 자원을 서비스하는 최종적인 원서버처럼 수신한다. 요구한 클라이언트는 자신이
게이트웨이와 통신하고 있다는 것을 알지 못할 수 있다.

   tunnel(터널)
두 연결 사이를 무조건 중계하는 역할을 하는 중간 프로그램. 활성화되면 비록 HTTP 요구
에 의하여 시작되지만 터널은 HTTP 통신의 참여자로 간주되지 않는다. 터널은 중계하고
있는 양 쪽의 연결이 종결되면 사라진다.

   cache(캐시)
프로그램이 응답 메시지를 저장하는 로컬 저장소. 메시지 보관, 조회 및 삭제를 제어하는
하부 시스템이기도 하다. 캐시는 응답 시간, 향후 네트워크 대역폭 소모 및 동일한 요구를
감소시킬 목적으로 캐시할 수 있는 응답을 저장한다. 어떤 클라이언트나 서버도 캐시를 포
함할 수 있다. 단지 터널 역할을 하는 서버는 캐시를 사용할 수 없다.

   cachable(캐시할 수 있는)
응답 메시지의 사본을 저장하여 계속적인 요구 응답에 사용할 수 있으면 응답을 캐시할
수 있다고 한다. HTTP 응답의 캐시 가능 여부를 결정하는 원칙은 13 장에 정의되어 있다.
자원을 캐시할 수 있다 하더라도 캐시가 특정 요구에 대하여 캐시 된 사본을 사용할 수
있는지 여부에 대한 추가적인 제한 사항이 있을 수 있다.

   first-hand(직접)
응답이 직접적으로 오며 원서버로부터 하나 또는 그 이상의 프락시를 거쳐옴으로써 발생
하는 불필요한 지연이 없을 경우 응답이 직접 온다고 할 수 있다. 또한 검증이 원서버에서
직접 이루어진다면 응답이 직접 온다고 할 수 있다.

   explicit expiration time(명백한 유효 시간)
원서버가 추가적인 검증 없이는 캐시에 의해 엔터티를 더 이상 되돌려 주지 않기로 한 시
간. 즉, 원서버가 캐시된 데이터의 유효성을 보장할 수 있는 시간.

[Page 10]


   heuristic expiration time(자동으로 설정되는 유효 시간)
분명한 유효 시간이 설정되어 있지 않을 때 캐시가 할당하는 유효 시간

   age(경과 시간)
응답 메시지의 경과 시간은 원서버로부터 전송된 후, 또는 성공적으로 검증된 후의 시간.

   freshness lifetime(신선한 기간)
응답의 생성 시점과 유효시간 만기 시점 사이의 시간 길이

   fresh(신선한)
응답의 경과 시간이 신선한 기간을 넘어서지 않았을 때 응답이 신선하다고 할 수 있다.

   stale(낡은)
응답의 경과 시간이 신선한 기간을 넘어섰다면 응답이 낡았다고 할 수 있다.

   semantically transparent(의미상으로 분명한)
성능을 향상시키고자 하는 목적을 제외하고 캐시의 사용이 요구하는 클라이언트나 원서버
에 영향을 미치지 않을 때 특정한 요구에 대하여 캐시가 "의미상으로 분명하게" 작동한다
고 할 수 있다. 캐시가 의미상으로 분명할 때 클라이언트는 원서버가 직접 처리했을 때와
완전히 동일할 응답을 수신하게 된다.( hop-by-hop 헤더는 제외).

   validator(검증자)
캐시 엔트리가 엔터티의 복사본과 동일한지 알아내는 데 사용하는 규약 요소(예를 들면
엔터티 태그나 Last-Modified 시간)

1.4 Overall Operation

HTTP 규약은 요구/응답 규약이다. 클라이언트는 요구 method, URI, 규약 버전의 형태로 서
버에 요구 메시지를 전송한다. 요구 변경자, 클라이언트 정보, 서버와의 접속에 사용되는
본문 내용을 포함하는 MIME 유형의 메시지가 뒤따른다. 서버는 메시지의 규약 버전 및
성공 또는 실패 코드를 포함하는 상태 정보로서 응답한다. 서버 정보, 엔터티 메타 정보,
Entity-Body 내용을 포함하는 MIME 유형의 메시지도 뒤따른다.

[Page 11]


대부분의 통신은 사용자 에이전트가 구동하며 특정 원서버에 적용할 요구로 구성되어 있다.
가장 단순한 경우 이것은 사용자 에이전트(UA)와 원서버(O) 사이의 단일 접속(v)에 의해 성취
할 수 있을 것이다.

    request chain ---------------------->
UA ---------------- v ------------------- O
    <--------------------- response chain

좀 더 복잡한 상황은 Request/Response chain에 하나 또는 그 이상의 중간 매개자가 있는 경우
이다. 프락시, 게이트웨이 및 터널의 세 가지 일반적인 중간 매개 형태가 있다. 프락시는 전송
에이전트로 절대 표현 형태의 URI 요구를 수신하여 메시지의 전체 혹은 부분을 재작성한 후
URI가 표시하는 서버로 재구성된 요구 메시지를 전달한다. 게이트웨이는 수신 에이전트로 다
른 서버 위의 계층 역할을 수행하며 필요하다면 원서버의 규약에 맞도록 요구를 해석하기도
한다. 터널은 메시지를 변경하지 않고 두 연결 지점을 연결하는 중계역할을 수행한다. 터널은
통신(communication)이 중간 매개자가 메시지의 내용을 이해할 수 없을 때라도 방화벽과 같은
중간 매개자를 통과할 필요가 있을 때 사용한다.

    request chain ------------------------------------->
UA -----v----- A -----v----- B -----v----- C -----v----- O
    <------------------------------------ response chain

위의 도표는 사용자 에이전트와 원서버 사이의 세 중간 매개자(A, B 및 C)를 보여 준다. 전체
고리를 통과하는 요구 또는 응답 메시지는 네 개의 별도 연결을 통과하게 된다. 몇몇 HTTP
통신 선택 사항은 최고 근접 거리의 비터널 이웃과의 통신, 연쇄적 연결 고리의 마지막 부분
에만 또는 연결 고리에 따르는 모든 연결에 적용되기 때문에 이러한 구분은 중요하다. 그림이
선형이지만 각 참여자는 복수의 동시 통신에 참여할 수 있다. 예를 들어 B는 A의 요구를 처
리함과 동시에 A를 제외한 복수의 클라이언트 요구를 수신하고/수신하거나 C 이외의 서버에
게 요구를 전송할 수 있다.

터널 역할을 수행하는 것이 아닌 통신에 참여하는 어떤 것이라도 요구를 처리할 때 내부 캐시
를 사용할 수 있다. 캐시의 효과는 연결 고리를 따라 참가자 중 하나가 해당되는 요구에 적용
할 수 있는 캐시된 응답을 갖고 있다면 Request/Response chain이 짧아진다. 다음은 UA 또는 A
가 캐시하지 않은 요구에 대한 O (C를 경유) 초기 응답의 사본을 B가 가지고 있을 때의 결과
고리를 설명하고 있다.

[Page 12]


    request chain --------->
UA -----v----- A -----v----- B - - - - - - C - - - - - - O
    <-------- response chain

보통 모든 응답을 캐시할 수 있는 것은 아니며 어떤 요구는 캐시 방식에 특별 요구를 하는 변
경자를 포함할 수 있다. 13 장에 캐시 방식과 캐시할 수 있는 응답에 대한 필요 조건이 기록되
어 있다.

사실상 World Wide Web에는 현재 실험되고 있거나 배포되고 있는 캐시와 프락시의 다양한 아
키텍쳐와 환경설정 방법이 있다. 이러한 것 중에는 대륙간 대역폭을 절약하기 위한 프락시 캐
시의 국가적 계층, 캐시 엔트리를 배포하거나 복수로 배포하는 시스템, CD-ROM 등을 통하여
캐시 된 데이터의 하부 세트를 배포하는 조직 등이 있다. HTTP 시스템은 광대역 연결을 통한
기업 인트라넷, 저동력 무선 연결의 PDA를 통한 연결 및 간헐적인 연결에 사용된다. HTTP/1.1
의 목적은 고도의 신뢰성과 신뢰성을 확보할 수 없다면 신뢰할 수 있는 실패의 표시 기능을
지닌 웹 응용프로그램을 개발하는 개발자의 요구를 충족하는 규약 구조물을 새로 소개하면서
도 이미 배포된 다양한 환경을 지원하는 것이다.

HTTP 통신은 대개 TCP/IP 연결을 통하여 이루어진다. 기본 포트는 TCP 80 이지만 다른 포트
를 사용할 수도 있다. 그러나 이것은 HTTP가 인터넷 상의 다른 규약이나 다른 네트워크 위에
서 구현될 수 없게 하는 것은 아니다. HTTP는 단순히 신뢰할 수 있는 전송 수단을 가정할 뿐
이며 이러한 보장을 해 줄 수 있는 어떠한 규약을 사용해도 된다. HTTP/1.1의 요구 응답 구조
를 적용하고자 하는 규약의 전송 데이터 단위로 배치(mapping)하는 것은 이 규격의 범위 밖의
것이다.

HTTP/1.0에서 대부분의 구현 방식은 각각의 요구/응답 교환에 새로운 접속을 사용하는 것이
다. 또한 HTTP/1.1에서는 하나의 접속을 하나 또는 그 이상의 요구/응답 교환에 사용할 수 있
으나 연결이 여러 가지 이유로 단절될 수 있다.( 8.1  절 참조)

2 기호 관례 및 일반적인 문법

2.1 추가된 BNF

이 문서에서 명시된 모든 메커니즘은 설명형 문구로서 RFC 822 [9]에서 사용한 것과 유사한
추가된 Backus-Naur Form (BNF)으로 설명되어 있다. 구현자는 이 규격을 이해하기 위하여 이러
한 기호에 익숙할 필요가 있다. 추가된 BNF는 다음의 구성 요소를 포함한다.

[Page 13]


name = definition
규칙의 이름이 이름 그 자체(둘러싸는 "<" 및 ">"이 없는)이며 정의 부분과는 등호 문자("=")
로 구별된다. 계속되는 공백 문자는 규칙에 대한 규정이 한 줄 이상에 걸쳐 있음을 표시하
는 들여쓰기의 경우에만 의미가 있다. SP, LWS, HT, CRLF, DIGIT, ALPHA 등과 같은 몇몇 기본
규칙은 대문자로만 사용한다. 정의문 내에서 소괄호는 규칙 이름의 사용 구별을 용이하게
해줄 경우에는 언제든지 사용한다.

"literal"
인용 부호로 문자 텍스트 주위를 감싼다. 별도의 언급이 없으면 문자는 대소문자를 구별한
다.

rule1 | rule2
막대 ("|")로 구분된 요소는 선택 사항이다. 예를 들어 "yes |no" 는 yes 나 no어느 것이든 가
능하다.

(rule1 rule2)
괄호로 둘러싼 요소는 단일 요소로 취급한다. 따라서 "(elem (foo | bar) elem)"는 
"elem foo elem" 및 "elem bar elem"의 토큰 순서를 허용한다.

*rule
이것은 반복을 의미하는 것으로서 뒤이어서 나올 #rule과 혼동을 일으키는 표현 방식이므
로 유의해야 한다. 반복을 통해 이루어지는 결과는 하나의 단어나 수와 같이 한 개 요소의
표현 형태로 되는 것이며, #rule에서는 똑같은 반복이지만 여러 개 단어나 수의 열 형태
와 같이 여러 개 요소의 나열 형태로 표현되는 것이다. *element와 같은 표기 방
법으로 쓰인다. 이것은 적어도 n개와 최대 m개의 요소로 구성되는 한 가지 결과를 의미한
다. 즉, 1*2DIGIT 라는 표현은 숫자가 적어도 한 개 최대 두 개로 구성되어 한 개의 수를
나타낸다는 뜻이다. 4는 한 가지 예이며, 45도 한 가지 예가 된다. 그러나 345의 경우
에는 숫자 세 개로 구성된 한 개 요소이므로 최대 갯수에 위배되어 적합하지 않다.
n과 m은 생략될 수 있으며, 이 경우에 n의 기본값은 0이고 m의 기본값은 무한대이다.
그러므로 "*(element)"는 0개를 포함해서 어떤 개수라도 가능하고, "1*element"의 경
우는 한 요소의 표현에 있어 적어도 한 개는 있어야 하며 최대 갯수에는 제한이 없다.

[rule]
대괄호는 선택 요소를 둘러 싼다. "[foo bar]" 는 "*1(foo bar)"와 동일하다.

N rule
특정 횟수의 반복을 나타낸다. "(element)" 은 "*(element)"와 동일하다.
즉 요소(element)가 정확하게 번 표시된다. 따라서 2 DIGIT 는 2 자리 숫자, 3 ALPHA
는 세 개의 알파벳 문자로 구성된 문자열이다.

#rule
앞서 설명한 것처럼 반복을 나타내긴 하지만 요소들의 나열로서 표현되는 것이다. 즉,
1#DIGIT 라고 하면 여러 개의 수로 구성된 수열로서 표현되는데, 최소 한 개의 수는 있어
야 하고 최대 갯수는 제한이 없는 수열이 된다. 각 요소들 사이의 구분은 ","와 LWS를 이
용하는데, 여러 개의 나열 형태를 쉽게 표현할 수 있게 해준다. 예를 들어, (*LWS
element *(*LWS "," *LWS element)) 이것을 간단하게 1#element 이와 같이 표현할
수 있다. 또 다른 예를 들자면, 1#2(2DIGIT)이것은 숫자 두 개로 구성된 수가 적어도 한
개가 있어야 하며 최대 두 개까지 가능하다는 것이다. 즉, 23 이렇게 표현될 수도 있고,
23, 56 이렇게 두 개로 표현될 수도 있다. 이것이 *rule과의 차이점이고, #rule 에서도
"#element" 의 구성이 그대로 성립한다. 이에 대한 설명은 *rule 의 경우와 같다. ","
를 이용하여 나열함에 있어, null element가 허용된다. 예를 들어, 1#3(2DIGIT)과 같
은 표현식에 대해23, , 56, 34 이렇게 null element 표시가 가능하지만, 실제 갯수는
세 개로서 간주된다. 따라서 최소 한 개 최대 세 개의 제한에 위배되지 않는다.

[Page 14]


; comment
규칙 문장에서 오른쪽으로 약간 떨어져 있는 세미콜론은 해당 라인의 끝에까지 계속되는 주
석의 시작을 의미한다. 이것은 규격과 병행하여 적절한 설명을 포함시키기 위한 방법이다.

implied *LWS
두 개의 인접한 단어 (token or quoted-string) 또는 인접한 토큰(tokens)과 식별자
(tspecials) 사이에 LWS (linear whitespace)가 포함될 수 있다. 여기서 두 개의 토큰 사이에
는 반드시 적어도 하나의 식별자가 존재하여 각기 하나의 토큰으로 간주되지 않게끔 구별되
어야 한다.

2.2 기본 규칙

다음의 규칙은 기본적인 분석 구조를 설명하기 위해 이 규격 전반에 걸쳐 사용되고 있다. US-
ASCII로 코드화 된 문자 집합은 ANSI X3.4-1986 [21]에 의하여 규정되었다.

 OCTET    = <모든 8-bit 연속 데이터>
 CHAR           = <모든 US-ASCII 문자 (octets 0 - 127)>
 UPALPHA       = <모든US-ASCII 대문자 "A".."Z">
 LOALPHA       = <모든 US-ASCII 소문자 "a".."z">
  ALPHA          = UPALPHA | LOALPHA
  DIGIT    = <모든 US-ASCII 숫자 "0".."9">
  CTL             = <모든 US-ASCII 제어 문자 (octets 0 - 31) 및 DEL (127)>
  CR              =
  LF             =
  SP              =  
  HT              =  
  <">             =  

[Page 15]


HTTP/1.1은 연속적인 CR LF를 Entity-Body를 (부록 19.3 참조) 제외한 모든 규약 요소의
라인 마감 부호로 정의한다. Entity-Body 내에서의 라인 마감 부호는 3.7 절에서 설명된 것
처럼 연관된 media type에 의하여 정의한다.

 CRLF =  CR LF

HTTP/1.1 헤더는 계속되는 라인이 스페이스나 수평 탭으로 시작한다면 복수의 라인에 걸쳐 계
속 작성할 수 있다. 폴딩(folding)을 포함한 모든 선형 공백 스페이스는 SP와 동일한 의미를
가진다.

  LWS            = [CRLF] 1*( SP | HT )

TEXT 규칙은 메시지 분석기가 해석하지 않도록 정의한 설명 필드 내용이나 값에 사용한다.
*TEXT의 단어는 RFC 1522 [14]의 규칙에 따라 인코딩되었을 경우에만 ISO 8859-1 [22] 이외 문
자세트의 문자를 포함할 수 있다.

 TEXT  = < CTLs을 제외한 (그러나 LWS는 포함) 모든 OCTET>

16 진수 숫자는 몇몇 규약 요소에서 사용할 수 있다.

 HEX = "A" | "B" | "C" | "D" | "E" | "F"
         | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT

많은 HTTP/1.1 헤더 필드 값은 LWS나 특수 문자로 구별되는 단어로 구성되어 있다. 파라미
터 값 내에서 사용할 이러한 특별 문자는 반드시 인용 문자열 내에 있어야 한다.

 token = 1*

 tspecials = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\"
| <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT

주석은 주석문을 괄호로 둘러싸서 몇몇 HTTP 헤더 필드에 포함할 수 있다. 주석은
"comment"를 필드 값 정의의 한 부분으로 포함하는 필드에서만 사용할 수 있다. 다른 필드
에서 괄호는 필드 값의 일부로 간주된다.

 comment = "(" *( ctext | comment ) ")"
  ctext    = < "(" and ")"을 제외한 모든 TEXT >

[Page 16]


텍스트 문자열이 이중 인용 부호를 사용하여 인용되었으면 단일 단어로 간주한다.

 quoted-string    = ( <"> *(qdtext) <"> )

 qdtext          = <<">을 제외한 모든 TEXT>

백슬래시 문자("\")는 인용된 문자열이나 주석 내에서만 단일문자 인용 메커니즘으로서 사용할
수 있다.

 quoted-pair     = "\" CHAR

3 규약 파라미터

3.1 HTTP 버전

HTTP는 "<주요한 변경>.<사소한 변경>" 번호 체계를 규약의 버전을 표시할 때 사용한다. 규
약 버전 부여 정책은 발송자가 통신을 통하여 획득한 기능보다는 메시지의 형식 및 계속적인
HTTP 통신을 이해할 능력이 있음을 표시할 수 있도록 하기 위해 정의되었다. 단순히 확장할
수 있는 필드 값을 추가하거나 통신 방식에 영향을 미치지 않는 메시지 구성 요소를 추가했을
경우에는 버전 숫자에 변화가 없다. <사소한 변경> 숫자는 일반적인 메시지 분석 알고리즘에
대한 변화는 없지만 메시지 의미에 대한 추가 사항이나 발송자의 추가적인 능력을 의미하는
규약 추가 기능에 대한 변경이 있을 경우 증가된다. <주요한 변경> 숫자는 규약 내부의 메시
지 형식이 변경되었을 때 증가한다.

HTTP 메시지의 버전은 메시지 첫 라인의 HTTP-Version 필드에 표시된다.

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

주요 및 사소한 부분을 표시하는 숫자는 반드시 별도의 정수 값으로 구분되어야 하며 10 단위
이상으로 증가할 수 있음을 주의해야 한다. 따라서 HTTP/2.4 은  HTTP/2.13보다 이전 버전이
며 또한 HTTP/12.3보다 이전 버전이다. 수신측에서는 앞 부분에 나오는 0을 반드시 무시해야
하며 전송해서는 안 된다.

이 규격이 규정하는 대로 요구나 응답 메시지를 전송하는 애플리케이션은 반드시 HTTP-
Version을 "HTTP/1.1"로 설정해야 한다. 이 버전 번호를 사용하는 것은 발송하는 애플리케
이션이 최소한 부분적으로는 이 규격을 따르고 있음을 표시한다.

애플리케이션의 HTTP 버전은 해당 프로그램이 최소한의 조건으로 상호 동작을 지원할 수 있
는 최고 HTTP 버전 값이다.
 
[Page 17]


프락시 및 게이트웨이 프로그램의 규약 버전이 애플리케이션과 상이할 경우 메시지를 전달할
때 주의해야 한다. 규약 버전은 발송자의 규약 능력을 표시하기 때문에 프락시/게이트웨이는
실제 자신의 버전보다 높은 버전 표시를 사용하여 메시지를 발송해서는 절대로 안 된다. 상위
버전의 요구가 수신되었으면 프락시/게이트웨이는 반드시 요구 버전을 내리거나, 에러를 발송
하거나 터널로 전환해야만 한다. 프락시/게이트웨이 버전보다 낮은 요구는 상위 버전으로 업그
레이드 할 수는 있으나 요구 받은 버전의 주요 버전은 반드시 동일해야 한다.

주의: HTTP 버전 간의 변환은 관련된 버전이 요구하거나 금지한 헤더 필드의 변경을 수반할
수도 있다.

3.2 보편적 자원 식별자(Uniform Resource Identifier - URI)

URI는 WWW 주소, 보편적인 문서 식별자, 보편적 자원 식별자 또는 보편적 자원 위치 지정
자(URL)와 이름(URN)의 결합에 이르기까지 많은 이름으로 불리우고 있다. HTTP로서는 보편
적 자원 식별자란 이름, 위치 또는 다른 어떤 특징을 이용하여 자원을 식별해 주는 정형화 된
문자열일 뿐이다.

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 | "/" )

[Page 18]


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 =  < ALPHA, DIGIT, reserved, extra, safe
                   및unsafe을 제외한 모든 OCTET>

URL 형식과 의미 규정에 관한 정보는 RFC 1738 [4] 및 RFC 1808 [11]을 따르고 있다. 상기
BNF 는 RFC 1738에 명시되어 있는 유효한 URL의 형태에서 허용하지 않고 있는 국가 문자
를 포함하고 있다. 이는 HTTP 서버가 주소에서 rel_path 부분을 표시하는 데 사용할 수 있
는 예약되어 있지 않는 문자 집합에 제한을 받지 않고, HTTP 프락시가 RFC 1738에 규정되지
않은 URI 요구를 수신할 수도 있기 때문이다.

HTTP 규약은 URI의 길이에 대한 어떠한 사전 제한도 두지 않는다. 서버는 반드시 자신이 제
공하는 어떠한 자원의 URI도 처리할 수 있어야 하며 이러한 URI를 생성할 수 있는 GET에
기초한 폼을 (GET-based forms) 제공한다면 무제한 길이의 URI를 처리할 수 있어야만 한다. 서
버는 URI의 길이가 자신의 처리할 수 있는 (10.4.15 절 참조) 것보다 긴 경우 414 (Request-URI
Too Long)를 응답으로서 돌려주어야 한다.

주의: 서버는 255 바이트 이상의 URI 길이를 사용할 때 몇몇 이전 클라이언트나 프락시 구
현 방식이 이러한 길이를 적절히 지원할 수 없는 경우가 있기 때문에 주의해야 한다.

3.2.2 http URL

"http" scheme은 HTTP 규약을 통하여 네트워크 자원의 위치를 파악하는 데 사용한다. 이 절은
http URL에 사용되는 scheme 특유의 형식과 의미를 규정한다.

[Page 19]


http_URL   = "http:" "//" host [ ":" port ] [ abs_path ]

host = <합법적인 인터넷 호스트 도매인 이름 또는 RFC 1123의 2.1 절에서 정
의한 방식의 IP 주소(점으로 구분된 형식)>

port  = *DIGIT

포트 항목이 비어 있거나 명시되지 않았으면 포트는 80으로 간주한다. TCP 연결 요구를 기다
리고 있는 해당 호스트 서버의 해당 포트에 식별된 자원이 위치하고 있으며 자원의
Request-URI는 abs_path라는 것이 의미한다는 내용이다. URL의 IP 주소의 사용은 가능한
한 피해야만 한다 (RFC 1900 [24] 참조). URL에 abs_path가 명시되어 있지 않으면 자원(5.1.2
절)을 위한 Request-URI로서 사용할 때 반드시 "/"가 주어져야 한다.

3.2.3 URI 비교

URI가 서로 일치하는지 여부를 결정하기 위해 URI를 비교할 때 클라이언트는 전체URI에
대하여 대소문자를 구별하는 8진수 대 8진수 비교 방법(octet-by-octet comparison)을 사용해야
만 하며 다음의 예외 사항이 있다.

? 비어 있거나 명시되지 않은 포트는 기본 포트 80번으로 정의한다;
 
? 호스트 이름의 비교에는 반드시 대소문자를 구별하지 않는다;
 
? scheme 이름의 비교는 반드시 대소문자를 구별하지 않는다;
 
? 비어 있는 abs_path는 "/"인 abs_path와 동일하다.

"예약되거나(reserved)" "안전하지 않는(unsafe)" 문자 집합 (3.2 절 참조) 이외의 문자는  ""%"
HEX HEX" 인코딩과 동일하다.

예를 들어 다음의 세 URI는 동일하다.

http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html

[Page 20]


3.3 날짜/시간 형식

3.3.1 완전한 날짜

HTTP 프로그램은 역사적으로 세 가지 방법으로 시간/날짜를 표시해 왔다.

Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, RFC 1123에서 갱신
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, RFC 1036에서 폐기
Sun Nov  6 08:49:37 1994       ; ANSI C의 asctime() 형식

첫번째의 형식이 인터넷 표준으로 우선권을 가지고 있으며 RFC 1123 (RFC 822의 개정판)에서
규정한 고정 길이의 하부 세트를 표시한다. 두 번째 형식은 일반적으로 사용되기는 하지만 폐
기된 RFC 850 [12] 날짜 형식에 기초하고 있으며 4 단위 년도 표시가 결여되어 있다. 날짜를
분석하는 HTTP/1.1 클라이언트 및 서버는 반드시 상기 세 형식을 모두 수용해야 한다. 그러나
헤더 필드의 HTTP-날짜 값을 표시할 때는 반드시 RFC 1123 형식만을 생산해야 한다.

주의 : 날짜 값 수신처는 메시지를 프락시/게이트웨이를 통하여 SMTP나 NNTP로 조회 또
는 발송하는 경우처럼 비 HTTP 애플리케이션이 발송한 날짜 값을 수신하는 데 적극적인 조
치를 취할 것을 장려한다.

모든 HTTP 날짜/시간 표시는 예외 없이 반드시 그린이치 표준 시간(GMT))을 따라야 한다. 이
는 처음 두 형식에서 시간대를 표시하는 3 문자의 축약어인 "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
                           ; day month year (e.g., 02 Jun 1982)
date2          = 2DIGIT "-" month "-" 2DIGIT
                           ; day-month-year (e.g., 02-Jun-82)
date3          = month SP ( 2DIGIT | ( SP 1DIGIT ))
                           ; month day (e.g., Jun  2)
time           = 2DIGIT ":" 2DIGIT ":" 2DIGIT
                           ; 00:00:00 - 23:59:59

wkday         = "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"

[Page 21]


weekday       = "Monday" | "Tuesday" | "Wednesday" | "Thursday"
                | "Friday" | "Saturday" | "Sunday"

month         = "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun"
                | "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"

주의: 날짜/시간 표현에 대한 HTTP 필요 조건은 규약 스트림 내부에서 사용할 때만 적용된
다. 클라이언트와 서버는 사용자의 표시 방법, 요구 로깅 등에서는 이러한 형식을 반드시 사
용해야 할 필요는 없다.

3.3.2 Delta Seconds

몇몇 HTTP 헤더는 메시지가 수신된 이후의 시간을 10진법의 정수로 초를 명시할 수 있도록
한다.

delta-seconds  = 1*DIGIT

3.4 문자 집합

HTTP는 MIME에서 설명된 "문자 집합"이라는 용어를 동일하게 사용한다.

일련의 8bit 데이터를 적절한 대응 관계에 있는 일련의 글자로 변환시킬 수 있도록 한 개 또
는 그 이상의 표로서 만들어서 참조하게 하는 수단이다. 그러므로 무조건 변환시켜서는 안
되고, 모든 글자가 문자 집합에 정의되어 있지 않을 수 있고, 특정한 글자를 표현하기 위해
하나 이상의 8bit 데이터열이 존재할 수도 있다. 이 정의에 따르면, US-ASCII와 같은 단순한
변환표로부터 ISO 2022의 경우에서와 같이 복잡한 변환표에 이르기까지 다양한 종류의 문자
인코딩들을 허용한다. 하지만 MIME 문자 집합 이름과 관련된 정의는 8bit 데이터로부터 글
자로의 변환에 관한 사항을 완전하게 명시하여야 한다. 완전한 변환 관계를 정의하기 위해
다른 수단을 통한 외부 정보를 활용해서는 안 된다.

주의 : 이러한 "문자 집합"이라는 용어의 사용은 보통 "문자 인코딩"으로 지칭된다. 그러나
HTTP와 MIME은 동일한 등록표를 사용하기 때문에 용어를 공유하는 것 또한 중요하다.

[Page 22]


HTTP 문자 집합은 토큰에 의해 식별되며 대소문자를 구별하지 않는다. 완전한 토큰 세트는
IATA 문자 집합 등록표(IANA Character Set registry [19])에 규정되어 있다.

charset = token

HTTP가 charset 값으로 임의의 토큰을 사용하도록 허용하지만 IATA 문자 집합 등록에 사전
정의된 모든 토큰은 반드시 이 등록표에 등록된 문자 집합을 표시해야 한다. 애플리케이션은
사용하는 문자 집합을 IATA 등록 표에서 규정된 것으로 제한해야만 한다.

3.5 내용 코딩(Content Codings)

내용 코딩 값은 엔터티에 적용하였거나 적용할 수 있는 인코딩 변환을 표시한다. 내용 코딩은
문서를 압축하거나, 그렇지 않다면 내용의 media type의 정체를 상실하거나 정보를 손실하지
않고 유용하게 변형하는 데 사용한다. 종종 엔터티는 코드화 된 폼에 저장되고 직접 전송되어
수신측만이 이를 해독한다.

content-coding   = token

모든 내용 코딩의 값은 대소문자를 구별하지 않는다. HTTP/1.1은 Accept-Encoding (14.3 절)
및 Content-Encoding (14.12 절) 헤더 파일에 내용 코딩 값을 사용한다. 그 값이 Content-
Coding을 설명하는 것이지만 더욱 중요한 것은 인코딩을 제거하기 위해 필요한 해독 메커니
즘을 표시한다는 것이다.

인터넷에서 할당된 숫자 체계(Internet Assigned Numbers Authority (IANA))는 Content-Coding
값 토큰의 등록표 역할을 수행한다. 처음에 이 등록표에는 다음의 토큰이 포함되어 있다.

   gzip
RFC 1952 [25]에 설명된 대로 파일 압축 프로그램인 "gzip"에 의하여 생성된 인코딩 포
맷. 이 포맷은 32 bit CRC를 가진 Lempel-Ziv coding (LZ77)이다.

   compress
일반적인 UNIX 파일 압축 프로그램인 "compress"에 의하여 생성된 인코딩 포맷. 이
포맷은 Lempel-Ziv-Welch 코딩(LZW)을 수정한 것이다.

[Page 23]


주의: 인코딩 포맷을 식별하는 프로그램 이름의 사용은 바람직하지 않으며 향후 인코딩을
위해서 사용하지 말도록 권고한다. 프로그램 이름을 여기에서 사용한 것은 역사적인 관례이
며 훌륭한 디자인은 아니다. HTTP의 이전 구현법과 호환성을 유지하기 위해 애플리케이션
은 "x-gzip" 및 "x-compress" 을 "gzip" 과 "compress" 각각 동일한 것으로 간주해야
한다.

   deflate
RFC 1951[29]에 설명된 "deflate" 압축 메커니즘과 결합하여 RFC 1950[31]에 정의된 "zlib"
포맷.

새로운 Content-Coding 값 토큰은 등록해야 한다. 클라이언트와 서버가 상호 운용성을 가
지도록 하기 위해 새로운 값을 구현하는 데 필요한 내용 코딩 알고리즘에 대한 규격은 일반인
이 사용할 수 있어야 하고 독립적으로 구현하기에 적합해야 하며 이 절에 규정된 내용 코딩의
목적에 따라야 한다.

3.6 전송 코딩 (Transfer Codings)

전송 코딩 값은 네트워크를 통한 "안전 전송"을 확보하기 위해 Entity-Body에 적용하였거
나, 적용할 수 있거나 또는 적용할 필요가 있는 인코딩 변환을 표시하는 데 사용한다. 전송 코
딩은 메시지의 특성 중의 하나이며 원래 엔터티의 특성이 아니라는 점이 내용 코딩과 다른 점
이다.

transfer-coding         = "chunked" | transfer-extension

transfer-extension       = token

모든 transfer-coding 값은 대소문자를 구별하지 않는다. HTTP/1.1은 Transfer-
Encoding 헤더 필드 (14.40 절)의 전송 코딩 값을 사용한다.

전송 코딩은 7 비트 전송 서비스로 바이너리 데이터를 안전하게 전송할 수 있도록 디자인 된
MIME의 Content-Transfer-Encoding 값과 유사하다. 그러나 8 비트 전송 규약에서 안전
전송의 중점은 다른 곳에 있다. HTTP에서 유일한 Message-Body의 불안전한 특징은 정확한
본문 길이(7.2.2 절)를 결정하기 어렵다는 것과 공유하는 전송체계에서 데이터를 암호화하기
어렵다는 것이다.

덩어리 인코딩(chunked encoding)은 메시지를 일련의 덩어리로 전송하기 위하여 메시지 본문을
변경한다. 이 덩어리는 각각 자신의 크기 표시자를 가지고 있으며 Entity-Header 필드를 포
함하고 있는 선택적인 각주(footer)가 뒤따른다. 이를 통하여 역동적으로 생산된 내용물이 수신
인이 메시지 전체를 수신하였다는 것은 증명하는 데 필요한 정보와 함께 전송될 수 있도록 한
다.

[Page 24]


Chunked-Body     = *chunk
                         "0" CRLF
                         footer
                         CRLF

chunk              = chunk-size [ chunk-ext ] CRLF
                      chunk-data CRLF

hex-no-zero      = < "0"을 제외한 HEX >

chunk-size       = hex-no-zero *HEX
chunk-ext        = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
chunk-ext-name   = token
chunk-ext-val    = token | quoted-string
chunk-data       = chunk-size(OCTET)

footer            = *Entity-Header

덩어리 인코딩은 크기 0의 덩어리로 종결되며 빈 라인으로 종료되는 각주가 뒤따른다. 각주의
목적은 역동적으로 생성된 엔터티에 대한 정보를 효과적으로 제공하도록 하는 것이다. 애플리
케이션은 Content-MD5, 디지털 서명이나 다른 기능을 위한 HTTP 향후 확장으로 명백하게
규정되지 않은 헤더 필드를 결코 각주에 넣어서 전송해서는 안 된다.

Chunked-Body를 해독하는 예가 부록 19.4.6에 제시되어 있다.

모든 HTTP/1.1 애플리케이션은 반드시 덩어리 전송 코딩을 해독하고 수신할 수 있어야 하며
해독할 수 없는 전송 코딩 확장은 반드시 무시해야 한다. 해독할 수 없는 Transfer-Coding
과 함께 Entity-Body를 수신하는 서버는 501 (Unimplemented)을 응답으로 돌려주고 연결을
종료해야 한다. 서버는 결코 Transfer-Coding을 HTTP/1.0 클라이언트에 보내서는 안 된다.

3.7 미디어 형식(Media type)

HTTP는 공개적이고 확장 가능한 데이터 유형 설정 및 유형 협상 기능을 제공하기 위해
Content-Type (14.18 절) 및 Accept (14.1 절) 헤더 필드의 인터넷 미디어 형식을 사용한다.

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

attribute/value(속성/값) 쌍 형태의 파라미터가 type/subtype 유형을 뒤따른다.
 
[Page 25]


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

유형, 하부 유형 및 파라미터 속성 이름은 모두 대소문자를 구분하지 않는다. 파라미터 값은
파라미터 이름의 의미에 따라 대소 문자를 구별할 수도 있고 않을 수도 있다. 선형 공백 스페
이스(LWS)는 유형과 하부 유형, 속성과 속성 값 사이에 절대 사용해서는 안 된다. 미디어 형
식을 인지하는 사용자 에이전트는 반드시 해당 MIME 유형의 파라미터를 해당
type/subtype 정의가 설정한 방식으로 처리해야 한다. (또는 사용자 에이전트가 해당
type/subtype을 처리하는 데 사용하는 외부 애플리케이션이 처리하도록 주선해야 한다.) 또
한 발견된 모든 문제를 사용자에게 알려 주어야 한다.

주의 : 이전 HTTP 애플리케이션은 미디어 형식 파라미터를 인지하지 못한다. 이전 HTTP 애
플리케이션으로 데이터를 전송할 때 구현 방식은 해당 type/subtype 정의가 요구할 때만
미디어 형식 파라미터를 사용해야 한다.

미디어 유형 값은 인터넷 할당 숫자 체계(IANA)에 등록된다. 미디어 유형을 등록하는 절차는
RFC 2048 [17]에 윤곽이 설명되어 있다. 등록되지 않은 미디어 유형을 사용하는 것은 권하지
않는다.

3.7.1 정형화(Canonicalization) 및 텍스트 기본값

인터넷에서의 미디어 형식은 정형화된 형식으로서 등록되어 있다. 보통 HTTP 메시지를 통하
여 전송되는 Entity-Body는 반드시 전송되기 이전에 적절한 정형화된 형식으로 표시되어야
한다. 이의 예외는 다음 문구에서 정의된 "text" 유형이다.

정형화된 형식으로서 text 형식의 미디어 subtype은 CRLF를 텍스트 라인 줄 바꿈으로 사
용한다. HTTP는 이러한 필요 조건을 완화하여 Entity-Body 전반에 걸쳐 일관성 있게 동일
한 방법을 사용하였을 경우 단순히 CR 또는 LF 하나를 줄 바꿈으로 표현하는 텍스트 미디어
전송을 허용한다. HTTP 애플리케이션은 CRLF, 단편적인CR 또는 LF를 HTTP를 통하여 수신
한 텍스트 미디어에서 줄 바꿈을 표시하는 것으로 인정해야만 한다. 또한 텍스트가 몇몇 멀티
바이트 문자 집합의 경우처럼 8진수 13과 10을 CR 과 LF로 사용하지 않는 문자 집합을 사
용하고 있을 경우 HTTP는 어떠한 일련의 octets가 해당 문자 집합에서 줄바꿈을 위한 CR 및
LF를 대표하는 것으로 규정하든 이를 허용한다. 이러한 줄바꿈에 대한 유연성은 Entity-
Body의 텍스트 미디어에만 적용되며 단편적인 CR 또는 LF는 어떠한 HTTP 제어 구조(헤더
필드 및 multipart 경계와 같은)에서도 CRLF를 대체해서는 안 된다.

Entity-Body가 Content-Encoding으로 인코딩 되었다면 내부 데이터는 인코딩 되기 이
전에 위에서 규정한 형식으로 표현되어 있어야 한다.
 
[Page 26]


"charset" 파라미터는 몇몇 미디어 형식에서 데이터의 문자 집합(3.4 절)을 규정하는 데 사용
한다. 송신자가 명백한 charset 파라미터를 제공하지 않았다면 "text" 유형의 미디어
subtype 형식은 HTTP를 통하여 수신했을 때 "ISO-8859-1"의 charset 기본값을 갖도록
규정되어 있다. "ISO-8859-1" 이외 문자 집합의 데이터나 그 하부 세트는 적절한 charset
값으로 명명되어야 한다.

몇몇 HTTP/1.0 소프트웨어는 charset 파라미터 없는Content-Type 헤더를 "수신측이 짐작
해야 한다"라고 잘못 해석하였다. 이러한 방식을 방지하고자 하는 송신자는 charset가 ISO-
8859-1일 때도 charset 파라미터를 포함할 수 있다. 또한 수신측에게 혼선을 주지 않는다
는 것을 알 수 있을 때도 그렇게 해야 한다.

불행하게도 몇몇 이전 HTTP/1.0 클라이언트는 명확한 charset 파라미터를 적절히 처리하지
못했다. HTTP/1.1 수신측은 송신측이 제공하는 charset 라벨을 반드시 감안해야 한다. 또한
charset을 추측하는 조항을 가진 사용자 에이전트는 Content-Type 필드의 charset를
지원한다면 처음 문서의 내용을 표시할 때 수신측의 선호도에 따르기보다는 반드시 이
charset를 사용해야 한다.

3.7.2 Multipart Type

MIME은 많은 "multipart" 형식을 제공하고 있는데 ? 하나 또는 그 이상의 엔터티를 단일
메시지 본문 내에 포함시킬 수 있도록 하는 것이다. 모든 multipart 형식은 MIME [7]에 규
정되어 있는 공통적 표기법에 따르며 미디어 형식 표시값의 일부로서 경계 파라미터를 포함해
야 한다. 메시지 본문 자체는 규약의 한 요소이며, Body-Part 간의 줄 바꿈을 표시할 때 반드시
CRLF만을 사용해야 한다. MIME과는 달리 모든 multipart 메시지의 맺음말은 반드시 비어
있어야 한다. HTTP 애플리케이션은 맺음말을 절대로 전송해서는 안 된다 (비록 원래의
multipart가 맺음말을 포함하고 있다 하여도).

HTTP에서 multipart의 Body-Part는 해당 부분의 의미에 중대한 영향을 끼치는 헤더필드를
포함할 수 있다. Content-Location 헤더 필드(14.15 절)는 URL로 확인할 수 있는 엔터티의
Body-Part에 포함되어야 한다.

일반적으로 HTTP 사용자 에이전트는 MIME 사용자 에이전트가 multipart 유형을 수신했을
때 처리하는 방식과 동일하거나 유사한 방식에 따라야 한다.

주의: RFC 1867 [15]에서 설명된 것처럼 "multipart/form-data" 유형이 POST 요구
method으로 처리하기에 적합한 폼 데이터를 전송하기 위해 특별히 규정되었다.

[Page 27]


3.8 제품 토큰

제품 토큰은 통신 애플리케이션이 자신의 소프트웨어 이름 및 버전을 확인하는 데 사용한다.
제품 토큰을 사용하는 대부분의 필드는 공백 문자로 구분되는 목록에 열거할 애플리케이션의
중요한 부분을 형성하는 부수적 제품명의 표시를 허용한다. 관례상 제품은 애플리케이션을 식
별해 주는 제품의 중요도에 따라 열거된다.

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

   예:

User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4

제품 토큰은 간략해야 하며 요점이 있어야 한다. 광고나 필수적이지 않은 다른 정보를 위해
사용하는 것은 분명하게 금지되어 있다. 어떠한 토큰 문자라도 제품 정보에 표시할 수 있지만
이 토큰은 버전 식별자에만 사용해야 한다.(동일한 제품의 계속적인 버전은 제품 값(value)의
product-version 부분만 달라야 한다.)

3.9 품질 등급 값

HTTP 내용 협상(12 장)은 짤막한 "부동소수점" 숫자를 사용하여 다양한 협상 가능 파라미터
의 상대적 중요성("가중치")을 표시한다. 가중치는 최소값 0부터 최대값 1까지 범위의 실수로
정형화할 수 있다. HTTP/1.1 애플리케이션은 부동소수점 이후의 자리에 세 자리 이상의 숫자를
절대 사용해서는 안 된다. 이러한 값들에 대한 사용자의 값 설정은 또한 다음의 방식으로 한
정되어야 한다.

qvalue         = ( "0" [ "." 0*3DIGIT ] )
               | ( "1" [ "." 0*3("0") ] )

"품질등급 값"은 이 값이 단순히 원하는 품질에 대한 상대적인 질 저하를 표현하는 것이기 때
문에 잘못된 명칭이다.

3.10 언어 태그

언어 태그는 인간이 다른 인간과 정보를 교환하기 위하여 말하거나, 쓰거나 혹은 전달하는 자
연적인 언어를 표시한다. 컴퓨터 언어는 분명히 제외된다. HTTP는 Accept-Language 및
Content-Language 필드를 이용하여 언어 태그를 표시한다.

[Page 28]


HTTP 언어 태그의 의미 및 등록표는 RFC 1766 [1]에서 규정한 것과 동일한 것을 사용한다. 요
약하면 언어 태그는 하나 또는 그 이상의 부분으로 구성되어 있다. 주요 언어 태그 및 비어
있을 수도 있는 일련의 하부 태그는 다음과 같다.

language-tag   = primary-tag *( "-" subtag )

primary-tag     = 1*8ALPHA
subtag           = 1*8ALPHA

태그 내에서는 공백 문자를 사용할 수 없고 모든 태그는 대소문자를 구별하지 않는다. 언어
태그의 이름 영역은 IANA에서 관리한다. 태그 예제는:

en, en-US, en-cockney, i-cherokee, x-pig-latin

여기서 두 자리 문자로 되어 있는 제일 앞 태그는 ISO 639 언어 축약어 형태이며, 두 자리 문
자로 되어 있는 첫 하부 태그는 ISO 3166 국가 코드이다.(위에서 마지막 세 가지 태그는 등록
되지 않은 태그이다. 마지막 태그만 향후 등록될 수 있다.)

3.11 엔터티 태그

엔터티 태그는 동일하게 요구된 자원에서 둘 또는 그 이상의 엔터티를 비교하는 데 사용한다.
HTTP/1.1 은 엔터티 태그를 ETag (14.20 절), If-Match (14.25 절), If-None-Match (14.26 절)
및 If-Range (14.27 절) 헤더 필드에서 사용한다. 사용 방법 및 캐시 검증자와의 비교에 관한
정의는 13.3.3 절에 있다. 엔터티 태그는 명쾌하지 않은 인용 문자열로 (an opaque quoted string)
구성되어 있으며 약함(weakness) 표시자가 접두사로 붙을 수 있다.

entity-tag    = [ weak ] opaque-tag

weak          = "W/"
opaque-tag    = quoted-string

"강한 엔터티 태그(strong entity tag)"는 8진수의 질이 (octet equality) 동일할 경우에만 두 엔터티
가 자원을 공유할 수 있다.

"W/" 접두사로 표시되는 "약한 엔터티 태그(weak entity tag)"는 엔터티가 동일하고 의미상 심각
한 변화 없이도 서로 대체할 수 있을 경우에만 두 엔터티가 자원을 공유할 수 있다. 약한 엔
터티 태그는 약한 비교에만 사용할 수 있다.

엔터티 태그는 반드시 특정 자원과 연관된 모든 엔터티의 모든 버전을 통틀어 유일해야 한다.
특정 엔터티 태그값을 상이한 URI에 대한 요구로부터 획득한 엔터티에 동일하다는 아무런 표
시 없이 사용할 수 있다.

[Page 29]


3.12영역 단위

HTTP/1.1 는 클라이언트가 엔터티의 일부분(특정 영역)만 응답으로 전송해 달라고 요구할 수
있다. HTTP/1.1은 Range (14.36 절) 및 Content-Range (14.17 절) 헤더 필드의 영역 단위를
사용한다. 엔터티는 여러 가지 구조적 단위 크기에 따라 여러 하부 영역으로 분리할 수 있다.

range-unit        = bytes-unit | other-range-unit

bytes-unit        = "bytes"
other-range-unit   = token

HTTP/1.1에서 정의한 유일한 영역 단위는 "바이트(bytes)"이다. HTTP/1.1의 구현 방식은 다른
단위를 사용하여 명시한 영역을 무시할 수 있다. HTTP/1.1은 영역에 대한 인식 여부에 상관없
이 애플리케이션의 구현을 허용하고 있다.

4 HTTP 메시지

4.1 메시지 유형

HTTP 메시지는 클라이언트로부터 서버로의 요구 및 서버로부터 클라이언트로의 응답으로 구
성되어 있다.

HTTP-message   = Request | Response     ; HTTP/1.1 messages

요구(5 장) 및 응답(6 장) 메시지는 엔터티를 전송(message payload)하기 위해 RFC 822 [9]의 일
반적 메시지 형식을 사용한다. 두 메시지 형식 모두는 시작 라인, 하나 또는 그 이상의 헤더
필드("헤더"라고도 알려졌다.), 헤더 필드의 끝을 표시하는 빈 라인(예를 들어 CRLF 이전에 아
무 것도 없는 라인) 및 선택 사항인 Message-Body으로 구성되어 있다.

generic-message  = start-line
                         *message-header
                         CRLF
                         [ message-body ]

start-line        = Request-Line | Status-Line

안정적인 동작(robustness)을 위해 서버는 Request-Line이 있어야 할 곳에 빈 라인을 수신하
면 이를 무시해야 한다. 다른 말로 표현 한다면, 만약 서버가 규약 스트림을 읽는 도중 메시지
처음에 CRLF를 수신하게 되면 이를 무시해야 한다.

[Page 30]


주의: HTTP/1.0 클라이언트로서 잘못 구현한 방법은 POST 요구 후 추가적인 CRLF를 생성한
다는 것이다. BNF가 분명하게 금지하고 있는 것을 다시 언급한다면 HTTP/1.1 클라이언트는
여분의 CRLF로 요구를 시작하거나 따라서는 안 된다.

4.2 메시지 헤더

Request-Header(5.3 절), Response-Header(6.2 절) 및 Entity-Header(7.1 절) 필드를 포
함하는 HTTP 헤더 필드는 RFC 822 [9] 3.1 절에서 규정한 일반적 형식을 동일하게 따르고 있
다. 각각의 헤더 필드는 콜론 (":") 및 필드값이 뒤 따르는 이름으로 구성되어 있다. 필드 이
름은 대소문자를 구분하지 않는다. 필드 값은 단일 SP가 우선적이지만 무한정한 LWS가 선행
될 수 있다. 헤더 필드는 최소한 하나의 SP 및 HT가 선행되는 여분의 라인이 선행되는 복수
의 행에 걸쳐 확장될 수 있다. 애플리케이션은 공통적인 구성 형태를 벗어난 것을 처리하지
못 하는 구현 결과도 있을 수 있기 때문에 HTTP 구조를 생성할 때 "일반적인 형식"을 따라야
한다.

message-header  = field-name ":" [ field-value ] CRLF

field-name      = token
field-value     = *( field-content | LWS )

field-content   = <필드 값을 구성하는 OCTET 이며 *TEXT 또는 토큰, tspecials,
                      인용 스트링의 결합으로 구성된다.>

다른 필드 이름으로 수신된 헤더 필드의 정렬 순서는 중요하지 않다. 그러나 General-
Header 필드를 맨 처음 나오고 Request-Header이나 Response-Header 필드가 뒤를 따
르고 마지막에 Entity-Header 필드가 나오는 것이 "바람직한 관행" 이다.

동일한 필드 이름을 가진 복수의 Message-Header 필드가 해당되는 헤더 필드의 전체
field-value가 콤마로 구분된 목록[예를 들면 #(values)]으로 규정되어 있을 경우에만 메
시지에 존재할 수 있다. 복수의 헤더 필드를 뒤 따르는 field-value를 처음에 추가하여(각
각의 값은 콤마로 구분된다) 메시지의 의미를 변화 시키지 않고 단일 "field-name: field-
value" 쌍으로 결합할 수 있어서는 안 된다. 따라서 동일한 field-name의 헤더 필드를 수
신하는 순서는 결합된 필드 값을 해석하는 데 중요하게 된다. 그러므로 프락시는 메시지를 전
송할 때 이러한 필드 값의 순서를 절대 변경해서는 안 된다.

[Page 31]


4.3 메시지 본문

HTTP 메시지의 Message-Body는 (만약 있다면) 요구 또는 응답과 관련된 Entity-Body를
전송하는 데 사용한다. Message-Body는 Transfer-Encoding 헤더 필드(14.40 절)에 설명
된 전송 코딩이 적용되었을 때에만 Entity-Body와 다르다.

message-body  = Entity-Body
                |

안전하고도 적절한 메시지 전송을 가능하게 하기 위해 애플리케이션이 적용한 전송 코딩 방식
을 표시하기 위해 반드시 Transfer-Encoding을 사용해야 한다. Transfer-Encoding은
메시지의 특성이지 엔터티의 특성이 아니기 때문에 요구/응답에 따라서 애플리케이션이 추가
또는 삭제할 수 있다.

Message-Body를 언제 메시지에서 사용할 수 있는가에 대한 규칙은 요구와 응답에 대해 각
각 다르다.

요구 메시지에 있어 Message-Body의 존재는 요구 Message-Header에 Content-Length
또는 Transfer-Encoding 헤더 필드를 포함함으로써 표시할 수 있다. Message-Body는 요
구 method(5.1.1 절)가 Entity-Body를 허용할 때만 요구 메시지에 포함할 수도 있다.

응답 메시지의 경우 Message-Body가 메시지에 포함되어 있는가의 여부는 요구 method 및
응답상태 코드(6.1.1 절) 모두에 달려 있다. HEAD 요구 method에 대한 모든 응답은 Entity-
Header 필드가 포함한 것처럼 믿게 하여도 Message-Body를 포함해서는 절대 안 된다. 모
든 1xx (Informational), 204 (No Content) 및 304 (Not Modified) 응답은
Message-Body를 절대 포함해서는 안 된다. 다른 모든 응답은 비록 길이가 제로라 할지라도
Message-Body를 포함한다.

4.4 메시지 길이

Message-Body가 메시지에 포함되어 있을 때 그 본문의 길이는 다음 중의 하나에 의해 결정
된다.(우선 순위에 따라)

1.  Message-Body를 절대 포함해서는 안 되는 모든 응답 메시지는 (1xx, 204 및 304 응답
메시지와 HEAD 요구에 대한 모든 응답) Entity-Header 필드의 존재 유무에 관계없이
헤더 필드 다음의 첫 빈 라인으로 항상 종료된다.
2.  Transfer-Encoding 헤더 필드가 (14.40 절) 존재하고 "chunked" 전송 코딩이 적용되
었음을 표시하고 있으면 길이는 chunked 인코딩에 (3.6 절) 의해 규정된다.

[Page 32]


3.  Content-Length 헤더 필드가 (14.14 절) 존재하고 그 바이트 단위의 값이 Message-
Body의 길이를 표시한다.
4.  메시지가 자신 스스로의 경계 설정 요소로서 미디어 형식 "multipart/byteranges"를
사용하고 있다면 바로 이것이 길이를 규정한다. 이 미디어 형식은 송신자가 수신측이 그
것을 분석할 수 있다는 것을 알 수 없을 때에는 절대 사용해서는 안 된다. 어떤 요구 메
시지가 복수의 Byte-Range 명시자를 가진 Range 헤더를 갖고 있으면 클라이언트가
multipart/byteranges 응답을 분석할 수 있음을 의미한다.
5.  연결을 단절하는 서버에 의하여. (연결 단절은 서버가 응답을 되돌려 줄 가능성을 전혀
남겨 두지 않기 때문에 응답 본문의 종료를 표시하는 데 사용해서는 안 된다.)

HTTP/1.0 애플리케이션과의 호환성 유지를 위해 Message-Body를 가지고 있는 HTTP/1.1 요
구는 서버가 HTTP/1.1을 따른다는 것을 알기 전에는 반드시 유효한 Content-Length 헤더
필드를 포함해야 한다. 요구가 Message-Body를 포함하고 있고 Content-Length가 주어지
지 않았으면 서버는 메시지의 길이를 결정할 수 없을 때는 400(Bad Request)을 응답으로
보내고, 계속하여 유효한 Content-Length 수신을 기다리고자 할 때는 411(Length
Required) 메시지를 반송하여야 한다.

엔터티를 수신하는 모든 HTTP/1.1 애플리케이션은 반드시 "chunked" 전송 코딩(3.6 절)을 허
용해야만 한다. 이렇게 함으로서 메시지의 길이를 미리 결정할 수 없을 때 이 메커니즘이 사
용될 수 있도록 한다.

메시지는 Content-Length 헤더 필드 및 "chunked" 전송 코딩을 모두 포함해서는 안 된다.
만약 둘 다를 수신하였으면 Content-Length는 반드시 무시해야 한다.

Message-Body가 허용된 메시지에 Content-Length가 주어졌을 때 그 필드 값은 반드시
Message-Body의 OCTET 숫자와 정확하게 일치해야 한다. HTTP/1.1 사용자 에이전트는 유효
하지 않은 길이를 수신했거나 탐지했을 때 반드시 사용자에게 이를 알려야 한다.

[Page 33]


4.5 일반 헤더 필드

요구와 응답 메시지 모두에 일반적으로 적용할 수 있지만 전송되는 엔터티에는 적용되지 않는
헤더 필드가 몇 가지 있다. 이러한 헤더 필드는 전송되는 메시지에만 적용된다.

general-header  = Cache-Control              ; 14.9 절
                   | Connection                ; 14.10 절
                   | Date                      ; 14.19 절
                   | Pragma                    ; 14.32 절
                   | Transfer-Encoding         ; 14.40 절
                   | Upgrade                  ; 14.41 절
                   | Via                       ; 14.44 절

General-Header 필드 이름을 추가하고자 한다면 HTTP 규약 버전이 변경되어야 한다. 그러
나 통신에 참여하는 모든 대상이 새로운 또는 실험적인 헤더 필드를 General-Header 필드
로 인지한다면 이들 헤더 필드를 일반 헤더의 의미로 적용할 수 있다. 인식되지 않은 헤더 필
드는 Entity-Header 필드로 처리된다.

5 요구(Request)

클라이언트로부터 서버로의 요구 메시지는 해당 메시지의 첫 라인 내에 자원, 자원의 식별자
및 사용 중인 규약 버전에 적용할 method를 포함한다.

Request          = Request-Line               ; 5.1 절
                     *( general-header          ; 4.5 절
                     | request-header           ; 5.3 절
                     | Entity-Header )          ; 7.1 절
                     CRLF
      [ message-body ]            ; 7.2 절

5.1 Request-Line

Request-Line은 method 토큰으로 시작하며 Request-URI 및 규약 버전이 뒤 따르며 CRLF
로 종결된다. 각 요소는 SP 문자로 구분된다. CR 또는 LF는 마지막 CRLF 순서 이외에는 허용
되지 않는다.

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

[Page 34]


5.1.1 Method

Method 토큰은 Request-URI로 식별되는 자원에서 수행할 method를 표시한다. method는 대
소문자를 구별한다.

Method         = "OPTIONS"               ; 9.2 절
                | "GET"                    ; 9.3 절
                | "HEAD"                  ; 9.4 절
                | "POST"                   ; 9.5 절
                | "PUT"                    ; 9.6 절
                | "DELETE"                ; 9.7 절
                | "TRACE"                 ; 9.8 절
                | extension-method

extension-method = token

자원이 허용하는 method의 목록은 Allow 헤더 필드(14.7 절)에 명시할 수 있다. 응답의 리턴
코드는 허용된 method 세트가 역동적으로 변할 수 있기 때문에 항상 method가 현재 자원에서
허용되는지 여부를 클라이언트에게 알려 준다. 서버는 서버가 method를 알고는 있으나 요구된
자원에서는 사용할 수 없을 때 상태 코드 405(Method Not Allowed)를, 서버가 method를
인지하지 못하거나 구현하지 않았을 때는 상태 코드 501(Not Implemented)을 리턴해야만
한다. 서버가 알고 있는 method의 목록은 Public Response-Header 필드(14.35 절)에 나열
할 수 있다.

GET 및 HEAD method는 모든 일반적인 목적의 서버가 반드시 지원해야 한다. 다른 모든
method는 선택적이다. 하지만 GET 및 HEAD method가 구현되었으면 반드시 9 장에 명시된 의
미와 동일하게 구현되어야 한다.

5.1.2 Request-URI(Request-URI)

Request-URI 는 보편적인 자원 식별자(3.2 절)이며 요구를 적용할 자원을 식별한다.

Request-URI    = "*" | absoluteURI | abs_path

Request-URI의 세 가지 선택 사항은 요구의 성격에 달려 있다. 별표 "*"는 요구를 특별한
자원에 적용하지 않고 서버 자체에 적용한다는 것을 의미하며 사용된 method가 반드시 자원
에 적용되는 것은 아닐 때 사용할 수 있다. 한 예를 보면;

OPTIONS * HTTP/1.1

 [Page 35]


프락시에게 요구를 만들 때는 absoluteURI 형식이 필요하다. 프락시는 유효한 캐시로부터
요구를 전송하거나 처리하여 응답을 되돌려 주어야 한다. 프락시는 absoluteURI에 명시된
대로 요구를 다른 프락시로 전송하거나 서버로 직접 전송할 수 있다는 점을 주목해야 한다.
요구가 무한 루프를 도는 것을 방지하기 위하여 프락시는 반드시 모든 별명(aliases), 지역적
변이 및 IP 주소 숫자를 포함한 모든 서버 이름을 인지할 수 있어야 한다. Request-Line의
예는 다음과 같다.

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

향후 버전 HTTP에서 모든 요구가 absoluteURI로 이전될 수 있도록 하기 위해 모든
HTTP/1.1 서버는 비록 HTTP/1.1 클라이언트가 단지 프락시에 대한 요구에서만 그것을 생산한
다 할지라도 반드시 요구의 absoluteURI 형식을 수용해야 한다.

가장 일반적인 형태의 Request-URI는 원서버나 게이트웨이의 자원을 식별하는 데 사용한다.
이 경우URI의 절대적 경로는 반드시 Request-URI처럼 전송(3.2.1절의 abs_path 참조)되
어야 하며 URI의 네트워크 위치는 반드시 Host 헤더 필드를 이용하여 전송되어야 한다. 예
를 들어 원서버에서 직접 자원을 조회하고자 하는 클라이언트는 "www.w3.org" 호스트의 포
트 80으로 TCP 접속을 한 다음 아래의 라인을 전송할 것이다.

GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.w3.org

위 내용 다음에 요구 메시지의 나머지 부분이 뒤따른다. 절대 경로는 절대 비어서는 안 된다.
원래 URI의 절대 경로가 비어있을 때에는 반드시 "/" (서버의 루트 디렉토리)를 추가한다.

프락시가 Request-URI에 아무런 경로가 없는 요구를 수신하고 명시된 method가 별표 모양
의 요구를 지원할 수 있으면 응답 메시지의 전달 경로 상의 (Request chain) 마지막 프락시는
반드시 요구 메시지에 마지막 Request-URI로서 "*"를 첨부하여 전송해야 한다. 예를 들어
다음과 같은 요구 메시지를

OPTIONS http://www.ics.uci.edu:8001 HTTP/1.1

프락시는 "www.ics.uci.edu".호스트의 포트 8001과 연결한 다음 아래와 같이 전송할 것이
다.

OPTIONS * HTTP/1.1
Host: www.ics.uci.edu:8001

Request-URI 는 3.2.1 절에서 명시한 형식으로 전송된다. 원서버는 요구를 적절히 해석하기
위하여 반드시 Request-URI를 해독해야 한다. 서버는 유효하지 않는  Request-URI를 수
신하면 적합한 상태 코드로 응답해야 한다.

[Page 36]


요구 메시지를 전송할 때 프락시는 어떤 방식으로든 위에서 설명한 것처럼 비어 있는 절대 경
로를 "*"로 대체하는 것 외에는 프락시 내부의 구현 방법에 관계없이 절대로 Request-URI
의 "abs_path" 부분을 재작성해서는 안 된다.

주의 : "재작성 금지" 규칙은 원서버가 특정 목적을 위해서 예약되지 않은 URL 문자를 적절
하게 사용하지 못하고 있을 때 요구의 의미를 변경하지 못하도록 한다. 구현자는 몇몇
HTTP/1.1 이전의 프락시는 Request-URI를 재작성하는 것으로 알려져 있음을 인식하고 있
어야만 한다.

5.2 요구에 의해 식별되는 자원

HTTP/1.1 원서버는 인터넷 요구가 식별하는 정확한 자원은 Request-URI 및 Host 헤더 필드
모두를 조사하여 결정된다는 것을 인지하고 있어야 한다.

요구받은 호스트와 다른 자원을 허용하지 않는 원서버는 Host 헤더 필드 값을 무시할 수 있
다. (그러나 HTTP/1.1에서의 Host 지원에 관한 다른 필요 조건에 관하여는 19.5.1절을 참조한
다.)

요구받은 호스트에 기초하여 자원을 구별하는 원서버(때로 가상 호스트 또는 허영 호스트 이
름이라고 불린다)는 HTTP/1.1 요구에 대한 자원을 결정할 때 다음의 규칙을 반드시 따라야 한
다.

1.  Request-URI 가 absoluteURI이면 호스트는 Request-URI의 일부분이다. 요구의
어떠한 Host 헤더 필드 값도 반드시 무시해야 한다.
2.  Request-URI 가 absoluteURI가 아니면 요구는 Host 헤더 필드를 포함한다. 호스
트는 Host 헤더 필드 값으로 결정된다.
3.  규칙 1, 2에 의하여 지정된 호스트가 서버의 유효한 호스트가 아니면 응답은 반드시
400(Bad Request) 에러 메시지이어야 한다.

Host 헤더 필드가 없는 HTTP/1.0의 수신측은 정확하게 무슨 자원을 요구했는지 결정하기 위
해 발견법을 (heuristics - 예를 들어 유일한 무엇인가의 특별한 호스트로의 URI 경로를 검사)
사용할 수도 있다.

5.3 요구 헤더 필드

요구 헤더 필드는 요구 및 클라이언트 자신에 관한 추가 정보를 클라이언트가 서버에게 전달
할 수 있도록 한다. 이 필드는 프로그래밍 언어 method 호출시 사용하는 파라미터와 동일한
의미로 요구 변경자(request modifiers)의 역할을 수행한다.

[Page 37]


request-header  = Accept                     ; 14.1 절
                   | Accept-Charset             ; 14.2 절
                   | Accept-Encoding            ; 14.3 절
                   | Accept-Language            ; 14.4 절
                   | Authorization               ; 14.8 절
                   | From                       ; 14.22 절
                   | Host                       ; 14.23 절
                   | If-Modified-Since          ; 14.24 절
                   | If-Match                   ; 14.25 절
                   | If-None-Match              ; 14.26 절
                   | If-Range                   ; 14.27 절
                   | If-Unmodified-Since        ; 14.28 절
                   | Max-Forwards              ; 14.31 절
                   | Proxy-Authorization        ; 14.34 절
                   | Range                      ; 14.36 절
                   | Referer                    ; 14.37 절
                   | User-Agent                 ; 14.42 절

Request-Header 필드 이름은 규약 버전의 변경과 함께 확장했을 때만 신뢰성 있게 확장될
수 있다. 그러나 통신에 참여하는 모든 대상이 그것을 Request-Header 필드로 인지한다면
새롭거나 실험적인 헤더 필드에 요구 헤더의 의미를 적용할 수 있다. 인정되지 않은 헤더 필
드는 Entity-Header 필드로 처리된다.

6 응답

요구 메시지를 수신하고 해석한 후 서버는 HTTP 응답 메시지로 응답한다.

Response      = Status-Line                  ; 6.1 절
                *( general-header            ; 4.5 절
                | response-header            ; 6.2 절
                | Entity-Header )             ; 7.1 절
                CRLF
   [ message-body ]             ; 7.2 절

6.1 상태 라인(Status-Line)

응답 메시지의 첫 라인은 상태 라인이다. 상태 라인은 규약 버전과 이에 뒤따르는 숫자 상태
코드 및 연관된 텍스트 문구로 구성되어 있으며 각 요소는 SP 문자로 구분된다. CR 또는 LF
는 마지막 CRLF에만 허용된다.

[Page 38]


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

6.1.1 상태 코드 및 이유 문구

Status-Code(상태 코드) 요소는 요구 메시지를 이해하고 이에 따라 서비스를 제공하려는 데
에 대한 결과로서 세 자리의 정수 코드이다. 이 코드는 10장에 모두 정의되어 있다. Reason-
Phrase(이유 문구)는 상태 코드에 대해 짧은 텍스트 형태의 설명을 제공하기 위해 사용한다.
상태 코드는 오토마타(automata)가 사용하고 이유 문구는 인간 사용자가 사용하기 위해서이다.

상태 코드의 첫 자리 숫자는 응답의 클래스를 규정하며 마지막 두 자리 숫자는 아무런 구분
역할을 가지고 있지 않다. 첫 자리에는 다섯 가지의 숫자가 올 수 있다.

? 1xx: 알림 정보 (Informational) ? 요구가 수신되어 계속 처리

? 2xx: 성공 (Success) ? 요구 메시지를 성공적으로 수신 및 해석을 하고 이를 허용

? 3xx: 방향 재설정 (Redirection) ? 요구에 대한 처리를 완료하기 위하여 추가 조치가 필

? 4xx: 클라이언트 오류 (Client Error) ? 요구 메시지가 잘못된 형식으로 구성되어 있기나
제대로 처리할 수 없는 경우

? 5xx: 서버 오류 (Server Error) ? 명백히 유효한 요구 메시지를 서버가 처리할 수 없을 때

HTTP/1.1이 규정한 숫자 상태 코드의 개별적인 값 및 이에 상응하는 Reason-Phrase의 예가 아
래에 제시되어 잇다. 여기에 열거된 이유 구문은 단지 권고 사항일 뿐이다. - 이유 구문은 규
약에 영향을 미치지 않고도 지역적인 등가물(equivalents)로 대체할 수 있다.

Status-Code    = "100"   ; Continue(계속)
                 | "101"   ; Switching Protocols(규약 전환)
                 | "200"   ; OK
                 | "201"   ; Created(생성 되었음)
                 | "202"   ; Accepted(접수 되었음)
                 | "203"   ; Non-Authoritative Information(비 인증 정보)
                 | "204"   ; No Content (내용이 없음)
                 | "205"   ; Reset Content(내용을 지움)
                 | "206"   ; Partial Content(부분 내용)
                 | "300"   ; Multiple Choices(복수 선택)
                 | "301"   ; Moved Permanently(영구 이동)
                 | "302"   ; Moved Temporarily(임시 이동)

[Page 39]


                 | "303"   ; See Other(다른 것을 참조)
                 | "304"   ; Not Modified(변경되지 않았음)
                 | "305"   ; Use Proxy(프락시를 사용할 것)
                 | "400"   ; Bad Request(잘못된 요구)
                 | "401"   ; Unauthorized(인증되지 않았음)
                 | "402"   ; Payment Required(요금 지불 요청)
                 | "403"   ; Forbidden(금지되었음)
                 | "404"   ; Not Found(찾을 수 없음)
                 | "405"   ; Method Not Allowed(method를 사용할 수 없음)
                 | "406"   ; Not Acceptable (접수할 수 없음)
                 | "407"   ; Proxy Authentication Required(프락시 인증 필요)
                 | "408"   ; Request Time-out(요구 시간 초과)
                 | "409"   ; Conflict(충돌)
                 | "410"   ; Gone(내용물이 사라졌음)
                 | "411"   ; Length Required(길이가 필요함)
                 | "412"   ; Precondition Failed(사전 조건 충족 실패)
                 | "413"   ; Request Entity Too Large (요구 엔터티가 너무 큼)
                 | "414"   ; Request-URI Too Large(Request-URI가 너무 김)
                 | "415"   ; Unsupported Media Type(지원되지 않는 미디어 유형)
                 | "500"   ; Internal Server Error(서버 내부 에러)
                 | "501"   ; Not Implemented(구현되지 않았음)
                 | "502"   ; Bad Gateway(불량 게이트웨이)
                 | "503"   ; Service Unavailable(서비스를 사용할 수 없음)
                 | "504"   ; Gateway Time-out(게이트웨이 시간 초과).
                 | "505"   ; HTTP Version not supported (지원되지 않는 HTTP 버
전)
                 | extension-code
extension-code   = 3DIGIT

Reason-Phrase    = *

HTTP상태 코드는 확장할 수 있다. HTTP 애플리케이션이 반드시 모든 등록된 상태 코드의 의
미를 이해할 필요는 없다.(이것이 분명 바람직하기는 하다.) 그러나 애플리케이션은 반드시 첫
단위가 표시하는 상태 코드의 클래스를 이해해야 하며 인식할 수 없는 응답은 해당 클래스의
x00 상태 코드와 동일한 것으로 처리해야 한다. 인식되지 않은 응답은 절대 캐시해서는 안 된
다. 예를 들어 클라이언트가 인식되지 않은 상태 코드 431을 수신하였으면 클라이언트는 요구
에 무엇인가 잘못이 있었으며 응답을 400 상태 코드로 수신한 것으로 안전하게 가정할 수 있
다. 이러한 경우 사용자 에이전트는 응답과 함께 리턴 된 엔터티를 사용자에게 제시해야 한다.
엔터티는 대개 사람이 읽을 수 있는 정보(비 정상적인 상태를 설명하는 정보)를 포함하고 있
기 때문이다.
 [Page 40]


6.2 응답 헤더 필드

응답 헤더 필드는 서버가 Status-Line에 표시할 수 없는 응답에 대한 추가 정보를 전달할
수 있도록 한다. 이러한 헤더 필드는 서버와 Request-URI가 식별하는 자원에 추가적으로
접근하는 방법에 대한 정보를 제공한다.

response-header  = Age                     ; 14.6 절
     | Location               ; 14.30 절
      | Proxy-Authenticate    ; 14.33 절
     | Public                 ; 14.35 절
     | Retry-After             ; 14.38 절
     | Server                 ; 14.39 절
     | Vary                   ; 14.43 절
      | Warning                ; 14.45 절
     | WWW-Authenticate     ; 14.46 절

Response-header 필드 이름은 규약 버전의 변경과 함께 확장했을 때만 신뢰성 있게 확장될
수 있다. 그러나 새로운 또는 실험적으로 사용하는 헤더 필드에 응답 헤더의 의미를 적용할
수 있는데, 이 경우는 통신에 참여하는 모든 대상이 그것을 response-header 필드로 인식
할 수 있을 때만 가능하다. 인식할 수 없는 헤더 필드는 Entity-Header 필드로 처리된다.

7 엔터티(Entity)

요구와 응답 메시지는 별도로 요구 method나 응답 상태 코드에 의하여 제한을 받지 않는 한
엔터티를 전송할 수도 있다. 어떤 응답은 엔터티 헤더만을 포함할 수도 있지만 엔터티는
Entity-Header 필드와 Entity-Body로 구성되어 있다.

이 절에서 송신자와 수신자는 누가 엔터티를 발송하고 누가 엔터티를 수신하는가에 따라 클라
이언트와 서버 어느 쪽이든지 지칭할 수 있다.

7.1 엔터티 헤더 필드

엔터티 헤더 필드는 Entity-Body에 대한 또는 본문이 없다면 요구 메시지를 통해 확인할
수 있는 자원에 대한 선택적인 메타 정보를 정의하고 있다.

[Page 41]


Entity-Header   = Allow                    ; 14.7 절
   | Content-Base             ; 14.11 절
   | Content-Encoding        ; 14.12 절
   | Content-Language        ; 14.13 절
   | Content-Length           ; 14.14 절
   | Content-Location         ; 14.15 절
   | Content-MD5             ; 14.16 절
   | Content-Range            ; 14.17 절
   | Content-Type             ; 14.18 절
   | ETag                     ; 14.20 절
   | Expires                  ; 14.21 절
   | Last-Modified            ; 14.29 절
   | extension-header

extension-header = message-header

Extension-Header 메커니즘은 규약을 변경하지 않고도 추가적인 Entity-Header 필드를
정의할 수 있게 한다. 그러나 이러한 필드를 수신자가 인식할 수 있다고 가정할 수는 없다. 인
식할 수 없는 필드는 수신측이 무시해야 하며 프락시를 통하여 전송한다.

7.2 엔터티 본문 (Entity Body)

HTTP 요구나 응답과 함께 발송된 (만약 있다면) Entity-Body는 Entity-Header 필드에서
규정한 포맷 및 인코딩에 따른다.

Entity-Body    = *OCTET

Entity-Body는 4.3 절에서 설명한 대로 Message-Body가 있을 때만 메시지 내에 존재한다.
안전하고 적절한 메시지 전송을 위해 적용되었을 수도 있는 Transfer-Encoding을 해독하
여 Message-Body에서 Entity-Body를 얻을 수 있다.

7.2.1 유형 (Type)

메시지에 Entity-Body가 포함되어 있으면 해당 본문의 데이터 타입은 Content-Type 및
Content-Encoding 의 헤더 필드를 통하여 결정된다. 이는 2 계층의 순서가 정해진 인코딩
모델을 규정한다.

Entity-Body  := Content-Encoding( Content-Type( data ) )

Content-Type은 메시지 본문 내용의 미디어 형식을 명시한다. Content-Encoding 은 대개
데이터를 압축할 목적으로 데이터에 적용된 추가적인 내용 코딩(요구된 자원의 속성이다)을
표시하는 데 사용할 수 있다.
 [Page 42]


Entity-Body를 포함하고 있는 모든 HTTP/1.1 메시지는 해당 본문의 미디어 형식을 규정하
는 Content-Type 헤더 필드를 포함하여야 한다. Content-Type 필드가 미디어 형식 정보를
제공하지 않는 경우에만 수신측은 자원을 확인하는 데 사용되는 URL 이름 확장자 및/또는 내
용 검사를 통하여 미디어 형식을 짐작하려 시도할 수도 있다. 계속 미디어 형식을 알 수 없다
면 수신측은 그것을 "application/octet-stream" 유형으로 처리해야만 한다.

7.2.2 길이

Entity-Body의 길이는 모든 전송 인코딩(Transfer-Coding)이 디코딩된 후의 Message-
Body의 길이이다. 4.4 절은 Message-Body의 길이를 결정하는 방법을 규정하고 있다.

8 접속(Connections)

8.1 지속형 연결(Persistent Connections)

8.1.1 목적

지속형 연결 개념이 등장하기 이전에는 각 URL의 정보를 가져오기 위해 매번 별도의 TCP
연결을 설정하여 HTTP 서버의 부하를 증가시키고 인터넷의 트래픽 혼잡을 유발했었다. 하이
퍼링크되어 있는 이미지와 및 기타 관련 데이터의 사용은 종종 클라이언트가 아주 짧은 시간
에 여러 개의 요구를 동일한 서버에 하도록 만들 수 있다. 이러한 성능 문제에 대한 분석을
[30][27]에서 참고할 수 있으며, 프로토타입 구현의 분석 및 결과를 [26]에서 참고할 수 있다.

지속형 HTTP 접속은 여러 가지 이점이 있다.

? TCP 연결을 시작하고 종료하는 회수를 줄임으로써 CPU 시간을 줄이고 TCP 규약 제어
블록에 사용되는 메모리를 절약할 수 있다.
? HTTP 요구와 응답이 연결선 상에서 파이프라인 될 수 있게 한다. 파이프라인을 사용하
면 클라이언트는 각 응답을 기다리지 않고도 복수의 요구를 할 수 있어 하나의 TCP 연
결을 효과적으로 빠른 시간 내에 이룩할 수 있다.
? TCP를 시작할 때 발생하는 패킷의 숫자를 감소시키고 네트워크의 혼잡 상태를 결정할
충분한 시간을 TCP에 주어 네트워크 혼잡을 줄일 수 있다.
? 오류가 발생해도 TCP 접속을 단절하지 않고도 이를 보고할 수 있기 때문에HTTP가 좀
더 잘 작동될 수 있도록 한다. HTTP 향후 버전을 사용하는 클라이언트는 새로운 기능을
시도할 수 있으나 이전 서버와 통신을 할 때 에러가 발생하면 이전 버전으로 재시도한
다.

HTTP 구현은 지속형 연결을 구현해야 한다.

[Page 43]


8.1.2 전반적인 운영

HTTP/1.1과 이전 버전의 HTTP의 큰 차이점은 지속적인 접속이 모든 HTTP 접속의 기본 방식
이라는 것이다. 별도의 표시가 없으면 클라이언트는 지속적인 접속을 유지한다고 가정한다.

지속적인 접속은 클라이언트와 서버가 TCP 연결 종결을 알릴 수 있는 메커니즘을 제공한다.
이러한 알림은 Connection 헤더 필드를 이용한다. 종료 신호가 통보되면 클라이언트는 더 이상
해당 연결에 요구를 보내서는 안 된다.

8.1.2.1 협상(Negotiation)

HTTP/1.1 서버는 요구 메시지에 "종료" Connection-Token이 포함된 Connection 헤더가 발송되지
않는 한 HTTP/1.1 클라이언트는 지속적인 접속을 유지하고자 한다고 가정한다. 서버가 응답을
발송한 후 곧 바로 연결을 종료하고자 한다면 종료 Connection-Token이 포함된 Connection 헤
더를 발송해야만 한다.

HTTP/1.1 클라이언트는 접속이 계속 유지되기를 기대하지만 서버로부터의 응답이 종료
Connection-Token의 Connection 헤더를 포함하고 있는가 여부에 따라 접속 유지 여부를 결정할
수도 있다. 클라이언트가 해당 요구 이상의 접속을 유지하기 원치 않는다면 클라이언트는 종
료 Connection-Token이 포함된 Connection 헤더를 발송해야 한다.

클라이언트 또는 서버가 Connection 헤더에 종료 토큰을 발송하면 해당 요구는 접속에 대한
마지막 요구가 된다.

클라이언트나 서버는 명확하게 표시되지 않는 한 1.1 이전의 HTTP 버전에서 지속적인 접속이
유지된다고 가정해서는 안 된다. HTTP/1.0 클라이언트와의 호환성 유지에 관한 정보는 19.7.1
절을 참조한다.

지속적으로 유지되기 위해서 연결선 상의 모든 메시지는 4.4 절에서 설명된 스스로 정의된 메
시지 길이(예를 들면 접속 종료에 의해 규정되지 않는)를 포함하고 있어야 한다.

8.1.2.2 파이프라인 사용

지속적인 접속을 지원하는 클라이언트는 요구를 파이프라인(복수의 요구를 각각의 응답을 기
다리지 않고 발송)할 수 있다. 서버는 반드시 이러한 요구에 대한 응답을 요구가 수신된 동일
한 순서로 발송해야 한다.

[Page 44]


접속된 후 곧 바로 지속적인 접속이나 파이프라인(pipeline)을 예상하는 클라이언트는 첫 파이
프라인 시도가 실패할 경우 재시도할 준비가 되어 있어야 한다. 클라이언트가 재시도를 했을
때 접속이 지속적인지 알기 전에는 파이프라인 기능을 절대로 사용해서는 안 된다. 클라이언
트는 서버가 모든 상응하는 응답을 발송하기 전에 접속이 종료되었으며 재발송할 준비가 되어
있어야만 한다.

8.1.3 프락시 서버

프락시가 14.2.1 절에 명시된 Connection 헤더 필드의 특성을 정확하게 구현하는 것이 특히 중
요하다.

프락시 서버는 연결하고 있는 클라이언트와 원서버(또는 다른 프락시 서버)의 지속적인 접속
을 반드시 구분하여 알려야 한다. 각각의 지속적 접속은 단지 하나의 전송 링크에만 적용한다.

프락시 서버는 절대 HTTP/1.0과 지속적인 접속을 설정해서는 안 된다.

8.1.4 실제적인 고려 사항

서버는 대개 비활성 접속을 더 이상 유지하지 않을 시간 초과 값을 가지고 있다. 프락시 서버
는 클라이언트가 동일한 서버를 통하여 더 많은 접속을 설정하기 쉽기 때문에 이 값을 더 높
게 할 수 있다. 지속적인 접속의 사용은 클라이언트나 서버의 시간 초과 길이에 어떠한 필요
조건을 두지 않는다.

클라이언트 또는 서버가 시간 초과 기능을 사용하고자 할 때 전송 접속 상에 종료를 알려야
한다. 클라이언트와 서버는 전송 선상의 다른 쪽의 접속 종료를 항상 주시하고 있다가 적절하
게 반응하여야 한다. 클라이언트 또는 서버가 다른 쪽의 종료를 신속하게 감지하지 못하면 네
트워크 상의 불필요한 자원 낭비를 초래하게 된다.

클라이언트, 서버 또는 프락시는 언제든지 전송 접속을 종료할 수 있다. 예를 들어 클라이언트
는 서버가 "사용하지 않는" 접속을 종료하기로 결정한 바로 그 순간에 새로운 요구 발송을 시
작했을 수 있다. 서버 관점에서 보면 접속은 사용하지 않고 있는 동안은 종료되고 있는 것이
며 클라이언트의 관점에서 보면 요구가 처리되고 있는 것이다.

이는 클라이언트, 서버 및 프락시가 반드시 동시 종료 이벤트에서 회복할 수 있어야 한다는
것을 의미한다. 클라이언트 소프트웨어는 전송 접속을 재개할 수 있어야 하며 요구 method가
멱등원(冪等元) method(9.1.2 절 참조)일 경우 사용자와의 상호 작용 없이도 중단된 요구를 재
전송할 수 있어야 한다. 다른 method는 사용자 에이전트가 인간 운영자에게 요구를 재시도할
수 있는 선택권을 줄 수도 있지만 자동적으로 재시도해서는 안 된다.

[Page 45]


그러나 두 번째 요구가 실패할 경우 자동적인 재시도를 반복해서는 안 된다.

서버는 가능하다면 항상 한 접속 건 당 최소한 하나의 요구에 응답해야 한다. 서버는 네트워
크나 클라이언트 실패가 발생할지도 모르는 상황이 아니면 응답을 전송하는 도중에 접속을 종
료해서는 안 된다.

지속적인 접속을 사용하는 클라이언트는 특정 서버로의 동시 접속 숫자에 제한을 두어야 한다.
단독 사용자 클라이언트는 최대 2 개의 서버나 프락시 접속을 유지해야 한다. 프락시는 최대
2*N 개의 서버나 프락시 접속을 할 수 있으며 여기서 N은 사용하고 있는 동시 사용자의 숫
자이다. 이러한 지침은 HTTP 응답 시간을 향상하고 인터넷이나 다른 네트워크의 혼잡을 피하
기 위함이다.

8.2 메시지 전송 필요 조건

일반적인 필요 조건:

? HTTP/1.1 서버는 지속적인 접속을 유지하고 있어야 하며 일시적인 오버로드(overloads)를 완화
시키기 위하여 클라이언트가 재시도할 것이라는 예상으로 접속을 종결하기보다는 흐름 제어
메커니즘을 사용해야 한다. 후자의 방법을 사용하면 네트워크 혼잡이 가중될 수 있다.

? Message-Body를 발송하는 HTTP/1.1 (또는 이후) 클라이언트는 요구를 전송하는 동안 네트워크
접속에 에러가 발생하는지 점검해야 한다. 클라이언트가 에러를 감지하였으면 본체 전송을
즉시 중단해야 한다. 본체가 "덩어리" 인코딩(3.6 절) 기법을 사용하여 전송되고 있을 경우에
는 제로 길이의 덩어리와 비어 있는 주석을 사용하여 메시지의 종료를 조기에 표시할 수도
있다. 본문에 앞서 Content-Length 헤더가 있으면 클라이언트는 접속을 종료해야 한다.
? HTTP/1.1 (또는 이후) 클라이언트는 정상적인 응답이 뒤 따르는 100(Continue) 상태 메시지를
접수할 준비가 반드시 되어 있어야 한다.

? HTTP/1.0 (또는 이전) 클라이언트로부터 요구를 수신한 HTTP/1.1 (또는 이후) 서버는 100
(Continue) 응답 메시지를 전송해서는 안 된다. 서버는 요구가 정상적으로 완료될 때까지(이렇
게 하여 중단된 요구가 발생하지 않도록 함) 기다리던가 조기에 접속을 종료해야 한다.

[Page 46]


HTTP/1.1 (또는 이후) 클라이언트로부터 이러한 필요 조건을 만족해야 하는 method를 수신하
면 HTTP/1.1 (또는 이후) 서버는 반드시 100 (Continue) 상태로 응답하고 입력 스트림에서 계속
적으로 요구를 읽어 들이든지 에러 상태 코드로 응답해야 한다. 에러 상태 코드로 응답하였으
면 전송(TCP) 접속을 종료하던지 또는 계속적으로 요구를 읽어 들이고 요구의 나머지 부분을
폐기할 수 있다. 에러 상태 코드를 리턴했을 때는 요구 받은 method를 절대로 처리해서는 안
된다.

클라이언트는 최소한 가장 최근에 사용된 서버의 버전 숫자를 기억하고 있어야 한다. HTTP/1.1
클라이언트가 HTTP/1.1 또는 이후의 응답을 서버로부터 얻고 서버로부터 상태 메시지를 수신
하기 전에 연결이 종료되었으면 클라이언트는 요구 method가 멱등원(冪等元) method(9.1.2 절
참조)이 아닌 이상 사용자와의 상호 작용 없이 요구를 재시도해야 한다. 사용자 에이전트가
인간 운영자에게 요구를 재시도할 선택권을 줄 수는 있지만 다른 method를 자동적으로 재시
도해서는 안 된다. 클라이언트가 요구를 재시도 했으면 클라이언트는

? 반드시 먼저 요구 헤더 필드를 발송해야 하며 그런 다음
 
? 서버가 100 (Continue) 응답(이 경우 클라이언트는 계속 진행해야 한다)이나 에러 코드를
응답할 때 까지 반드시 기다려야 한다.

HTTP/1.1 클라이언트가 HTTP/1.1이나 이후 응답을 서버로부터 얻지 못하면 서버가 HTTP/1.0
이나 이전 버전을 구현하고 있으면 100 (Continue) 응답을 사용하지 않을 것으로 가정해야 한
다. 이 경우 클라이언트가 서버로부터 상태 메시지를 접수하기 전에 접속이 종료되면 클라이
언트는 요구를 재시도해야 한다. 클라이언트가 이 HTTP/1.0 서버에 요구를 재시도할 때 아래
의 "바이너리 지수 백오프(binary exponential backoff)" 알고리즘을 사용하여 신뢰할 수 있는 응
답을 얻었음을 확인해야 한다.

1.  서버로 새로운 접속을 시작한다.
 
2.  Request-Header을 전송한다.
 
3.  변수 R을 서버로의 예상 왕복 여행 시간으로 초기화한다.(예를 들면 접속을 설정하기 위
해 소요되는 시간에 기초한다)
 
4.  T = R * (2**N)을 계산한다. 이때 N은 이 요구를 이전에 재시도한 숫자이다.
 
5.  서버로부터 에러 응답을 기다리던가 T 초 동안 기다린다. (어떤 것이든 먼저 오는 것)

[Page 47]


6.  아무런 에러 응답도 수신되지 않았으면 T 초가 경과한 후 요구의 본문을 전송한다.
 
7.  클라이언트가 접속이 조기에 종료되는 것을 알았으면 요구가 접수되었거나, 에러 응답을
수신하였거나 또는 사용자가 더 이상 기다릴 수 없어 재시도 절차를 종료할 때 까지 첫
스텝부터 계속한다.

서버 버전에 관계없이 에러 상태가 접수되었으면 클라이언트는

? 절대로 계속해서는 안 되며
 
? 메시지 전송을 완료하지 않았으면 접속을 반드시 종료해야 한다.

다른 어떤 상태 메시지를 접수하기 이전에 100 (Continue)을 수신한 후 접속을 종료한 것을 인
지한 HTTP/1.1 (또는 이후) 클라이언트는 요구를 재시도해야 하며 100 (Continue) 응답을 기다릴
필요가 없다.(그러나 이것이 구현 방법을 단순하게 한다면 기다려도 된다.)

9 Method 정의

HTTP/1.1에서 사용되는 일반적인 method 세트를 아래에 규정하였다. 이 세트를 확장할 수 있
지만 추가된 method를 별도로 확장된 클라이언트와 서버가 동일한 의미를 공유하고 있다고
가정할 수 없다.

호스트 Request-Header 필드(14.23 절)는 반드시 모든 HTTP/1.1 요구를 따라야 한다.

9.1 안전 및 멱등원(冪等元) method

9.1.1 안전 method

구현자는 소프트웨어가 사용자와의 상호작용이 인터넷을 통하여 표시된다는 점을 인지해야 하
며 사용자에게 자신이 취하는 행동이 자신과 다른 사용자에게 예상하지 못한 중요성을 가질
수 있다는 점을 인지시키도록 주의해야 한다.

특히 GET 및 HEAD method가 조회 이외의 작업을 수행하는 중요성을 가져서는 안 된다는 관
례가 확립되었다. 이러한 method는 안전한 것으로 간주해야 한다. 이렇게 하여 사용자 에이전
트가 POST, PUT 및 DELETE와 같은 다른 method를 특별한 방식으로 표현할 수 있게 하며
사용자가 안전하지 못한 처리를 요구하고 있다는 사실을 인식할 수 있게 한다.

당연히 서버가 GET 요구를 수행한 결과로서 부작용을 발생하지 않고 있음을 보장할 수 없다.
[Page 48]


사실상 몇몇 역동적인 자원은 이것을 하나의 기능으로 보고 있다. 중요한 구별 점은 사용자가
부작용을 요청하지 않았기 때문에 부작용에 대한 책임을 부과할 수는 없다는 것이다.

9.1.2 멱등원(冪等元) method

Method는 또한 N > 0 과 동일한 요구의 부작용이 단일 요구의 부작용과 동일하다는 점에서
"멱등원" 특성을 가질 수 있다.(에러 또는 만기일의 문제는 별도로 하고)  GET, HEAD, PUT 및
DELETE method는 이 특성을 공유하고 있다.

9.2 OPTIONS

OPTIONS method는 Request-URI에 의하여 식별되는 Request/Response chain에서 사용할 수 있
는 통신 선택 사항에 관한 정보 요구를 표시한다. 이 method는 클라이언트가 자원 처리를 시
도하거나 자원 조회를 시작하지 않고도 선택 사항 및/또는 자원과 관련된 필요 조건, 서버의
처리 능력을 결정할 수 있게 한다.

서버의 응답이 에러가 아닌 이상 응답은 통신 선택 사항이라고 간주할 수 있는 것 이외의 엔
터티 정보를 포함해서는 안 된다.(예를 들어 Allow 는 적합하지만 Content-Type은 적합하지 않
다).

Request-URI 가 별표("*")이면 OPTIONS 요구는 전체를 서버에 적용하려는 것이다. 200 응답은
모든 적용 가능한 일반 필드 또는 Response-Header 필드 이외에 이 규격에서 규정하지 않는
모든 확장을 포함하여 서버가 구현한(예 Public) 선택 기능을 표시하는 모든 헤더 필드를 포함
해야 한다. 5.1.2 절에서 설명된 것처럼  "OPTIONS *" 요구는 경로 정보 없이 Request-URI에
목적지 서버를 명시함으로써 프락시를 통하여 적용할 수 있다.

Request-URI가 별표가 아니면 OPTIONS 요구는 해당 자원과 통신할 때 사용할 수 있는 선택
사항에만 적용된다. 200 응답은 모든 적용 가능한 일반 필드 또는 Response-Header 필드 이외
에 이 규격에서 규정하지 않는 모든 확장을 포함하여 서버가 구현한(예 Allow) 선택 기능을
표시하는 모든 헤더 필드를 포함해야 한다. OPTIONS 요구가 프락시를 통한다면 프락시는 프
락시의 성능에 관계되는 선택 사항 및 프락시를 통하여 사용할 수 없는 것으로 알려진 선택
사항을 제외할 수 있도록 응답을 반드시 편집해야 한다.

[Page 49]


9.3 GET

GET method는 Request-URI가 식별하는 모든 정보(엔터티의 형태로)를 조회한다는 것을 의미
한다. Request-URI가 데이터를 생성하는 프로세스를 참조한다면 텍스트가 우연히 프로세스의
산출물이 아닌 이상 엔터티로서 리턴 되는 것은 프로세스의 소스 텍스트가 아니라 생성된 데
이터이다.

GET method의 의미는 요구 메시지가 If-Modified-Since, If-Unmodified-Since, If-Match, If-None-
Match 또는 If-Range 헤더 필드를 포함하고 있으면 "조건적인 GET"으로 변화한다. 조건적인
GET method는 엔터티가 조건 헤더 필드가 명시한 조건 하에서만 전송되도록 요청하는 것이다.
조건적 GET method는 복수의 요구나 클라이언트가 이미 보유하고 있는 데이터를 전송하지 않
고도 캐시 된 엔터티를 갱신할 수 있도록 함으로서 불필요한 네트워크 사용을 감소시키기 위
해 사용한다.

GET method의 의미는 요구 메시지가 Range 헤더 필드를 포함하고 있으면 "부분적인 GET"으
로 변화한다. 부분적인 GET method는 14.36 절에 설명된 것처럼 엔터티의 일 부분만 전송하도
록 요청하는 것이다. 부분적 GET method는 클라이언트가 이미 보유하고 있는 데이터를 전송
하지 않고도 부분적으로 조회한 엔터티가 완성될 수 있도록 함으로써 불필요한 네트워크 사용
을 감소시키기 위해 사용한다.

GET 요구에 대한 응답은 13 장에 설명된 대로 HTTP 캐시 요구 필요 조건을 만족할 경우에만
캐시할 수 있다.

9.4 HEAD

HEAD method는 서버가 응답 메시지에 Message-Body를 반드시 리턴해야 한다는 것 이외에는
GET과 동일하다. HEAD 요구에 대한 응답으로 HTTP 헤더에 포함된 메타 정보는 GET 요구에
대한 응답으로 발송된 정보와 반드시 동일해야 한다. 이 method는 Entity-Body 자체를 전송하
지 않고도 요구가 내포하는 엔터티에 대한 메타 정보를 얻는 데 사용할 수 있다. 이 method는
종종 하이퍼텍스트 링크의 유효성, 접근성 및 최근의 변경 사항을 테스트하기 위해 사용된다.

HEAD 요구에 대한 응답은 응답에 포함된 정보를 해당 자원의 이전 캐시 엔터티를 갱신하는
데 사용할 수 있다는 의미에서 캐시할 수 있다. 새로운 필드 값이 캐시 된 엔터티가 현재 의
엔터티 (Content-Length, Content-MD5, ETag 또는 Last-Modified의 변화에 의해 표시되는 것과 같
은)와 상이함을 표시할 때는 캐시는 반드시 이 캐시 엔트리를 낡을 것으로 취급해야 한다.

[Page 50]


9.5 POST

POST method는 서버에게 Request-Line의 Request-URI가 식별하는 자원의 새로운 부속물로서
요구에 포함된 엔터티를 접수할 것을 요구하는 데 사용한다. POST는 다음의 기능을 수행하는
일관된 method를 사용할 수 있도록 디자인 되었다.

? 기존 자원의 주해;
 
? 게시판, 뉴스그룹, 편지 발송 목록 또는 유사한 기사 그룹으로 메시지를 송부;
 
? 폼을 제출한 결과로 발생한 데이터 블록을 데이터 처리 프로세스에 제공;
 
? 추가 작업을 통한 데이터 베이스의 확장.

POST method가 실제적으로 수행하는 기능은 서버가 결정하며 보통 Request-URI에 달려 있다.
발송된 엔터티는 파일이 파일을 포함하고 있는 디렉토리에 종속되고, 뉴스 기사가 발송한 뉴
스그룹에 종속되며 레코드가 데이터 베이스에 종속되듯이 해당 URI에 종속된다.

POST method가 수행하는 작업이 URI로 식별할 수 있는 자원을 생성하지 않을 수도 있다. 이
러한 경우 응답이 결과를 설명하는 엔터티를 포함하고 있는가 여부에 따라 200(OK)이나
204(No Content)가 적절한 응답 상태이다.

새로운 자원이 원서버에서 생성되었다면 응답은 201(Created)이어야 하고 요구의 상태를 설명
하며 새로운 자원 및 Location 헤더 (14.30 절 참조)를 지칭하는 엔터티를 포함해야 한다.

이 method에 대한 응답은 응답이 적절한 Cache-Control 또는 Expires 헤더 필드를 포함하지 않
는 한 캐시할 수 없다. 그러나 303(See Other) 응답을 사용하여 사용자 에이전트에게 캐시할 수
있는 자원을 조회하도록 지시할 수 있다.

POST 요구는 8.2 절에 설정된 메시지 전송 필요 조건을 반드시 따라야 한다.

[Page 51]


9.6 PUT

PUT method는 동봉된 엔터티를 제공된 Request-URI에 저장하도록 요구한다. Request-URI가 이
미 존재하는 자원을 지칭할 경우 동봉된 엔터티는 원서버에 있는 엔터티의 변경된 버전으로
간주해야 한다. Request-URI가 기존 자원을 지칭하지 않고 URI가 요구하는 사용자 에이전트가
새로운 자원으로 규정할 수 있다면 원서버는 해당 URI로 자원을 생성할 수 있다. 만약 새로
운 자원이 생성되었으면 원서버는 사용자 에이전트에게 201(Created) 응답을 알려야 한다. 기존
자원이 변경되었다면 200(OK)이나 204(No Content) 응답 코드를 발송하여 요구를 성공적으로
완료하였음을 표시하여야 한다. Request-URI로 자원을 생성하거나 변경할 수 없는 경우에는 문
제의 기본 성격을 반영하는 적절한 에러 응답을 발송해야 한다. 엔터티의 수신측은 이해 또는
구현할 수 없는 Content-* (예: Content-Range) 헤더를 반드시 무시해야 하고 이러한 경우
501(Not Implemented) 응답을 리턴해야 한다.

요구가 캐시를 통과할 경우 Request-URI는 하나 또는 그 이상의 현재 캐시 된 엔터티를 식별
한다. 이러한 엔터티는 낡은 것으로 취급해야 하며 이러한 method에 대한 응답은 캐시할 수
없다.

POST와 PUT 요구의 근본적인 차이점은 Request-URI의 다른 의미에 반영된다. POST의 URI
는 동봉된 엔터티를 처리할 자원을 식별한다. 그 자원은 데이터를 접수하는 프로세스, 다른 규
약으로의 게이트웨이 또는 주석을 접수하는 별도의 엔터티일 수 있다. 이에 비하여 PUT 요구
의 URI는 요구에 포함된 엔터티를 식별한다. - 사용자 에이전트는 어떤 URI를 의도하고 있으
며 서버는 요구를 다른 자원에 적용해서는 절대로 안 된다는 것을 알고 있다. 만약 서버가 해
당 요구를 다른 URI에 적용하고자 한다면 서버는 301(Moved Permanently) 응답을 반드시 발송
해야 한다. 그러면 사용자 에이전트는 해당 요구의 방향을 재설정 할 것인지에 관한 자신의
결정을 한다.

단일 자원이 복수의 상이한 URI에 의하여 식별될 수 있다. 예를 들어 기사(article)는 각각의
특별한 버전을 식별하는 URI와 구별되는 "현재 버전"을 확인하기 위한 URI를 가질 수 있다.
이 경우 일반 URI의 PUT 요구는 원서버에 의하여 규정되는 복수의 URI를 생성할 수도 있다.

HTTP/1.1은 PUT method가 어떻게 원서버의 상태에 영향을 미치는가에 대해서는 규정하지 않
는다.

PUT 요구는 8.2 절에 설정된 메시지 전송 필요 조건을 반드시 따라야 한다.

[Page 52]


9.7 DELETE

DELETE method는 Request-URI가 식별하는 자원을 삭제하도록 원서버에 요구한다. 이 method
는 원서버에서 사용자의 개입(또는 다른 방법)에 의하여 무시될 수 있다. 클라이언트는 비록
원서버에서 발송한 상태 코드가 해당 작업이 성공적으로 완수되었다는 표시를 하여도 실제로
작업이 완료되었다는 보장을 받을 수 없다. 그러나 서버는 요구를 접수한 시점에서 자원을 삭
제하거나 접근할 수 없는 위치로 이동할 의사가 없는 한 성공을 표시해서는 안 된다.

성공적인 응답은 응답이 상태를 설명하는 엔터티를 포함한다면 200 (OK), 처리가 시작되지 않
았으면 202 (Accepted), 응답은 OK이나 엔터티를 포함하지 않고 있으면 204 (No Content)이다.

요구가 캐시를 통과할 경우 Request-URI는 하나 또는 그 이상의 현재 캐시 된 엔터티를 식별
한다. 이러한 엔터티는 낡은 것으로 취급해야 하며 이러한 method에 대한 응답은 캐시할 수
없다.

9.8 TRACE

TRACE method는 요구 메시지의 원격지, 애플리케이션-계층 루프백(loop back)을 호출하는 데
사용한다. 응답의 최종 수신측은 클라이언트에게 되돌려 진 메시지를 200(OK) 응답의 Entity-
Body로 수신해야 한다. 마지막 수신측은 메시지의 Max-Forwards 제로 값(14.31 절)을 수신하는
원서버, 첫 프락시 또는 게이트웨이이다. TRACE 요구는 절대 엔터티를 포함해서는 안 된다.

TRACE는 클라이언트가 Request chain의 다른 끝 쪽에 무엇이 수신되는가를 알 수 있게 하며
그 데이터를 시험 또는 진단 정보로 사용한다. Via 헤더 필드(14.44 절)의 값은 Request chain의
추적 역할을 수행하기 때문에 특히 주목할 만하다. Max-Forwards 헤더 필드를 사용하면 클라이
언트가 Request chain의 길이를 제한할 수 있으며 이는 무한 루프에서 메시지를 전달하는 프락
시 고리를 테스트하는 데 유용하다.

성공적이면 응답은 "message/http" 의 Content-Type을 가진 Entity-Body의 전체 요구 메시지를
포함할 수 있어야 한다. 이러한 method에 대한 응답을 절대 캐시해서는 안 된다.

10 Status Code Definitions

각Status-Code 가 어떤 method를 따를 수 있는가에 대한 설명과 응답에서 필요로 하는 헤더 정보
를 포함하여 아래에 설명되어 있다.

[Page 53]


10.1 정보를 알려 주는 1xx

이 상태 코드 클래스는 잠적적인 응답을 표시하며 Status-Line과 선택적인 헤더로 구성되어 있
다. 이 클래스는 빈 라인으로 종료된다. HTTP/1.0은 어떠한 1xx 상태 코드로 정의하지 않기 때
문에 실험적인 상황 이외에 서버는 1xx 응답을 HTTP/1.0 클라이언트에 발송해서는 안 된다.

10.1.1 100 계속

클라이언트는 요구를 계속 진행할 수 있다. 이 잠정적인 응답은 클라이언트에게 응답의 시초
부분이 수신되었으며 서버가 아직 거부하지 않았음을 알리는 데 사용한다. 클라이언트는 요구
의 나머지 부분을 발송하여야 하며 요구가 완료 되었으면 이 응답을 무시해야 한다. 서버는
요구가 완료된 다음 마지막 응답을 발송한다.

10.1.2 101 규약 전환

서버가 이해하였으며 기꺼이 Upgrade 메시지 헤더 필드(14.41 절)를 통하여 접속에 사용되고
있는 애플리케이션 규약 변경에 관한 클라이언트의 요구에 따른다. 서버는 101 응답을 종료하
는 빈 라인 바로 다음 응답 메시지의 Upgrade 헤더 필드가 정의한 규약으로 전환할 것이다.

규약은 전환하는 것이 유리한 경우에만 전환된다. 예를 들어 새로운 버전의  HTTP로 전환하
는 것이 이전 버전을 사용하는 것보다 유리하며 해당 기능을 사용하는 자원을 배달할 때 실시
간, 동시 규약으로 전환하는 것이 유리하다.

10.2 성공을 알리는 2xx

이 상태 코드 클래스는 클라이언트의 요구가 성공적으로 수신, 해석 및 접수되었음을 표시한
다.

10.2.1 200 OK

요구를 성공적으로 전달하였다. 응답과 함께 리턴 되는 정보는 요구에 사용된 method에 달려
있다. 예를 들면:

   GET  요구한 자원에 상응하는 엔터티는 응답에 포함되어 발송된다.

   HEAD 요구한 자원에 상응하는 Entity-Header 필드는 Message-Body 없이 응답에 포함되어 발송
된다.

[Page 54]


   POST 처리 결과를 설명 또는 포함하는 엔터티.

   TRACE 수신 서버가 수신한 요구 메시지를 포함하고 있는 엔터티

10.2.2 201 Created (생성 되었음)

요구가 충족되었으며 새로운 자원이 생성되고 있다. 새로 생성된 자원은 응답  엔터티의 리턴
된 URI를 통하여 참조할 수 있으며 자원의 가장 상세한 URL은 Location 헤더 필드로 알 수
있다. 원서버는 201 상태 코드를 리턴하기 전에 반드시 자원을 생성해야 한다. 처리가 즉각적
으로 수행될 수 없을 때에 서버는 202(Accepted) 응답으로 대신 응해야 한다.

10.2.3 202 Accepted (접수 되었음)

처리를 위해 응답을 접수하였으나 처리는 완료되지 않았다. 요구는 엔터티의 처리 과정에서
허용되지 않을 수도 있기 때문에 궁극적으로 처리될 수도 있고 처리되지 않을 수도 있다. 이
와 같은 동시 작업에서 상태 코드를 재발송하는 설비는 없다.

202 응답은 의도적으로 작업을 수행하지 않는다. 이 응답의 목적은 서버가 사용자 에이전트가
프로세스가 완료될 때까지 서버에 지속적으로 연결되지 않고도 다른 프로세스에 대한 요구(하
루에 한 번만 실행되는 배치 지향적인 프로세스일 수도 있다.)를 접수할 수 있도록 하는 데
있다. 이 응답을 리턴하는 엔터티는 상태 점검자(monitor)에 대한 지시자 또는 사용자가 언제
요구가 완료될 수 있는지에 대한 예상 및 요구의 현재 상태에 대한 표시를 포함해야 한다.

10.2.4 203 Non-Authoritative Information(비 인증 정보)

Entity-Header의 리턴 된 메타 정보는 서버에서 사용할 수 있는 정의 세트가 아니고 지역 또는
제 3 자의 복사본에서 수집한 것이다. 제시된 세트는 원래 버전의 하부 세트 또는 상위 세트
일 수 있다. 예를 들어 자원에 대한 지역적 주해 정보를 포함하면 원서버가 알고 있는 메타
정보에 대한 상위 세트를 만들어 낼 수도 있다. 이 응답 코드를 사용하는 것은 의무사항이 아니
며 응답이203이 아니면 200 (OK)일 때만 적합하다.

10.2.5 204 No Content(내용이 없음)

서버가 요구를 완전히 처리 했으나 반송할 새로운 정보가 없다. 클라이언트가 사용자 에이전
트이면 요구를 발송하도록 한 문서 내용을 변경해서는 안 된다.

[Page 55]


이 응답은 주로 사용자 에이전트의 문서 내용에 대한 변화를 초래하지 않고 처리를 위한 입력
을 실행하도록 하기 위해 사용한다. 응답은 Entity-Header 형태의 새로운 메타 정보를 포함한다.
이 정보는 사용자 에이전트의 현재 문서에 적용해야 한다.

204 응답은 Message-Body를 포함해서는 안되며 항상 헤더 필드 다음의 첫 빈 라인으로 종료
된다.

10.2.6 205 Reset Content(내용을 지움).

서버가 요구를 완전히 처리하였으며 사용자 에이전트는 요구를 발송하도록 한 문서의 내용을
지워야 한다. 이 응답은 주로 사용자 입력을 통하여 처리를 위한 입력이 발생하도록 하기 위
해 사용한다. 이 응답 뒤에 입력을 수행한 폼을 지워 사용자가 다른 입력 요구를 쉽게 시작할
수 있게 한다. 이 응답은 엔터티를 포함해서는 안 된다.

10.2.7 206 Partial Content(부분적 내용).

서버가 자원에 대한 부분적 GET 요구를 완료하였다. 이 요구는 반드시 원하는 영역을 표시하
는 Range 헤더 필드(14.36 절)를 포함해야 한다. 응답은 이 응답에 포함된 영역을 표시하는
Content-Range 헤더 필드(14.17 절)나 각 파트의 Content-Range 필드를 포함하는
multipart/byteranges Content-Type을 포함해야 한다. multipart/byteranges를 사용하지 않았으면 응
답의Content-Length 헤더 필드는 Message-Body로 전송된 OCTET의 실제 숫자와 정확하게 일
치해야 한다.

Range 및 Content-Range 헤더를 지원하지 않는 캐시는 206(Partial Content) 응답을 캐시해서는
안 된다.

10.3  (방향을 재설정하는 3xx)

이 상태 코드 클래스는 사용자 에이전트가 요구를 완전히 처리하기 위해서는 추가적인 처리가
필요하다는 것을 표시한다. 요구되는 처리는 두 번째 요구에 사용된 method가 GET 또는
HEAD일 경우에만 사용자와의 상호작용 없이도 수행될 수 있다. 사용자 에이전트는 이러한
방향 재설정이 무한 루프를 표시하는 것이기 때문에 다섯 번 이상 자동적으로 요구 방향 재설
정을 해서는 안 된다.

[Page 56]


10.3.1 300 Multiple Choices (복수 선택)

요구된 자원이 각자 자신 특유의 위치를 가지고 있는 표현 세트 중의 하나와 대응되며 사용자
(또는 사용자 에이전트)가 선호하는 표현 방식을 선택하고 요구를 해당 위치로 재설정할 수
있도록 에이전트가 주도하는(agent-driven) 협상 정보가 제공된다.

HEAD 요구가 아닌 이상 응답은 사용자 또는 사용자 에이전트가 가장 적합한 것을 선택할 수
있는 자원 특징 및 위의 목록을 포함한 엔터티를 포함한다. 엔터티 포맷은 Content-Type 헤더
필드가 설정한 media type에 의해 명시된다. 사용자 에이전트의 포맷 및 성능에 따라 가장 적
합한 선택을 결정하는 것은 자동으로 수행될 수 있다. 그러나 이 규격은 이러한 자동 선택의
표준에 대하여 아무런 규정도 하지 않는다.

서버가 선호하는 표시 방법을 가지고 있으면 Location 필드에 해당 표시 방법에 대한 상세한
URL을 포함해야 한다. 사용자 에이전트는 Location 필드 값을 이용하여 자동으로 방향을 재
설정할 수 있다. 이 응답은 별도의 표시가 없는 한 캐시할 수 있다.

10.3.2 301 301 Moved Permanently (영구 이동)

요구된 자원에 새로운 영구 URI가 할당되었으며 향후 이 자원에 대한 참조는 리턴 된 URI
중 하나를 이용하여 이루어질 수 있다. 링크를 편집할 수 있는 능력이 있는 클라이언트는 가
능하다면 Request-URI 에 대한 참조를 서버가 리턴한 하나 또는 그 이상의 새로운 참고처로
자동적으로 재링크시켜야 한다. 다르게 표시되어 있지 않으면 이 응답은 캐시할 수 있다.

새로운 URI가 위치이면 해당 URL은 응답의Location 필드가 부여해야 한다. 요구 method가
HEAD가 아니면 응답의 엔터티는 새로운 URI로의 하이퍼링크가 표시된 짧은 하이퍼텍스트
주석을 포함하고 있어야 한다.

GET 또는 HEAD 이외의 요구에 대한 응답에 301 상태 코드가 접수되면 사용자 에이전트는
사용자가 확인하지 않는 한 요구를 발행한 조건을 변경할 수도 있기 때문에 자동적으로 요구
의 방향을 재설정해서는 안 된다.

주의 : 301 상태 코드를 수신한 후 자동적으로 POST 요구의 방향을 재설정할 때 기존의 몇
몇 HTTP/1.0 사용자 에이전트는 실수로 POST 요구를 GET 요구로 변경한다.

[Page 57]


10.3.3 302 Moved Temporarily(임시 이동)

요구된 자원이 별도의 URI에 임시로 보관되어 있다. 방향 재설정은 종종 변경될 수 있기 때문
에 클라이언트는 향후 요구를 위해서 계속해서 Request-URI를 사용해야 한다. 이 응답은 Cache-
Control 또는 Expires 헤더 필드가 표시할 경우에만 캐시할 수 있다.

새로운 URI가 위치이면 해당 URL은 응답의Location 필드가 부여해야 한다. 요구 method가
HEAD가 아니면 응답의 엔터티는 새로운 URI로의 하이퍼링크가 표시된 짧은 하이퍼텍스트
주석을 포함하고 있어야 한다.

GET 또는 HEAD 이외의 요구에 대한 응답에 301 상태 코드가 접수되면 사용자 에이전트는
사용자가 확인하지 않는 한 요구를 발행한 조건을 변경할 수도 있기 때문에 자동적으로 요구
의 방향을 재설정해서는 안 된다.

주의 : 301 상태 코드를 수신한 후 자동적으로 POST 요구의 방향을 재설정할 때 기존의 몇
몇 HTTP/1.0 사용자 에이전트는 실수로 POST 요구를 GET 요구로 변경한다.

10.3.4 303 See Other(다른 것을 참조)

요구된 자원이 별도의 URI에 임시로 보관되어 있으며 해당 자원에서 GET method를 사용하여
조회해야 한다. 이 method는 주로 POST가 활성화한 스크립트의 산출물을 사용자 에이전트가
선택된 자원으로 방향을 재설정할 수 있도록 하기 위해 사용된다. 새로운 URI는 처음 요구된
자원에 대한 대체 참고처가 아니다. 303 응답은 캐시할 수 없으나 두 번째(재설정된) 요구에
대한 응답은 캐시할 수 있다.

GET 또는 HEAD 이외의 요구에 대한 응답에 301 상태 코드가 접수되면 사용자 에이전트는
사용자가 확인하지 않는 한 요구를 발행한 조건을 변경할 수도 있기 때문에 자동적으로 요구
의 방향을 재설정해서는 안 된다.

10.3.5 304 Not Modified(변경되지 않았음)

클라이언트가 조건적 GET 요구를 실행했고 접근할 수 있으나 문서가 변경되지 않았으면 서버
는 이 상태 코드로 응답해야 한다. 이 응답은 Message-Body를 포함해서는 안 된다.

[Page 58]


응답은 다음의 헤더 필드를 포함하고 있어야 한다.

? 날짜
 
? ETag 및/또는 Content-Location, 동일한 요구에 대한 200 응답 속에 헤더가 발송되었을 경

 
? Expires, Cache-Control, 및/또는 Vary, 동일한 변이에 대한 이전 응답 속에 발송된 field-
value가 상이할 경우

조건적 GET이 강한 캐시 검증자(13.3.3 절 참조)를 사용했다면 응답은 다른 Entity-Header를
포함해서는 안 된다. 그렇지 않으면(조건적 GET이 약한 캐시 검증자를 사용할 때) 응답은
Entity-Header을 포함해서는 안 된다. 이렇게 하여 캐시 된 Entity-Body과 갱신된 헤더 사이의
불일치를 방지할 수 있다.

304 응답이 현재 캐시 되지 않은 엔터티를 표시할 때 캐시는 이 응답을 무시하고 조건 없이
요구를 반복해야 한다.

캐시가 수신한 304 응답을 캐시 엔트리의 갱신에 사용한다면 캐시는 응답이 가지고 있는 새로
운 필드 값을 반영하기 위해 엔트리를 반드시 갱신해야 한다.

304 응답은 Message-Body를 포함해서는 안되므로 항상 헤더 필드 다음의 첫 공백 라인으로
종료되어야 한다.

10.3.6 305 Use Proxy(프락시를 사용할 것)

요구된 자원을 Location 필드에 명시된 프락시를 통하여 접근해야만 한다. Location 필드가 프
락시의 URL을 제공한다. 수신측은 프락시를 통한 요구를 반복할 것으로 기대된다.

10.4 Client Error 4xx (클라이언트 에러 4xx)

상태 코드의 4xx 클래스는 클라이언트가 에러를 발생한 것처럼 보일 경우에 사용된다. HEAD
요구에 응답하는 경우를 제외하고는 서버는 임시적이건 영구적이건 에러 상황에 대한 설명을
포함한 엔터티를 포함해야 한다. 이러한 상태 코드는 모든 요구 method에 적용할 수 있다. 사
용자 에이전트는 사용자에게 포함된 엔터티를 표시해야 한다.

주의 : 클라이언트가 데이터를 발송한다면 TCP를 사용하는 서버 구현 방식은 서버가 입력
접속을 종료하기 전에 응답을 포함하고 있는 패킷 접수를 확인할 수 있도록 주의해야 한다.
클라이언트가 접속이 종료된 후에도 계속해서 데이터를 전송한다면 서버의 TCP 스택은 리
셋 패킷을 클라이언트에게 발송할 것이다.
 [Page 59]


이 리셋 패킷은 HTTP 애플리케이션이 읽거나 해석하기 전에 클라이언트가 확인한 입력 버
퍼를 지운다.

10.4.1 400 Bad Request(잘못된 요구)

잘못된 형식 때문에 서버가 요구를 이해할 수 없다. 클라이언트는 변경 없이 요구를 반복해서
는 안 된다.

10.4.2 401 Unauthorized (인증되지 않았음)

응답이 사용자 인증을 요구한다. 이 응답은 요구된 자원에 적용할 수 있는 설명 요구
(challenge)를 포함하고 있는 WWW-Authenticate 헤더 필드(14.46 절)를 포함하고 있어야 한다.
클라이언트는 적절한 Authorization 헤더 필드(14.8 절)를 가지고 요구를 반복할 수 있다. 요구
가 벌써 Authorization 증명서를 포함하고 있다면 401 응답은 해당 증명서에 대한 인증이 거절
되었음을 표시한다. 401 응답이 이전 응답과 동일한 설명 요구를 포함하고 있고 사용자 에이전
트가 한 번 이상 인증 획득을 시도했다면 해당 엔터티가 관련된 진단 정보를 포함하고 있기
때문에 사용자에게 응답에 표시된 엔터티를 표시해주야 한다. HTTP 접속 인증은 11 장에 설명
되어 있다.

이 코드는 향후 사용을 위해 예약되었다.

10.4.4 403 Forbidden(금지되었음)

서버가 요구를 이해했으나 완료하는 것을 거절하고 있다. 인증은 적용되지 않으며 요구를 반
복될 수 없다. 요구 method가 HEAD가 아니고 서버가 왜 요구가 완료되었는지 알리고 싶다면
엔터티 안에 거절한 이유를 기록해야 한다. 이 상태 코드는 서버가 요구가 거부 사유를 밝히
기 원하지 않을 때나 다른 응답을 적용할 수 없을 때 일반적으로 사용된다.

10.4.5 404 Not Found(찾을 수 없음)

서버가 Request-URI와 일치하는 것을 아무것도 발견하지 못했다. 이러한 상태가 잠정적인지
영구적인지 관한 아무런 표시도 주어지지 안는다.

[Page 60]


서버가 이 정보를 클라이언트에게 알리고 싶지 않을 경우 상태 코드 403(Forbidden)을 대신 사
용할 수 있다. 내부적으로 환경을 설정할 수 있는 메커니즘을 통하여 이전의 자원을 영구적으
로 사용할 수 없으며 전송 주소가 없다는 것을 알 수 있으면 410(Gone) 상태 코드를 사용한다.

10.4.6 405 Method Not Allowed(Method를 사용할 수 없음)

Request-Line에 명시된 method를 Request-URI로 확인할 수 있는 자원에서 사용할 수 없다. 응
답은 요구된 자원에 사용할 수 있는 method의 목록을 포함한 Allow 헤더를 포함해야 한다.

10.4.7 406 Not Acceptable(접수할 수 없음)

요구가 확인한 자원이 요구 메시지와 함께 발송된 Accept 헤더에 의해서 접수할 수 없는 내용
특징을 가지고 있는 응답 엔터티만을 생성할 수 있다.

HEAD 요구가 아닌 이상 응답은 사용자 또는 사용자 에이전트가 가장 적합한 것을 선택할 수
있는 자원 특징 및 위의 목록을 포함한 엔터티를 포함한다. 엔터티 포맷은 Content-Type 헤더
필드가 설정한 media type에 의해 명시된다. 사용자 에이전트의 포맷 및 성능에 따라 가장 적
합한 선택을 결정하는 것은 자동으로 수행될 수 있다. 그러나 이 규격은 그러한 자동 선택의
표준에 대하여 아무런 규정도 하지 않는다.

주의 : HTTP/1.1 서버는 요구 메시지와 함께 발송된 Accept 헤더에 의해서 접수할 수 없는
응답을 리턴할 수 있게 한다. 어떤 경우엔 이것이 406 응답을 발송하는 것보다 좋을 수도
있다. 사용자 에이전트는 도착하는 응답의 헤더를 검사하여 그것의 접수 여부를 결정하도록
추천한다. 응답을 접수할 수 없을 때 사용자 에이전트는 잠정적으로 더 이상의 데이터를 수
신하지 말아야 하며 추가 행동을 취할 것인지 사용자에게 질의한다.
    
10.4.8 407 Proxy Authentication Required(프락시 인증 필요)

이 코드는 401(Unauthorized)과 유사하지만 클라이언트는 먼저 프락시에서 자기 자신을 인증해
야 한다는 것을 표시한다. 프락시는 요구된 자원의 프락시에 적용할 수 있는 설명 요구를 포
함하는 Proxy-Authenticate 헤더 필드(14.33 절)를 리턴해야 한다. 클라이언트는 적절한 Proxy-
Authorization 헤더 필드(14.34 절)와 함께 요구를 반복해야 한다. HTTP 접속 인증 획득에 대해
서는 11 장에 설명되어 있다.
  
[Page 61]


10.4.9 408 Request Timeout(요구 시간 초과)

클라이언트가 서버가 기다리도록 준비한 시간 내에 요구를 만들어 낼 수 없다. 클라이언트는
나중에 변경 없이 요구를 반복할 수 있다.

10.4.10 409 Conflict(충돌)

자원의 현재 상태와의 충돌 때문에 요구를 완료할 수 없다. 이 코드는 사용자가 충돌을 해결
하고 요구를 재전송할 수 있을 것으로 기대할 수 있는 상황에서만 사용할 수 있다. 응답 본문
은 사용자가 충돌의 원인을 인지할 수 있도록 충분한 정보를 포함해야 한다. 이상적으로는 응
답 엔터티가 사용자 또는 사용자 에이전트가 문제를 해결할 수 있을 정도의 충분한 정보를 포
함할 수 있을 것이다. 그러나 가능하지 않을 수도 있으며 필수 사항은 아니다.

충동은 PUT 요구에 대한 응답으로 발생할 가능성이 높다. 버전 관리를 사용하고 있고 PUT 요
구를 하는 엔터티가 이전 요구(제 3 자)가 작성한 요구와 충돌되는 자원에 대한 변경 사항을
포함하고 있다면 서버는 409 응답을 사용하여 요구를 완료할 수 없음을 표시해야 한다. 이 경
우 응답 엔터티는 응답 Content-Type이 규정한 형식으로 두 버전 사이의 차이점 목록을 포함
해야 한다.

10.4.11 410 Gone (내용물이 사라졌음)

요구된 자원이 서버에 더 이상 존재하지 않으며 전송 주소를 알 수 없다. 이 조건은 영구적인
것으로 간주해야 한다. 링크를 편집할 기능이 있는 클라이언트는 사용자 인증 후의 Request-
URI에 대한 참고는 삭제해야 한다. 서버가 그 조건이 영구적인지 여부를 알 수 없거나 결정
할 시설이 없으면 상태 코드 401(Unauthorized)을 대신 사용해야 한다. 다르게 표시되지 않는
한 이 응답은 캐시할 수 있다.

410 응답은 주로 수신측에게 자원을 의도적으로 사용할 수 없게 하였고 서버의 소유주가 해당
자원에 대한 원격 링크를 제거하고자 한다는 것을 알림으로써 웹 유지 작업을 지원하기 위해
사용된다. 이러한 일은 제한된 시간, 선전용 서비스 및 서버의 사이트에서 더 이상 일하지 않
는 개인에게 소속된 자원에서 공통적으로 발생할 수 있다. 영구적으로 사용할 수 없는 모든
자원을 "사라진" 것으로 표시하거나 특정 시간 동안 표시를 유지할 필요는 없다. - 이것은 서
버 소유자의 판단에 달려 있다.

[Page 62]


10.4.12 411 Length Required(길이가 필요함)

서버가 규정된 Content-Length 없는 요구 접수를 거부하였다. 요구 메시지 내의 Message-Body
의 길이를 포함하는 유효한 Content-Length 헤더 필드를 추가한다면 클라이언트는 요구를 반복
할 수 있다.

10.4.13 412 Precondition Failed(사전 조건 충족 실패)

하나 또는 그 이상의 Request-Header 필드에 기입된 사전 조건이 서버에서 테스트 했을 때 거
짓으로 평가되었다. 이 응답 코드는 클라이언트가 현재 자원의 메타 정보에 사전 조건을 부여
할 수 있게 하여 의도하지 않는 자원에 요구 method를 적용하는 것을 방지한다.

10.4.14 413 Request Entity Too Large(요구 엔터티가 너무 큼)

요구 엔터티가 서버가 처리할 수 있거나 처리하려는 것보다 크기 때문에 서버가 요구 처리를
거부하였다. 서버는 클라이언트가 계속적으로 요구하는 것을 방지하기 위하여 연결을 종료한
다.

조건이 잠정적이면 서버는 Retry-After 헤더 필드를 포함하여 조건이 잠정적이며 얼마 후에 클
라이언트가 재시도할 것인지를 표시한다.

10.4.15 414 Request-URI Too Long(Request -URI가 너무 김)

Request-URI가 서버가 해석할 수 있는 것보다 크기 때문에 서버가 요구 처리를 거부하였다.
이처럼 드문 조건은 클라이언트가 부적절하게 질의 정보가 긴 POST 요구를 GET 요구로 변환
했을 때, 클라이언트가 방향 재설정의 URL "블랙 홀"로 빠졌을 때(방향이 재설정된 URL 접두
사가 자신의 접미사를 지칭할 때), Request-URI를 읽거나 조작하는 고정-길이 버퍼를 사용하는
몇몇 서버에 존재하는 보안의 허점을 이용하려는 클라이언트로부터 서버가 공격을 받을 때만
발생하는 것 같다.

10.4.16 415 Unsupported Media Type(지원되지 않는 media type)

요구의 엔터티가 요구 받은 method의 자원이 지원하지 않는 포맷으로 구성되어 있기 때문에
요구 처리를 거부하였다.

[Page 63]


10.5 Server Error 5xx(서버 에러 5xx)

숫자 "5"로 시작하는 응답 상태 코드는 서버가 에러를 발생시켰으며 요구를 처리할 능력이 없
음을 인지한 경우를 표시한다. HEAD 요구에 응답하는 때를 제외하고는 서버는 에러 상황에
대한 설명 및 에러가 잠정적인지 영구적인지에 관한 상황 설명을 포함하는 엔터티를 포함해야
한다. 사용자 에이전트는 포함된 모든 엔터티를 사용자에게 표시하여야 한다. 이러한 응답 코
드는 모든 요구 method에 적용할 수 있다.

10.5.1 500 Internal Server Error(서버 내부 에러)

서버가 요구를 처리하지 못하도록 하는 예상치 못한 상황에 접했다.

10.5.2 501 Not Implemented(구현되지 않았음)

서버가 요구를 완료하는 데 필요한 기능을 지원하지 않는다. 이것은 서버가 요구 method를 인
지할 수 없고 어떠한 자원을 사용해도 지원할 수 없을 때 적절한 응답이다.

10.5.3 502 Bad Gateway(불량 게이트웨이)

게이트웨이나 프락시 역할을 수행하는 서버가 요구를 완료하려는 시도에서 접근한 업스트림
(upstream) 서버로부터 유효하지 않은 응답을 수신했을 경우이다.

10.5.4 503 Service Unavailable(서비스를 사용할 수 없음)

서버가 현재 잠정적인 오버로딩(overloading)이나 서버의 유지 작업 때문에 요구를 처리할 수
없다. 이것의 의미는 이것이 잠정적인 상황이며 얼마 후에는 완화될 수 있다는 것이다. 알 수
있다면 지연 시간 길이를 Retry-After 헤더에 표시할 수 있다. 아무런 Retry-After 정보가 없으
면 클라이언트는 500 응답을 처리하는 것처럼 응답을 처리해야 한다.

주의 : 503 상태 코드가 있다는 것이 서버가 오버로드 되었을 때 이것을 반드시 사용해야 된
다는 것을 의미하지 않는다. 어떤 서버는 단순히 접속을 거부하고자 한다.

10.5.5 504 Gateway Timeout(게이트웨이 시간 초과)

게이트웨이나 프락시 역할을 수행하는 서버가 시간 내에 요구를 완료하려는 시도에서 접근한
업스트림(upstream) 서버로부터 응답을 수신하지 못했을 경우이다.

[Page 64]


10.5.6 505 HTTP Version Not Supported(지원되지 않는 HTTP 버전)

서버가 요구 메시지에서 사용된 HTTP 규약 버전을 지원하지 않거나 지원하기를 거부했다. 서
버는 이 에러 메시지 이외에는 3.1 절에서 설명한 대로 클라이언트가 사용하는 동일한 주요
버전을 사용하여 요구를 완료할 의사나 능력이 없음을 표시한다. 응답은 왜 해당 버전이 지원
되지 않으며 서버가 어떤 규약을 지원하는가를 설명하는 엔터티를 포함해야 한다.

11 접속 인증

HTTP는 서버는 클라이언트의 요구를 시도하고 클라이언트는 인증 정보를 제공하는 단순한
Try-Response 인증 획득 메커니즘을 제공한다. 이것은 확장 가능하고 대소문자를 구별하지 않
는 토큰을 사용하여 인증 scheme을 확인한다. 이 scheme 뒤에는 이 scheme을 통하여 인증을
획득하는 데 필요한 파라미터를 가지고 있는 콤마로 구분된 attribute-value 쌍의 목록이 뒤따른
다.

          auth-scheme     = token

          auth-param      = token "=" quoted-string

원서버는 401(Unauthorized) 응답 메시지를 사용하여 사용자 에이전트의 인증을 시도한다. 이
응답은 요구된 자원에 적용할 수 있는 최소한 하나의 시도를 포함한 WWW-Authenticate 헤더
필드를 포함해야 한다.

          challenge       = auth-scheme 1*SP realm *( "," auth-param )

          realm           = "realm" "=" realm-value
          realm-value     = quoted-string

인증을 시도하는 모든 인증 scheme은 영역 속성(대소문자를 구별하지 않음)을 가지고 있어야
한다. 영역 속성(대소문자를 구별함)은 접속하려는 서버의 정형적 루트 URL (5.1.2 절 참조)과
결합하여 보호 구역(protection space)을 정의한다. 이 영역은 서버의 보호된 자원이 각각 자신의
인증 획득 scheme 및/또는 인증 데이터 베이스를 가지고 보호 구역 세트로 분할될 수 있도록
한다. 영역 값은 문자열이며 보통 원서버가 지정한다. 원서버는 인증 획득 scheme에 한정된
추가적인 의미를 가질 수 있다.

서버에 자신의 인증을 얻고자 하는 사용자 에이전트는 - 대개의 경우 필수적인 사항은 아니지
만 401 또는 411 응답을 수신한 후 -요구에 Authorization 헤더 필드를 포함하여 인증을 얻을
수 있다. Authorization 필드 값은 요구하고 있는 자원의 영역에 대한 사용자 에이전트의 인증
획득 정보를 포함하고 있는 인증 증명서로 구성되어 있다.

 [Page 65]


          credentials    = basic-credentials
                         | auth-scheme #auth-param

사용자 에이전트에 의해 증명서가 자동적으로 적용될 수 있는 도메인(domain)은 보호 구역에
의하여 결정된다. 이전의 요구가 인가되었으면 인증 획득 scheme, 파라미터 및/또는 사용자의
선호에 따라 결정되는 기간 동안 해당 보호 구역 내에서는 동일한 증명서를 재사용할 수 있다.
인증 획득 scheme에 의해 다르게 규정되지 않는 한 단일 보호 구역은 서버의 범위를 넘어서
확장될 수 없다.

요구

서버가 요구와 함께 수신한 증명서를 접수하고 싶지 않으면 서버는 401(Unauthorized) 응답을
리턴해야 한다. 응답은 요구된 자원 및 거절 이유를 설명하는 엔터티에 적용할 수 있는 시도
(재시도일 수도 있다)를 포함한 WWW-Authenticate 헤더 필드를 반드시 포함해야 한다.

HTTP 규약은 접속 인증 획득을 위해 이 단순한 Try-Response 메커니즘만을 애플리케이션이
사용하도록 제한하지는 않는다. 전송 수준 또는 메시지 내포화(encapsulation)를 통한 암호화 등
과 같은 추가적인 메커니즘을 인증 획득 정보를 명시하는 추가적인 헤더 필드와 더불어 사용
할 수 있다.

프락시는 반드시 사용자 에이전트 인증 획득에 관하여 완전히 투명해야 한다. 말하자면 프락
시는 반드시 WWW-Authenticate 및 Authorization 헤더를 변경하지 않고 전송해야 하며 14.8 절
에 있는 규칙에 따라야 한다.

HTTP/1.1은 클라이언트가 인증 획득 정보를 Proxy-Authenticate 및 Proxy-Authorization 헤더를
통하여 프락시와 주고 받을 수 있도록 허용해야 한다.

11.1 기본 인증 scheme

"기본적(basic)" 인증 scheme은 사용자 에이전트가 각 영역에서 사용자 ID 및 암호로서 자신의
인증을 획득해야 한다는 모델에 기초하고 있다. 영역 값은 동일 서버의 다른 영역과의 동일성
이 비교될 수 있는 불투명한 문자열로 간주해야 한다. 서버는 Request-URI의 보호 구역에서
사용자 ID와 암호를 검증할 수 있을 때만 요구를 청할 것이다. 선택적인 인증 획득 파라미터
는 없다.

[Page 66]


보호 구역 내의 URI에 대한 허가되지 않는 요구를 수신하면 서버는 다음과 같은 시도로 응답
할 수 있다.

          WWW-Authenticate: Basic realm="WallyWorld"

여기서 "WallyWorld"는 서버가 지정한 문자열로 Request-URI의 보호 구역을 확인해 준다.

인증 획득을 수신하기 위해서 클라이언트는 증명서 내의 base64로 인코딩된 문자열 내에서 단
일 콜론(":") 문자로 구분된 사용자 ID 와 암호를 발송한다.

          basic-credentials = "Basic" SP basic-cookie

          basic-cookie    =                            라인 당 76 문자에 제한을 받지 않을 경우>

          user-pass      = userid ":" password

          userid        = *

          password      = *TEXT

Userids 는 대소문자를 구별할 수도 있다.

사용자 에이전트가 userid "Aladdin" 과 암호 "open sesame"를 송신하고 싶다면 다음의 헤더 필
드를 사용해야 할 것이다:

          Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

기본 인증 획득과 관련된 보안에 대한 고려 사항은 15 장을 참고한다.

11.2 요약 인증 scheme

HTTP의 요약 인증 scheme은 RFC 2069 [32]에 명시되어 있다.

12 내용 협상(Content Negotiation)

대부분의 응답은 인간 사용자가 해석하는 정보를 포함한 엔터티를 포함하고 있다. 당연히 사
용자에게 요구에 상응하는 "최상의 사용 가능" 엔터티를 제공하는 것이 바람직하다. 서버와
캐시에게는 불행하게도 모든 사용자가 무엇이 최상인가에 대한 동일한 선호 사항을 가지고 있
는 것이 아니며 모든 사용자 에이전트가 평등하게 모든 엔터티 유형을 표시할 능력이 있는 것
이 아니다. 이러한 이유로 HTTP는 "내용 협상"을 위한 몇몇 메커니즘을 제공하고 있다.
[Page 67]


내용 협상이란 복수의 표현 방법을 사용할 수 있을 때 특정 응답에 대한 최상의 표현 방법을
선택하는 과정이다.

주의 : 대체하는 표시 방법이 동일한 media type이고 동일 유형의 다른 능력을 사용하거나
다른 언어로 되어 있을 수 있기 때문에 "포맷 협상" 이라고 부르지 않는다.

에러 응답을 포함하여 Entity-Body를 가지고 있는 모든 응답은 협상의 대상이 될 수 있다.

HTTP에서 사용할 수 있는 두 가지 종류의 내용 협상이 있다 - 서버가 주도하는 협상과 에이
전트가 주도하는 협상. 이 두 종류의 협상은 직교하기 때문에 분리하여 사용할 수도 있고 결
합하여 사용할 수도 있다. 투명한 협상으로 지칭되는 결합의 한 방법은 직후의 요구에 대하여
서버가 주도하는 협상을 제공하기 위해서 캐시가 원서버가 제공하는 에이전트 주도의 협상 정
보를 사용할 때 발생한다.

12.1 서버가 주도하는 협상

응답에 대한 최상의 표현 방식 선택이 서버에 위치한 알고리즘에 의하여 이루어 질 때 이를
서버가 주도하는 협상이라 부른다. 선택은 사용 가능한 응답 표시 방법(변형할 수 있는 차원.
예를 들어 언어 Content-Codings 등), 요구 메시지의 특정 헤더 필드의 내용 또는 요구와 관련
된 기타 정보(클라이언트의 네트워크 주소 같은 것)에 기초한다.

서버가 주도하는 협상은 사용 가능한 표현 방법 중에서 선택하는 알고리즘이 사용자 에이전트
에게 설명하기가 어려울 때 또는 서버가 자신의 "최상의 예측"을 첫 응답에 뒤 따라서("최상
의 예측"이 사용자에게 충분할 정도로 좋다면 계속되는 요구의 왕복 여행으로 인한 지연을 피
하려는 희망에서) 클라이언트에게 발송할 때 유리하다. 서버의 예측을 향상시키기 위해 사용
자 에이전트는 그러한 응답에 대한 자신의 선호를 표시하는 요구 헤더 필드(Accept, Accept-
Language, Accept-Encoding 등)를 포함할 수도 있다.

서버가 주도하는 협상은 다음의 단점이 있다.

1.  서버가 정확하게 특정 사용자에게 "최상"이 무엇인지 결정한다는 것은 사용자 에이전트의
능력 및 응답의 의도된 사용 용도에 대한 완벽한 이해를 필요로 하기 때문에 불가능하다.
(예를 들면 사용자가 그것을 화면에서 보기를 원하는가 아니면 종이에 인쇄하기를 원하는
가?)
 
2.  사용자 에이전트에게 요청할 때마다 자신의 능력을 설명하도록 하는 것은 매우 비효율적
(적의 퍼센트의 응답만이 복수의 표현 방법을 가지고 있다고 가정하면)이면서도 사용자의
프라이버시를 침해할 가능성이 있다.
[Page 68]


 
3.  원서버의 구현 방법 및 요구에 대한 응답을 생성하는 알고리즘을 복잡하게 만든다.
 
4.  복수의 사용자 요구에 대해 동일한 응답을 사용할 수 있는 보편적인 캐시의 능력을 제한
할 수 있다.

HTTP/1.1은 사용자 에이전트의 능력 및 사용자의 선호를 기술하여 서버가 주도하는 협상을
가능하게 하는 다음의 Request-Header 필드를 포함하고 있다. -  Accept (14.1 절), Accept-Charset
(14.2 절), Accept-Encoding (14.3 절), Accept-Language (14.4 절) 및User-Agent (14.42 절). 그러나
원서버는 이러한 차원에 제한 받지 않고 Request-Header 필드 이외의 정보 또는 이 규격이 규
정하지 않은 확장 헤더 필드를 포함하는 요구의 어떠한 측면에 따라 변형될 수 있다.

HTTP/1.1 원서버는 서버가 주도하는 협상에 기초한 캐시할 수 있는 모든 응답에서 반드시 적
절한 Vary 헤더 필드(14.43 절)를 포함해야 한다. Vary 헤더 필드는 응답이 변형될 수 있는 차
원을 설명한다. (예를 들어 원서버가 복수의 표현 방식으로부터 "최상의 예측"을 끄집어 낼 수
있는 차원)

HTTP/1.1 공공 캐시는 응답에 포함되어 있는 Vary 헤더 필드를 인지해야 하고 캐시와 내용 협
상의 상호 작용을 기술하고 있는 13.6 절에 설명된 필요 조건을 충족해야 한다.

12.2 에이전트가 주도하는 협상

에이전트가 주도하는 협상에서 응답에 대한 최상의 표현 방식의 선택은 원서버로부터 첫 응답
을 수신한 다음 사용자 에이전트가 수행한다. 선택은 각각의 표현 방식은 자신의 URI에 의하
여 식별하면서 헤더 필드(이 규격은 부록 19.6.2.1에 기술한 대로 필드 이름 Alternates를 예약
했다.) 내에 포함되어 있는 사용 가능한 표현 방식의 목록이나 첫 응답의 Entity-Body에 기초
한다. 표현 방식 선택은 자동적으로 수행(사용자 에이전트가 그렇게 할 능력이 있다면)될 수도
있고 사용자가 생성된(하이퍼텍스트일 수 있다) 메뉴에서 선택할 수도 있다.

에이전트가 주도하는 협상은 응답이 일반적으로 사용하는 차원(유형, 언어 또는 인코딩)에 따
라 변할 때, 원서버가 응답을 관찰하여 사용자 에이전트의 능력을 결정할 수 없을 때 또는 서
버의 부하를 분산하고 네트워크 사용을 감소시키기 위해 공공 캐시가 사용되었을 때 유리하다.

[Page 69]


에이전트가 주도하는 협상은 최적의 대체 표시 방법을 얻기 위해서 두 번째 요구가 필요하다
는 단점이 있다. 이 두 번째 요구는 캐시가 사용될 때만 효과적이다. 또한 이 규격은 자동적
선택을 지원하는 어떠한 메커니즘도 규정하지 않는다. 그러나 이 규격은 또한 이러한 메커니
즘이 확장으로서 개발되고 HTTP/1.1 내에서 사용되는 것을 금지하지는 않는다.

HTTP/1.1은 서버가 주도하는 협상을 이용하는 변화된 응답을 제공할 수 없거나 제공하려 하
지 않을 때 에이전트가 주도하는 협상이 가능하도록 300 (Multiple Choices) 및 406 (Not
Acceptable) 상태 코드를 규정한다.

12.3 투명한 협상(Transparent Negotiation)

투명한 협상은 서버가 주도하는 협상과 에이전트가 주도하는 협상의 복합체이다. 캐시가 응답
의 사용 가능한 표현 방식 목록 형태로 제공되고(에이전트가 주도하는 협상처럼) 캐시가 변이
의 차원을 완전히 이해했으면 해당 자원에 대한 계속적인 요구에 대하여 원서버를 대신하여
캐시는 서버가 주도하는 협상을 수행할 수 있게 된다.

투명한 협상은 그렇지 않다면 원서버가 수행해야 하는 협상 작업을 분산할 수 있고 캐시가 정
확하게 올바른 응답을 예측할 수 있을 때 에이전트가 주도하는 협상의 두 번째 요구 지연을
제거할 수 있다는 장점을 가지고 있다.

이 규격은 투명한 협상에 대한 어떠한 메커니즘도 규정하지 않는다. 그러나 이 규격은 또한
이러한 메커니즘이 확장으로서 개발되고 HTTP/1.1 내에서 사용되는 것을 금지하지는 않는다.
투명한 협상을 수행하는 HTTP/1.1 캐시는 HTTP/1.1과의 올바른 상호 작용을 확보하기 위하여
캐시할 수 있다면 반드시 응답(변이의 차원을 정의)에 Vary 헤더 필드를 포함해야 한다. 원서
버가 제공하는 에이전트가 주도하는 협상에 대한 정보는 투명하게 협상된 응답에 포함되어야
한다.

13 HTTP에서의 캐시

HTTP는 전형적으로 응답 캐시를 사용하여 성능을 향상시킬 수 있는 분산 정보 시스템에서
사용된다. HTTP/1.1 규약은 캐시 작업을 가능한 한 잘 수행하기 위한 몇몇 요소를 포함한다.
이러한 요소는 규약의 다른 측면에서 제외할 수 없는 것이기 때문에 또한 서로 상호 작용을
하기 때문에 method, 헤더, 응답 코드 등에 대한 자세한 설명과는 별도로 HTTP의 기본 캐시
디자인을 설명하는 것이 유용하다.

[Page 70]


성능을 상당히 개선하지 못한다면 캐시는 쓸모없는 것이 될 것이다. HTTP/1.1 캐시의 목적은
많은 경우에 요구를 발송할 필요를 제거하고 또 다른 많은 경우에 완전한 응답을 발송할 필요
를 제거하는 것이다. 전자는 많은 운영에서 네트워크의 왕복 여행 숫자를 줄여 준다. 우리는
이 목적을 위해서 "만기일" 메커니즘을 사용한다. (13.2 절 참조). 후자는 네트워크 대역폭 요
구를 감소시켜 준다. 우리는 이 목적을 위해서는 "검증" 메커니즘을 사용한다.( 13.3 절 참조)

성능, 가용성 및 단절된 운영에 대한 필요 조건이 우리에게 의미 투명성(semantic transparency)
의 목적을 완화할 수 있도록 요구한다. HTTP/1.1 규약은 원서버, 캐시, 클라이언트가 필요하다
면 분명하게 투명성을 감소할 수 있도록 한다. 그러나 비-투명적 작업은 비 전문가 사용자에
게 혼선을 줄 수 있고, 특정 서버 애플리케이션과 호환되지 않을 수 있기 때문에(제품 주문을
위한 애플리케이션처럼) 규약은 투명성을 완화시킬 것을 요구한다.

? 클라이언트나 원서버에 의해 완화되었을 때는 분명하게 규약 수준의 요구에 의해서만
? 캐시나 클라이언트에 의해 완화되었을 때는 사용자에게 분명한 경고를 줌으로써

[Page 71]


따라서 HTTP/1.1 규약은 다음의 중요한 요소를 제공한다.

1.  모든 참가자가 요구할 때 완전한 의미 투명성을 제공하는 규약 기능
 
2.  원서버나 사용자 에이전트가 비 투명적 작업을 분명하게 요청하고 제어할 수 있도록 하는
규약 기능
 
3.  캐시가 요구한 의미 투명성에 대한 근접 요구를 유지할 수 없는 응답에 경고를 첨부하는
규약 기능

기본 규칙은 클라이언트가 잠재적인 의미 투명성의 완화를 감지할 수 있어야 한다는 것이다.

주의 : 서버, 캐시 또는 클라이언트 구현자는 이 규격에서 분명하게 토의되지 않은 디자인을
결정해야 하는 문제에 직면하게 된다.  결정 사항이 의미 투명성에 영향을 미치게 되면 구
현자는 주의 깊고 완전한 분석이 투명성을 어김으로써 상당한 혜택을 주는 것으로 나타나지
않는 한 투명성을 유지하는 데 치우쳐야 한다.

13.1.1 캐시의 정확성

정확한 캐시는 반드시 아래의 조건 중 하나를 만족하며 요구에 적합한(13.2.5, 13.2.6 및 13.12
절 참조) 보유하고 있는 캐시 중 가장 최근의 응답으로 요구에 답해야 한다.

1.  원서버가 원서버를 사용하여 응답을 재검증한 후 되돌려 주었을 것과 같은 것인지 점검하
였다.( 13.3 절)
 
2.  충분히 신선하다.( 13.2 절 참조). 기본적인 경우 이것은 클라이언트, 서버 및 캐시의 최소
한도의 신선도 필요 조건을 만족한다는 것을 의미한다.(14.9 절 참조). 원서버가 그렇게 명
시하였으면 그것은 원서버의 신선도 필요 조건일 뿐이다.
 
3.  클라이언트 또는 서버의 신선도 요구가 위반되었을 경우(13.1.5 또는 14.45 절 참조) 경고
를 포함하고 있다.
 
4.  적절한 304 (Not Modified), 305 (Use Proxy), 또는 error (4xx or 5xx) 응답 메시지이다.

캐시가 원서버와 통신할 수 없다면 정확한 캐시는 위처럼 응답해야 한다.(캐시가 정확한 응답
을 할 수 있다면). 그렇지 못하면 캐시는 통신 실패가 있었음을 알리는 에러 또는 경고를 리
턴해야 한다.

[Page 72]


캐시가 보통 클라이언트로 전달하게 되는 응답을 수신하고(전체 응답 혹은 304(Not Modified)응
답) 수신한 응답이 더 이상 신선하지 않으면 캐시는 응답을 새로운 Warning(그러나 기존의
Warning헤더는 제거하지 않고)을 추가하지 않고 요구한 클라이언트로 전달한다. 캐시는 응답
이 그 동안 낡은 것이 되기 때문에 검증하려 시도해서는 안 된다. 시도하면 무한 루프로 빠지
게 될 것이다. Warning 없는 낡은 응답을 수신한 사용자 에이전트는 사용자에게 경고 표시를
할 수 있다.

13.1.2 경고

캐시가 처음이 아니거나 "충분히 신선하지"( 13.1.1 절의 조건 2의 의미) 않은 응답을 리턴할
때는 Warning Response-Header을 이용하여 이러한 취지로 경고를 부착하여야 한다. 이 경고는
클라이언트가 적절한 조치를 취할 수 있도록 한다.

경고는 캐시와 관련되거나 별도의 다른 목적을 위해 사용할 수 있다. 에러 상태 코드 대신 경
고를 사용하여 이 응답을 진짜 실패와 구별할 수 있게 한다.

경고는 응답의 투명성을 결코 약하게 하지 않기 때문에 언제나 캐시할 수 있다. 이는 경고를
HTTP/1.0에게 위험 없이 전달할 수 있음을 의미한다. 이러한 캐시는 단순히 경고를 응답의
Entity-Head헤드와 함께 전달한다.

경고는 0부터 99까지의 숫자로 지정한다. 이 규격은 코드 숫자와 현재 각각에 지정된 경고의
의미를 규정하여 클라이언트 또는 캐시가 몇몇 경우(모든 경우는 아니다.) 자동화된 조치를 취
할 수 있게 한다.

경고는 또한 경고문을 수반한다. 경고문은 적당한 자연 언어(아마도 클라이언트의 Accept 헤더
에 기초하여)로 작성될 수 있으며 선택적으로 사용된 문자 집합 표시를 포함할 수 있다.

동일한 코드 번호의 복수의 경고를 포함하는 복수의 경고가 응답에 부착될 수 있다.(원서버나
캐시에 의해서). 예를 들어 서버는 동일한 경고를 영어와 바스크어로 된 경고문으로 제공할
수 있다.

복수의 경고가 응답에 부착되었을 때 이 모두를 사용자에게 보여 주는 것은 실질적이지 않거
나 비합리적일 수 있다. 이 HTTP 버전은 어떤 경고를 어떤 순서에 입각하여 표시할 것인지
결정하는 엄격한 우선권 규칙은 명시하지 않지만 약간의 발견법(heuristics)을 제안하기는 한다.

[Page 73]


Warning 헤더와 현재 정의된 경고는 14.45 절에 기술되어 있다.

13.1.3 Cache-Control 메커니즘

HTTP/1.1의 기본적인 캐시 메커니즘(서버가 명시한 유효 시간 및 검증자)은 캐시에 내재된 지
시를 하는 것이다. 어떤 경우에 서버나 클라이언트는 내재된 지시자를 HTTP 캐시에게 제공할
필요가 있다. 우리는 Cache-Control 헤더를 이 목적으로 사용한다.

Cache-Control 헤더는 클라이언트나 서버가 요구나 응답의 다양한 지시자를 전달할 수 있도록
한다. 이 지시자는 대개의 경우 기본 캐시 알고리즘을 무시한다. 보편적인 원칙으로 만약 헤더
값 사이에 분명한 충돌이 있으면 가장 엄격한 해석을 사용해야 한다.(말하자면 의미 투명성을
가장 잘 보존할 수 있는 것). 그러나 어떤 경우에는 Cache-Control 지시자가 분명하게 의미 투
명성의 근사치를 약화시키는 것으로 명시할 수 있다.(예를 들어 "max-stale" 또는 "public"

Cache-Control 지시자는 14.9 절에 자세하게 기술되어 있다.

13.1.4 명백한 사용자 에이전트 경고

많은 사용자 에이전트는 사용자가 기본적인 캐시 메커니즘을 무시할 수 있도록 한다. 예를 들
어 사용자 에이전트는 사용자가 캐시 된 엔터티(분명하게 낡은 캐시까지도)를 결코 검증하지
말도록 명시하는 것을 허락한다. 또는 사용자 에이전트가 습관적으로 "Cache-Control: max-
stale=3600" 을 모든 요구 내에 첨가할 수도 있다. 사용자는 투명하지 않는 방식이나 비정상적
으로 비효과적인 캐시를 초래하는 방식을 확실하게 요구해야 한다.

사용자가 기본적인 캐시 메커니즘을 무시했다면 이것이 서버의 투명성 필요 조건을 만족시켜
주지 못할 정보 표시를 초래하게 될 때 사용자 에이전트는 항상 사용자에게 분명하게 표시해
주어야 한다. 보통 규약은 사용자 에이전트가 응답이 낡은 것인지 아닌지 여부를 결정할 수
있도록 하기 때문에 실제로 발생했을 경우에는 이것을 화면에 표시할 필요가 있다. 이 표시는
반드시 대화 박스일 필요는 없고 아이콘(예를 들어 부패된 생선 그림)이나 다른 시각적 표시
자일 수도 있다.

사용자가 캐시의 효과성을 비정상적으로 감소시키는 방식으로 캐시 메커니즘을 무시했다면 사
용자 에이전트는 계속해서 화면에 이를 표시(예를 들어 불타는 지폐 그림)하여 사용자가 부주
의하게 과도한 자원을 낭비하거나 지나치게 기다리지 않도록 해야 한다.

[Page 74]


13.1.5 규칙 및 경고의 예외 사항

어떤 경우에는 캐시 운영자는 클라이언트가 요구하지 않았어도 낡은 응답을 리턴하도록 환경
을 설정할 수 있다. 이러한 결정은 가볍게 해서는 안되지만 가용성이나 성능 특히 캐시가 원
서버와 약하게 연결되어 있을 때는 필요할 수도 있다. 캐시가 낡은 응답을 리턴할 때마다 이
러한 상태를 표시해야 한다.(Warning 헤더를 이용하여). 이렇게 하여 클라이언트 소프트웨어가
사용자에게 문제가 발생할 소지가 있음을 경고할 수 있도록 한다.

또한 사용자 에이전트가 처음 또는 새로운 응답을 얻는 조치를 취할 수 있도록 한다. 이러한
이유로 캐시는 클라이언트가 분명하게 처음 또는 새로운 캐시를 요구하면 기술적인 이유나 정
책적인 이유에 따르는 것이 불가능하지 않는 한 낡은 응답을 리턴해서는 안 되는 것이다.

13.1.6 클라이언트가 제어하는 행태

원서버(최소한 응답의 시간 경과에 공헌한 것을 감안하여 중간 캐시)가 만기일 정보의 주요
소스일 때 어떤 경우에는 클라이언트가 검증 없이 캐시 된 응답을 리턴할 것인지 여부에 대한
결정을 제어할 필요가 있다. 클라이언트는 몇몇 Cache-Control 헤더 지시자를 사용하여 이를
수행한다.

클라이언트의 요구는 검증되지 않은 응답을 접수할 수 있는 최대한의 경과시간을 명시한다.
이 값을 제로로 설정하면 캐시가 모든 응답을 재검증하도록 한다. 클라이언트는 응답이 만료
되기 전에 남아 있는 최소한의 시간을 명시한다. 이 두 선택 사항 모두 캐시의 행태에 대한
제한을 증대시키기 때문에 캐시의 의미 투명성 근사치를 추가로 완화시켜 주지는 못한다.

클라이언트는 또한 최대한 어떠한 수준까지의 낡은 응답을 접수할 것임을 명시할 수 있다. 이
것은 캐시에 대한 제한을 완화시켜 주기 때문에 원서버가 명시한 의미 투명성에 대한 제한 사
항을 위반할 수도 있지만 접속이 단절된 상태에서의 운용, 불량한 접속에 직면하여 높은 가용
성을 지원하기 위해 필요할 수도 있다.

13.2 만기일 모델

13.2.1 서버가 명시한 만기일

HTTP 캐시는 원서버로 요구를 발송하는 것을 완전히 피할 수 있을 때 최상으로 작동한다. 요
구를 피하는 주요 메커니즘은 원서버가 분명하게 해당 응답이 계속되는 요구를 만족시킬 수
있다는 것을 표시하는 미래의 만료 시간을 제공하는 것이다. 다른 말로 표현하면 캐시가 먼저
서버와 접촉하지 않고도 새로운 응답을 리턴할 수 있다는 것이다.

[Page 75]


우리가 기대하는 것은 서버가 만기일이 도착 전에 엔터티가 의미상으로 중대하게 변화하지 않
을 것이라는 믿음으로 미래의 분명한 만료 시간을 부여하는 것이다. 이렇게 하면 서버의 유효
시간이 신중하게 선택된 한 대개의 경우 의미 투명성을 보존한다.

유효일 메커니즘은 캐시에서 얻은 응답에만 적용되며 요구한 클라이언트에게 직접적으로 전달
되는 첫 응답에는 적용되지 않는다.

원서버가 모든 요구를 검증하기 위해 의미상으로 투명한 캐시를 요구한다면 과거 시점의 유효
시간을 부여할 수도 있다. 이는 응답이 항상 낡은 것이기 때문에 계속되는 요구에 이것을 사
용하기 위해서는 반드시 먼저 검증을 해야 한다는 것을 의미한다. 검증을 강제로 요구하는 제
한적인 방법에 관한 추가 정보는 14.9.4 절을 참조한다.

원서버가 HTTP/1.1 캐시가 모든 요구를 검증하도록 하려면 어떤 방식으로 환경이 설정되었든
"must-revalidate" Cache-Control 지시자(14.9 절 참조)를 사용해야 한다.

서버는 Expires 헤더 또는 Cache-Control 헤더의 max-age 지시자를 사용하여 분명하게 유효 시
간을 명시한다.

유효 시간은 사용자 에이전트가 자원을 화면에 표시하거나 갱신하도록 만드는 데 사용할 수
없다. 이 의미는 캐시 메커니즘에만 적용되며 이러한 메커니즘은 해당 자원에 대한 새로운 요
구가 시작되었을 때 자원의 유효일 상태만을 점검할 필요가 있다. 캐시와 history 메커니즘의
차이점에 대한 설명은 13.13 절을 참고한다.

13.2.2 스스로 유효일을 찾음(Heuristic Expiration)

원서버가 언제나 명백한 유효 시간을 제공하는 것이 아니므로 HTTP 캐시는 전형적으로 그럴
듯한 유효 시간을 짐작하기 위해 다른 헤더 값(Last-Modified 시간과 같은)을 사용하는 알고리
즘을 활용하는 발견법(heuristic) 유효 시간을 할당한다. HTTP/1.1 규격은 상세한 알고리즘을 제
공하지는 않지만 결과에 대한 최악의 경우 제한 사항을 부과하고 있다. 발견법에 의한 유효
시간은 의미 투명성 때문에 정확하지 않을 수도 있기 때문에 조심해서 사용해야 하며 우리는
원서버가 가능한 한 분명한 유효 시간을 제공하도록 권고한다.

[Page 76]


13.2.3 경과 시간 계산(Age Calculations)

캐시 된 엔트리가 새로운 것인지 확인하기 위해서 캐시는 캐시의 경과 시간이 신선한 기간
(freshness lifetime)을 초과했는지 알 필요가 있다. 신선한 기간을 계산하는 방법에 대해서는
13.2.4 절에서 토의하고 이 절에서는 응답이나 캐시 엔트리의 경과 시간을 계산하는 방법을 설
명한다.

이 설명에서 우리는 "지금" 이라는 용어를 "계산을 수행하는 호스트 시계의 현재 값"을 의미
하는 것으로 사용한다. HTTP 를 사용하는 호스트, 특히 원서버와 캐시를 운영하는 서버는
NTP [28] 나 유사 규약을 사용하여 자신의 시계를 국제적으로 정확한 시간 기준과 동시화해야
한다.

HTTP/1.1은 원서버가 모든 응답에 응답이 생성된 시간을 알려 주는 Date 헤더를 포함하여 발
송할 것을 요구한다는 점에 주의한다. 우리는 "date_value"라는 용어를 Date 헤더의 값을 사칙
연산에 적합한 형식으로 표시하는 것으로 사용한다.

HTTP/1.1은 Age Response-Header을 사용하여 캐시 사이의 경과 시간 정보를 전달한다. Age 헤
더 값은 응답이 원서버에서 생성된 이후의 발송자의 예측이다. 원서버가 검증한 캐시 된 응답
의 경우 Age 값은 원래의 응답이 아닌 재검증 시간에 기초한다.

핵심적으로 Age 값은 원서버로부터의 경로를 따라서 응답이 각 캐시에 보관되어 있던 시간의
총합 및 네트워크 경로를 따라서 이동되었던 시간의 양이다.

우리는 "date_value"라는 용어를 Date 헤더의 값을 사칙연산에 적합한 형식으로 표시하는 것으
로 사용한다.

응답의 경과 시간은 완전히 독립적인 두 가지 방법으로 계산할 수 있다.

1.  현재 마이너스 date_value, 지역 시계가 원서버 시계와 비교적 잘 동시화 되어 있을 경우.
결과 값이 마이너스이면 결과를 제로로 대체한다.
 
2.  age_value, 응답 경로에 따른 모든 캐시가 HTTP/1.1을 구현할 경우.

응답을 수신하였을 때 응답의 경과 시간을 계산하기 위한 두 가지의 독립적인 방법을 가지고
있다고 가정하면 우리는 그것들을 다음처럼 결합할 수 있다.

          corrected_received_age = max(now - date_value, age_value)

우리가 거의 동시화 된 시계와 모든 HTTP/1.1 경로를 가지고 있다면 신뢰할 만한(조심스러운)
결과를 얻을 수 있다.
 
[Page 77]


이러한 수정은 경로를 따라 각각의 HTTP/1.1 캐시에 적용되기 때문에 경로에 HTTP/1.0 캐시
가 있으면 수정된 수신 경과 시간을 수신하는 캐시의 시계가 거의 동시화 되어 있는 한 계산
할 수 있다. 양편 모두의 시계가 동시화 될 필요는 없으며(바람직하기는 하지만) 시계를 명백
하게 동시화(synchronization) 하는 절차는 없다.
 
네트워크가 부과한 지연때문에 서버가 응답을 생성한 시간 또는 다음의 외부 방향 캐시나 클
라이언트가 수신한 시간 이후로 중요한 중간 시간이 경과했을 수도 있다. 수정하지 않으면 이
러한 지연은 부적절하게 짧은 경과시간을 초래할 수도 있다.

리턴 된 Age 값을 생산하는 요구는 반드시 해당 Age 값이 생산되기 이전에 시작되어야 하기
때문에 요구가 시작된 시간을 기록함으로써 네트워크가 부과한 지연 시간을 결정할 수 있다.
따라서 Age 값이 수신되면 반드시 응답이 수신된 시간이 아닌 요구가 시작된 시간과 상대적
으로 해석해야 한다. 이 알고리즘은 얼마나 많은 지연 시간이 발생했는가에 관계없이 조심스
러운 행태를 낳게 된다. 따라서 우리는 다음과 같이 계산한다.

         corrected_initial_age = corrected_received_age
                               + (now - request_time)

여기서 "request_time"은 이 응답을 이끌어 낸 응답이 발송된 시간(지역 시계의 시간에 따라)이
다.

캐시가 응답을 수신했을 때 경과 시간 계산 알고리즘의 요약은 다음과 같다.

      /*
       * age_value
       *      는 Age의 값이다: 캐시가 이 응답과 더불어 수신한 헤더
       * date_value
       *      는 원서버의 Date 값이다: 헤더
       * request_time
       *      는 이 캐시 된 응답을 만들어 낸 요구를 캐시가 요구한
       *      (지역)시간이다.
       * response_time
       *      는 캐시가 응답을 수신한 (지역)시간이다.
       * now
       *      는 현재 (지역) 시간이다.
       */
      apparent_age = max(0, response_time - date_value);

[Page 78]


      corrected_received_age = max(apparent_age, age_value);
      response_delay = response_time - request_time;
      corrected_initial_age = corrected_received_age + response_delay;
      resident_time = now - response_time;
      current_age   = corrected_initial_age + resident_time;

캐시가 응답을 송신하였을 때 캐시는 응답이 지역적으로 보관되었던 시간의 양을
corrected_initial_age에 추가하여야 한다. 그런 다음 캐시는 이 합산된 경과 시간을 Age 헤더
를 이용하여 다음 수신측 캐시로 전달해야 한다.

클라이언트는 응답이 처음이라는 것을 신뢰성 있게 말할 수 없음을 주의해야 한다. 그러나
Age 헤더가 있다는 것은 응답이 분명 처음은 아니라는 것을 표시한다. 또한 응답의 Date가
클라이언트의 지역 요구 시간보다 앞설 경우 해당 응답은 아마도 첫 응답이 아닐 것이다.(심
각할 정도로 시계의 시간이 빗나가지 않았을 때)

13.2.4 유효일 계산

응답이 신선한지 낡은 것인지 결정하기 위해 우리는 경과된 시간과 신선한 기간(freshness
lifetime)을 비교할 필요가 있다. 경과된 시간은 13.2.3 절에서 설명한 대로 계산한다. 이 절은
신선한 기간을 계산하는 방법을 기술하고 응답이 만료되었는지 결정한다. 아래의 설명에서 값
은 사칙연산 수행에 적합한 어떠한 형식으로도 표현될 수 있다.

우리는 "expires_value" 라는 용어를 Expires 헤더 값을 표시하는 것으로 사용한다. 또한 우리는
"max_age_value" 라는 용어를 응답(14.10 절 참조)에 있는 Cache-Control 헤더의 max-age 지시자
가 가지고 있는 적절한 초 값을 의미하는 것으로 사용한다. 

max-age 지시자는 Expires보다 우선권을 갖는다. 따라서 응답에 max-age가 있으면 계산은 간
단히 다음과 같다.

         freshness_lifetime = max_age_value

그렇지 않고 Expires가 응답에 있으면 계산은:

         freshness_lifetime = expires_value - date_value

모둔 정보가 원서버에서 오기 때문에 두 계산 방법 모두 정확하지 않는 시계에 취약하지 않다
는 점에 유의한다.

Expires 및Cache-Control: max-age 모두가 응답에 없으면 해당 응답은 캐시에 대한 제약 사항을
포함하지 않는다.
[Page 79]


이 때 캐시는 발견법 사용하여 신선한 기간을 산출한다. 값이 24시간보다 클 때는 캐시는
Warning 13을, 이 경고가 추가되지 않았다면 경과 시간이 24시간 이상인, 응답에 첨가해야 한
다.

또한 응답이 Last-Modified 시간을 포함하고 있다면 발견법에 의한 유효일 값은 그 시간 이후
의 중간 시간의 한 부분보다 커서는 안 된다. 이 부분의 전형적인 설정값은 10%가 될 것이다.

응답이 만료되었는지 결정하기 위한 계산은 굉장히 단순하다:

         response_is_fresh = (freshness_lifetime > current_age)

13.2.5 유효일 값을 명확하게 하기

유효일 값이 낙천적으로 부여되기 때문에 두 캐시가 내용이 다른 동일한 자원에 대한 신선도
값을 포함할 수 있다.

조회 작업을 수행하는 클라이언트가 요구에 대해 이미 자체 캐시에서 신선했던 처음이 아닌
응답을 수신하면 기존 캐시 엔트리의 Date 헤더는 새로운 응답의 Date보다 새로운 것이다. 이
때 클라이언트는 응답을 무시할 수 있다. 만약 그렇다면 클라이언트는 원서버가 점검하도록
강요하기 위해 "Cache-Control: max-age=0" 지시자(14.9 절 참조)를 포함한 요구를 다시 시도할
수 있다.

캐시가 상이한 검증자의 동일한 표현을 위한 두개의 새로운 응답을 가지고 있으면 가장 최근
의 Date 헤더를 가지고 있는 것을 사용해야 한다. 이 상황은 캐시가 다른 캐시로부터 응답을
모을 수(pooling) 있고 클라이언트가 분명히 새로운 캐시 엔트리를 갱신 또는 재검증하도록 요
구할 수 있기 때문에 발생할 수 있다.

13.2.6 복수의 응답을 명확하게 하기

클라이언트가 복수의 경로를 통해 응답을 수신할 수 있기 때문에(어떤 응답은 한 캐시 세트를
통해서 오고 다른 응답은 다른 캐시 세트를 통해 올 수 있기 때문에) 클라이언트는 응답을 원
서버가 발송한 순서와 다르게 수신할 수도 있다. 이전의 응답이 아직도 분명 새롭다 할지라도
우리는 클라이언트가 가장 최근에 생성된 응답을 사용하기 바란다.

나중의 응답이 의도적으로 더 빠른 유효 시간을 가지고 있을 수 있기 때문에 엔트리 태그나
유효일 값 모두 응답의 순서에 대하여 영향을 미칠 수 없다. 그러나 HTTP/1.1 규격은 모든 응
답에 Date 헤더를 전송해야 하며 Date 값은 1 초 단위로 순서가 매겨져야 한다.

[Page 80]


클라이언트가 캐시 엔트리의 재검증을 시도할 때, 수신하는 응답이 기존 엔트리의 Date 헤더
보다 더 오래된 것처럼 보이는Date 헤더를 포함할 때 클라이언트는 요구를 무조건적으로 반
복해야 하며 다음을 포함해야 한다.

          Cache-Control: max-age=0

중간 캐시에게 자신의 사본을 원서버와 직접적으로 검증하도록 강요한다.

          Cache-Control: no-cache

중간 캐시에게 원서버에서 새로운 사본을 얻도록 강요한다.

Date 값이 동등하면 클라이언트는 양쪽 응답을 모두 사용할 수 있다. (또는 충분히 신중하다면
새로운 응답을 요구할 수 있다.) 서버는 두 응답의 유효일이 중첩된다면 클라이언트가 동일한
시간에 생성된 응답 중에서 하나를 과감하게 선택할 수 있다고 믿어서는 절대 안 된다.

13.3 검증 모델

캐시가 클라이언트 요구에 대한 응답으로 사용하고자 하는 낡은 엔트리를 가지고 있을 때 캐
시 된 엔트리를 아직도 사용할 수 있는지 알아보기 위해서 클라이언트는 먼저 원서버(새로운
응답을 가진 중간 캐시일 수도 있다.)를 점검해야 한다. 우리는 이것을 캐시 엔트리를 "검증한
다"고 한다. 우리는 캐시 된 엔트리의 상태가 좋을 때 전체 응답을 재전송해야 하는 오버헤드
를 갖길 원하지 않기 때문에, 또한 캐시 된 엔트리가 유효하지 않을 때 왕복 여행을 해야 하
는 오버헤드를 갖기 원하지 않기 때문에 HTTP/1.1 규약은 조건적인 method 사용을 지원한다.

조건적 method를 지원하는 핵심 규약 기능은 "캐시 검증자"에 관련된 것들이다. 원서버가 완
전한 응답을 생성할 때 서버는 일종의 검증자를 부착하며 이것은 캐시 엔트리와 함께 보관된
다. 클라이언트(사용자 에이전트 또는 프락시 캐시)가 캐시 엔트리를 가지고 있는 자원에 대한
조건적인 요구를 할 때 클라이언트는 요구에 관련된 검증자를 포함한다.

그런 다음 서버는 해당 검증자를 엔터티의 현재 검증자에 비추어 점검한다. 서로 일치하면 서
버는 특수 상태 코드(대개의 경우 304 (Not Modified))와 Entity-Body가 없는 것으로 응답한다.
따라서 우리는 검증자가 일치하면 전체 응답 전송을 피할 수 있고 일치하지 않으면 추가적인
왕복 여행을 피할 수 있다.

 [Page 81]


주의 : 검증자가 일치하는지 여부를 결정하는 데 사용되는 비교 기능은 13.3.3 절에 규정되
어 있다.

HTTP/1.1에서 조건적인 요구는 요구가 method(대개 GET)를 조건적으로 변경시키는 특수 헤더
(검증자를 포함하는)를 가지고 있는 경우를 제외하고는 동일한 자원에 대한 정상적인 요구와
정확하게 동일한 것처럼 보인다.

규약은 긍정적 및 부정적 의미의 Cache-Validation 조건을 포함한다. 이는 검증자가 일치하는
경우 및 일치하지 않는 경우 모두 method를 수행하도록 요구할 수 있다는 것이다.

주의 : 검증자가 없는 응답도 Cache-Control 지시자가 분명하게 금지하지 않는 한 캐시할 수
있으며 만료될 때까지 사용할 수 있다. 그러나 캐시는 엔터티에 대한 검증자가 없으면 조건
적인 조회를 할 수 없다. 이는 캐시가 만료된 다음에는 갱신할 수 없다는 것을 의미한다.

13.3.1 최종 갱신 날짜(Last-modified Dates)

Last-Modified Entity-Header 필드 값은 종종 캐시 검증자로 사용된다. 간단히 말하면 캐시 엔트
리는 엔터티가 Last-Modified 값 이후에 변경되지 않았으면 유효한 것으로 간주된다는 것이다.

13.3.2 엔터티 태그 캐시 검증자(Validators)

ETag Entity-Header 필드 값, 엔터티 태그는 "불투명한" 캐시 검증자를 제공한다. 이 검증자는
변경된 날짜를 저장하는 것이 불편한 상황에서, HTTP 날짜 값을 1초 동안 분석하는 것이 충
분하지 않은 상황에서 또는 원서버가 변경된 날짜를 사용하여 발생하는 특정 역설을 피하고자
하는 상황에서 좀더 신뢰성 있는 검증을 가능하게 한다.

엔터티 태그는 3.11 절에 기술되어 있고 엔터티 태그에 사용되는 헤더는 14.20, 14.25, 14.26 및
14.43 절에 기술되어 있다.

13.3.3 약한/강한 검증자

원서버 및 캐시 모두는 검증자가 동일한 엔터티를 표현하는지 상이한 엔터티를 표시하는지 결
정하기 위해 두 검증자를 비교하기 때문에 우리는 엔터티(Entity-Body 또는 모든 Entity-Header)
가 어떤 식으로든 변경되면 연관된 검증자도 또한 변경되리라 예상할 수 있다. 이것이 사실이
라면 우리는 이 검증자를 "강한 검증자"라고 부른다.

그러나 서버가 엔터티의 미미한 측면이 변화할 때보다는 의미상으로 중대한 변화에 대해서만
검증자를 변경하려 하는 경우가 있을 수 있다.
[Page 82]


자원이 변화할 때마다 변화하지 않는 검증자가 "약한 검증자" 이다.

엔터티 태그는 대개 "강한 검증자"이지만 규약은 엔터티 태그를 "약한" 것으로 태그를 붙일
수 있는 메커니즘을 제공한다. 우리는 강한 검증자를 엔터티의 일 부분이라도 변하면 따라서
변하는 것이고 약한 값은 엔터티의 의미가 변화할 때마다 변화한다고 생각할 수 있다. 다르게
표현하면 강한 검증자는 특정 엔터티에 사용되는 식별자의 일부분으로 약한 검증자는 의미상
으로 동일한 엔터티 세트를 위한 식별자의 일부라고 생각할 수 있다.

주의 : 강한 검증자의 한 예는 엔터티가 변할 때마다 불변 기억장치 내에서 증가되는 정수
이다.

엔터티의 변경 시간은 일 초 동안의 분석으로 표시된다면 약한 검증자일 수 있다. 자원이
일 초 동안 두 번 변경될 수 있기 때문이다.

약한 검증자를 지원하는 것은 선택 사항이다. 그러나 약한 검증자는 동일한 객체에 대한 좀
더 효과적인 캐시를 가능하게 한다. 예를 들어 사이트의 방문 카운터는 2 - 3일 또는 주마다
갱신해도 충분하다. 또한 이 기간 동안의 값은 충분히 동일한 것으로 간주할 수 있다.

검증자를 사용하는 것은 클라이언트가 요구를 생성하여 검증 헤더 필드에 검증자를 포함할
때 또는 서버가 두 검증자를 비교하는 때이다.

강한 검증자는 어떤 상황에서든지 유용하다. 약한 검증자는 엔터티가 완벽하게 동일하지 않아
도 되는 상황에서 유용하다. 예를 들어 강한 검증자만이 하부-영역 검색에 유용하다. 그렇지
않다면 클라이언트는 내부적으로 일치하지 않은 엔터티로 종결될 것이다.

HTTP/1.1 규약이 검증자에 규정한 유일한 기능은 비교이다. 비교 상황이 약한 검증자의 사용
을 허용하는가 여부에 따라 두 개의 검증자 비교 기능이 있다.

? 강한 비교 기능 : 동등한 것으로 간주되기 위해서 두 검증자는 모든 면에서 동일해야 하
며 모두 다 약한 검증자이면 안 된다.
 
? 약한 비교 기능 : 동등한 것으로 간주되기 위해서 두 검증자는 모든 면에서 동일해야 하
나 둘 중의 하나 또는 모두가 결과에 영향을 미치지 않고 "약한" 것으로 태그를 붙일 수
있다.

약한 비교 기능은 간단한(하부 영역이 아닌) GET 요구에 사용할 수 있다. 강한 비교 요구는
모든 다른 경우에 반드시 사용해야 한다.

[Page 83]


엔터티 태그는 분명하게 약한 것으로 태그를 붙이지 않는 한 강하다. 3.11 절에 엔터티 태그의
의미론이 있다.

요구의 검증자로 사용되었을 때 Last-Modified 시간은 다음의 규칙을 사용하여 강한 것으로 연
역할 수 없는 한 함축적인 의미에서 약하다.

? 원서버가 엔터티의 실제적인 현재 검증자와 검증자를 비교하고 있거나
? 원서버가 신뢰할 수 있을 정도로 관련된 엔터티가 제시된 검증자가 다루고 있는 동안 두
번 변경되지 않았다는 사실을 알 수 있다.
? 클라이언트가 연관된 엔터티의 캐시 엔트리를 가지고 있기 때문에 If-Modified-Since 또는
If-Unmodified-Since 헤더에서 검증자를 사용하려고 한다.
? 해당 캐시 엔트리가 원서버가 원래의 응답을 발송한 시간을 알려 주는 Date 값을 포함하
고 있다.
? 제시된 Last-Modified 시간이 최소한 Date 값보다 60초 이전이다.

또는

? 중간 캐시가 검증자와 엔터티에 사용되는 캐시 엔트리에 저장된 검증자를 비교하고 있는
중이다.
? 해당 캐시 엔트리가 원서버가 원래의 응답을 발송한 시간을 알려 주는 Date 값을 포함하
고 있다.
? 제시된 Last-Modified 시간이 최소한 Date 값보다 60초 이전이다.

이 method는 원서버가 두 개의 다른 응답을 같은 시간에 발송했으나 둘 모두 동일한 Last-
Modified 시간을 가지고 있으면 이 응답 중 최소한 하나는 Date 값이 Last-Modified 시간과 동
등하다는 사실에 기초하고 있다. 임의적인 60초 제한은 Date 와 Last-Modified 값이 별도의 시
계에서 생성되었거나 응답을 준비하는 동안 다른 시간대에 생성되었을 가능성에 대비시켜 준
다. 구현 방법에 60초가 너무 짧다고 생각되면 60초 이상의 값을 사용할 수 있다.

클라이언트가 Last-Modified 시간과 불투명하지 않은 검증자를 가지고 있는 값에 대하여 하부
영역 조회를 수행하고 싶으면 Last-Modified 시간이 여기에서 기술한 의미에서 강할 경우에만
수행할 수 있다.

[Page 84]


전체-본문 GET 요구 이외의 Cache-Conditional 요구를 수신하고 있는 캐시 또는 원서버는 반드
시 조건을 평가하기 위해 강한 비교 기능을 사용해야 한다.

이러한 규칙은 HTTP/1.1 캐시와 클라이언트가 HTTP/1.0 서버에서 획득된 값에 대하여 하부
영역 조회를 안전하게 수행할 수 있게 한다.

13.3.4 엔터티 태그와 최종 갱신 날짜를 사용할 때를 결정하는 규칙

어떠한 목적이건 다양한 검증자 유형을 사용해야 할 때의 원서버, 클라이언트 및 캐시를 위한
일련의 규칙과 권고안을 채택하였다.

   HTTP/1.1 원서버:

? 새로운 것을 생성하는 것이 불가능하지 않는 한 엔터티 태그 검증자를 발송해야 한다.
? 성능에 대해 고려했을 때 약한 엔터티 태그를 사용해도 될 때 또는 강한 엔터티 태그를
발송하는 것이 실현성이 없을 때 강한 엔터티 태그 대신 약한 엔터티 태그를 발송할 수도
있다.
? If-Modified-Since 헤더의 날짜를 사용하면 의미 투명성이 파괴될 위험성이 심각한 문제를
초래하지 않는 한, Last-Modified값을 발송하는 것이 가능하면 값을 보내야 한다.

달리 표현하면 HTTP/1.1 원서버의 바람직한 행태는 강한 엔터티 태그와 Last-Modified 값 모두
를 발송하는 것이다.

합법적이면 강한 엔터티 태그는 관련된 엔터티 값이 어떤 식으로든 변경될 때마다 변경되어야
한다. 약한 엔터티 태그는 관련된 엔터티가 의미상 상당히 변경되었으면 변경되어야 한다.

주의 : 의미상 투명한 캐시를 제공하기 위해서 원서버는 두 개의 별도 엔터티에 특정한 강
한 엔터티 값을 재사용하지 말아야 한다. 캐시 엔트리는 유효 시간에 관계없이 임의적으로
긴 기간동안 지속될 수 있다. 따라서 과거의 특정 시점에 획득한 검증자를 사용하는 캐시가
결코 엔터티를 검증하려 시도하지 않는다고 예상하는 것은 적절하지 않다.

   HTTP/1.1 클라이언트:

? 서버가 엔터티 태그를 제공하였으면 클라이언트는 어떠한 Cache-Conditional 요구에서든
지 그 엔터티 태그를 반드시 사용해야 한다.(If-Match 또는 If-None-Match를 사용)

[Page 85]



? 원서버가 단지 Last-Modified 값만을 제공했을 때 클라이언트는 하부 영역이 아닌
Cache-Conditional 요구에 그 값을 사용할 수 있다. (If-Modified-Since를 사용)
? HTTP/1.0 원서버가 Last-Modified 값만을 제공했을 때 클라이언트는 그 값을 하부 영역
의 Cache-Conditional 요구에 사용할 수 있다.(If-Unmodified-Since:를 사용). 사용자 에이전
트는 장애가 있을 경우 이 기능을 중지시킬 방법을 제공해야 한다.
? 원서버가 엔터티 태그 및 Last-Modified 값 모두를 제공했을 때 클라이언트는 양쪽 검증
자를 Cache-Conditional 요구에 사용해야 한다. 이것은 HTTP/1.1 및 HTTP/1.0 모두가 적
절히 응답할 수 있도록 한다.

요구를 접수하자마자 HTTP/1.1 캐시는 클라이언트의 캐시 엔트리가 캐시 자신의 캐시 엔트
리와 일치하는지 여부를 결정할 때 가장 제한적인 검증자를 반드시 사용해야 한다. 이것은
요구가 엔터티 태그와 last-modified-date 검증자(If-Modified-Since 또는 If-Unmodified-Since) 모
두를 포함하고 있을 때만 문제시 된다.

논리에 대한 주석 : 이 규칙 뒤의 일반적인 원칙은 HTTP/1.1 서버와 클라이언트는 자신의
응답 및 요구에서 최대한 중첩되지 않는 정보를 전달해야 한다는 것이다. 이 정보를 수신하
는 HTTP/1.1 시스템은 자신이 수신하는 검증자에 관한 가장 조심스러운 가정을 할 것이다.

HTTP/1.0 클라이언트와 캐시는 엔터티 태그를 무시할 것이다. 일반적으로 이 시스템들이 수
신하거나 사용하는 Last-Modified 값은 투명하거나 효과적인 캐시를 지원하기 때문에
HTTP/1.1 원서버는 Last-Modified 값을 제공해야 한다. HTTP/1.0 시스템이 Last-Modified 값을
검증자로 사용하여 심각한 문제를 초래하는 극히 드문 경우에는 HTTP/1.1 원서버는 값을 제
공하지 말아야 한다.

13.3.5 검증을 하지 않는 조건법

엔터티 태그 뒤의 원칙은 서비스 저작자만이 자원의 의미를 충분히 알아서 적합한 캐시 검증
메커니즘을 선택할 수 있다는 것이다. 바이트-동등(byte-equality) 비교보다 더 복잡한 검증자 비
교 기능을 열거하면 아주 복잡하게 될 것이다. 따라서 캐시 엔트리를 검증할 목적으로 다른
어떤 헤더의 비교(HTTP/1.0과의 호환성을 위해 Last-Modified는 제외) 도 사용해서는 안 된다.

13.4 응답을 캐시할 수 있는 정도(Cachability)

Cache-Control (14.9 절) 지시자가 특별히 통제하지 않는 한 캐시 시스템은 언제나 성공적인 응
답을 캐시 엔트리로서 저장할 수 있고, 새로운 것이라면 검증 없이 리턴할 수 있으며 성공적
인 검증 후에 리턴할 수도 있다.

[Page 86]


캐시 검증자도 없고 응답과 관련된 명확한 유효 시간도 없으면 우리는 그것을 캐시할 수 있다
고 기대하지 않는다. 그러나 특정한 캐시는 이러한 기대를 위반할 수도 있다.(예를 들어 네트
워크가 약하게 연결되었거나 연결되지 않았을 때). 클라이언트는 보통 이러한 응답이 캐시에
서 나왔다는 것을 Date 헤더와 현재 시간을 비교하여 탐지할 수 있다.

몇몇 HTTP/1.0 캐시는 아무런 Warning 도 제공하지 않고 이러한 기대를 위반하는 것으로 알
려졌다는 점에 주의한다.

그러나 어떤 경우에는 캐시가 엔터티를 보유하고 있는 것이, 또는 캐시를 계속되는 요구에 대
한 응답으로 리턴하는 것이 적절하지 않을 수 있다. 이는 서비스 저작자는 절대적인 의미 투
명성을 당연한 것으로 여기고 있기 때문이거나 또는 보안이나 사생활 보호에 관한 고려 사항
때문이다. 따라서 다른 고려 사항에 관계없이 특정 엔터티 또는 엔터티의 일부를 캐시할 수
없다는 것을 표시하기 위해 특정 Cache-Control 지시자가 제공되었다.

14.8 절은 대개 요구가 Authorization 헤더를 포함하고 있으면 공유된 캐시가 이전 요구에 대한
응답을 저장하거나 리턴할 수 없게 한다는 점에 주의한다.

Cache-Control 지시자가 캐시를 금지하지 않는 한 상태 코드 200, 203, 206, 300, 301 또는 410와
더불어 수신한 응답은 유효일 메커니즘을 조건으로 하여 캐시로 저장할 수 있고 계속되는 요
구에 대한 응답에 사용할 수 있다. 그러나 Range 및  Content-Range 헤더를 지원하지 않는 캐
시는 206(Partial Content) 응답을 절대로 캐시해서는 안 된다.

다른 상태 코드와 함께 수신된 응답은 Cache-Control 지시자나 이를 명백하게 허용하는 헤더가
없으면 계속되는 요구에 대한 응답으로 절대 리턴해서는 안 된다. 예를 들어 이러한 것들은
다음과 같다. - Expires 헤더 (14.21 절); "max-age", "must-revalidate", "proxy-revalidate", "public" 또
는 "private" Cache-Control 지시자 (14.9 절).

13.5 캐시에서 응답을 구축하기

HTTP 캐시의 목적은 요구에 대한 응답으로 수신된 정보를 저장하여 미래의 요구에 대한 응답
을 사용하기 위함이다. 많은 경우에 캐시는 단순히 요구자에게 응답의 적합한 부분을 리턴한
다. 그러나 캐시가 이전 응답에 기초한 캐시 엔트리를 보유하고 있으면 새로운 응답의 일 부
분과 기존 캐시 엔트리에 보관하고 있던 것을 결합해야만 한다.

[Page 87]


13.5.1 End-to-end 및 Hop-by-hop 헤더

캐시와 캐시를 지원하지 않는 프락시의 행태를 규정할 목적으로 우리는 HTTP 헤더를 두 종류
도 구분하였다.

? End-to-end 헤더 - 요구나 응답의 궁극적인 수신측에게 전달되어야 한다. 응답의 End-to-
end 헤더는 캐시 엔트리의 일 부분으로 저장되어야 하고 캐시 엔트리에서 구성된 어떠한
응답에도 전송되어야 한다.
? Hop-by-hop 헤더 - 단일-전송-수준 접속에만 의미가 있으며 캐시가 저장하지도 않고 프락
시가 전송하지도 않는다.

다음의 HTTP/1.1 헤더들이 hop-by-hop 헤더이다:

? Connection
? Keep-Alive
? Public
? Proxy-Authenticate
? Transfer-Encoding
? Upgrade

HTTP/1.1이 규정한 다른 모든 헤더는 end-to-end 헤더이다.

HTTP 향후 버전에 소개될 Hop-by-hop 헤더는 14.10 절에 기술한 것처럼 반드시 Connection 헤
더에 열거되어야 한다.

13.5.2 변경할 수 없는 헤더

Digest Authentication 과 같은 HTTP/1.1 규약의 몇몇 기능은 특정 end-to-end 헤더 값에 의존한
다. 캐시나 캐시를 지원하지 않는 프락시는 해당 헤더의 규정이 이를 요구하거나 특별히 허용
하지 않는 한 end-to-end헤더를 변경해서는 안 된다.

캐시나 캐시를 지원하지 않는 프락시는 요구나 응답에서 다음의 필드 중 어떤 것도 변경해서
는 안 되며 기존에 존재하지 않으면 추가해서도 안 된다.

? Content-Location
? ETag
? Expires
? Last-Modified

[Page 88]


캐시나 캐시를 지원하지 않는 프락시는 변환 금지 Cache-Control 지시어를 포함한 응답 또는
어떠한 요구에서도 다음의 필드 중 어떤 것도 변경하거나 추가해서는 안 된다.

? Content-Encoding
? Content-Length
? Content-Range
? Content-Type

캐시나 캐시를 지원하지 않는 프락시는 변환 금지(no-transform)를 포함하지 않은 응답에서 이
러한 필드를 변경하거나 추가해서는 안 된다. 그렇게 했다면 응답에 Warning 14(Modification
Applied)가 없으면 이를 추가해야 한다.

경고 : 불필요한 end-to-end 헤더의 변경은 HTTP의 이후 버전에서 더 강력한 인증 획득 메
커니즘이 도입된다면 인증 획득 실패를 초래할 수 있다. 이러한 인증 획득 메커니즘은 여기
에 열거되지 않은 헤더 필드 값에 의존할 수 있다.

13.5.3 헤더의 결합

캐시가 서버에게 검증 요구를 하고 서버가 304(Not Modified) 응답을 주었을 때 캐시는 요구한
클라이언트에게 발송하기 위해 응답을 구축해야 한다. 캐시는 캐시 엔트리에 보관된 Entity-
Body를 이 발송 응답의 Entity-Body로 사용한다. 캐시 엔트리에 저장된 end-to-end 헤더는 304
응답이 제공한 end-to-end 헤더가 캐시 엔트리에서 상응하는 헤더를 반드시 대체해야만 하는
경우를 제외하고 구축된 응답을 위해 사용된다. 캐시가 캐시 엔트리를 제거하기로 결정하지
않는 한 캐시는 반드시 캐시 엔트리에 저장된 end-to-end 헤더를 들어오는 응답에서 수신한 헤
더로 대체해야 한다.

달리 표현하면 들어오는 메시지에서 수신한 end-to-end 헤더 세트가 캐시 엔트리에 저장된 모
든 end-to-end 헤더를 무시한다는 것이다. 이 캐시는 이 세트에 Warning 헤더를 추가할 수 있
다.(14.45 절 참조)

들어오는 응답의 헤더 필드 이름이 캐시 엔트리의 헤더와 하나 이상 일치하면 이러한 모든 오
래된 헤더는 대체된다.

주의 : 이 규칙은 원서버가 304(Not Modified) 응답을 사용하여 동일 엔터티에 대한 이전 응
답에 관련된 헤더를 갱신할 수 있도록 해 준다. 이렇게 하는 것이 항상 의미가 있거나 올바
를 것은 아닐 수 있다. 이 규칙은 원서버가 304(Not Modified) 응답을 사용하여 이전 응답에
제공했던 헤더를 완전히 삭제할 수 있도록 허용하는 것은 아니다.

[Page 89]


13.5.4 바이트 영역(Byte Ranges)의 결합

응답은 요구가 하나 또는 그 이상의 Range 규격을 포함하고 있거나 접속이 조기에 단절되었
기 때문에 Entity-Body 바이트의 하부 영역만을 전송할 수 있다. 이러한 방식으로 몇 번 전송하
면 캐시는 동일한 Entity-Body의 몇몇 영역을 수신할 수 있을 것이다.

캐시가 엔터티의 저장되어 있고 공백이 아닌 하부 영역 세트를 가지고 있고 또한 들어오는 응
답이 다른 하부 영역을 전송한다면 캐시는 새로운 하부 영역을 기존의 세트와 결합할 수 있다.
(아래의 두 조건을 모두 만족해야 한다.)

? 들어오는 응답과 캐시 엔트리 모두 캐시 검증자를 가지고 있어야 한다.
? 두 캐시 검증자는 강한 비교 기능(13.3.3 절 참조)을 사용하여 서로 일치해야 한다.

두 조건 모두가 만족되지 않으면 캐시는 가장 최근의 부분 응답(모든 응답과 함께 전송되는
Date 값에 기초하거나 또는 이 값이 동등하거나 빠져 있으면 들어오는 응답을 사용하여)만을
사용해야 하고 다른 부분 정보는 폐기해야 한다.

13.6 협상을 통한 응답을 캐시하기

응답의 Vary 헤더 필드의 존재로 표시되는 서버가 주도하는 내용 협상(12 장)의 사용은 캐시
가 계속적인 요구에 대한 응답에 사용할 수 있는 조건 및 절차를 변경한다.

서버는 Vary 헤더 필드(14.43 절)를 사용하여 캐시에게 어떤 헤더 필드 차원을 이용하여 캐시
할 수 있는 응답의 다양한 표시 방법 중에서 하나를 선택하였는지 알려 준다. 캐시는 해당 자
원에 대한 계속적인 요구에 응답하기 위하여 계속되는 요구가 Vary Response-Header 안에 명시
된 모든 헤더 필드의 동일 또는 동등한 값을 가지고 있을 때만 선택된 표시 방법(특정 응답에
포함된 엔터티)을 이용할 수 있다. 하나 또는 그 이상의 이러한 헤더 필드를 가진 요구는 원
서버로 전송될 것이다.

엔터티 태그가 표시 방법에 부여되었을 때 전송된 요구는 조건적이어야 하며 Request-URI의
모든 캐시 엔트리로부터의 If-None-Match 헤더 필드에 있는 엔터티 태그를 포함해야 한다. 이
것은 현재 캐시가 가지고 있는 엔터티 세트를 서버에게 전달한다. 이렇게 함으로써 만약 이
엔터티 중 하나라도 요구된 엔터티와 일치한다면 서버는 304 (Not Modified) 응답의 ETag 헤더
를 이용하여 어떤 엔트리가 적합한지 캐시에게 알려 준다. 새로운 응답의 Entity-Tag가 기존
엔트리의 Entity-Tag와 일치한다면 새로운 응답을 이용하여 기존 엔트리의 헤더 필드를 갱신
해야 하고 결과는 클라이언트에게 돌려주어야 한다.

[Page 90]


또한 Vary 헤더 필드는 캐시에게 Request-Header에 한정되지 않은 범주를 이용하여 표시 방법
이 선택되었음을 알릴 수 있다. 이 경우 캐시는 캐시가 새로운 요구를 조건적인 요구로 원서
버에게 중계하거나 서버가 엔터티 태그 또는 어떤 엔터티를 사용하여야 하는지 표시하는
Content-Location을 포함하여 304(Not Modified)로 응답하지 않는 한 응답을 계속되는 요구에 대
한 대답으로 사용해서는 절대 안 된다.

기존의 캐시 엔트리 중 어떤 것이라도 관련된 엔터티의 부분적인 내용을 포함하고 있다면 요
구가 해당 엔트리가 충분히 충족시킬 수 있는 영역에 관한 것이 아닌 이상 그것의 Entity-Tag
를 If-None-Match 헤더에 포함해서는 안 된다.

캐시가 Content-Location 필드가 동일한 Request-URI를 위한 기존 캐시 엔트리의 그것과 일치
하며 Date가 기존 엔트리의 그것보다 최신인 성공적인 응답을 수신하였으면 기존의 엔트리를
향후 요구에 대한 응답으로 리턴해서는 안 되며 캐시에서 삭제해야 한다.

13.7 공유/비공유 캐시

보안 및 사생활 보호의 이유 때문에 "공유" 및 " 비공유" 캐시를 구별할 필요가 있다. 비공유
캐시는 단일 사용자만 접근할 수 있는 캐시이다. 이 경우의 접근성은 적절한 보안 메커니즘으
로 집행된다. 다른 모든 캐시는 "공유"된 캐시로 간주된다. 이 규격의 다른 섹션에서는 공유된
캐시의 운영에 대해 사생활 보호와 접근 통제 실패를 방지하기 위하여 어떠한 제한을 두고 있
다.

13.8 에러 또는 불완전한 응답 캐시 행태

불완전한 응답을 수신하는 캐시(예를 들어 Content-Length 헤더에 명시된 것보다 적은 데이터)
는 응답을 저장할 수 있다. 그러나 캐시는 이것을 부분적 응답으로 처리해서는 안 된다. 부분
적 응답은 13.5.4 절에서 기술한 것처럼 결합할 수 있다. 그 결과는 완전한 응답이 될 수도 있
고 여전히 부분적일 수도 있다. 캐시는 클라이언트에게 분명하게 206(Partial Content) 상태 코드
를 사용하여 그렇다고 표시하지 않고는 부분적 응답을 리턴해서는 안 된다. 캐시는 상태 코드
200(OK)을 이용하여 부분적 응답을 리턴해서는 절대로 안 된다.

캐시가 엔트리를 재검증하려 시도하는 동안 5xx 응답을 수신하면 캐시는 이 응답을 요구한 클
라이언트에게 전송하든지 서버가 응답에 실패한 것처럼 처리해야 한다. 후자의 경우 캐시 된
엔트리가 "must-revalidate" Cache-Control 지시자(14.9 절 참조)를 포함하고 있지 않으면 캐시는
이전에 수신된 응답을 리턴할 수도 있다.

[Page 91]


13.9 GET 및 HEAD의 부작용

원서버가 분명하게 자신의 응답을 캐시하는 것을 금지하지 않는 한 GET 및 HEAD method를
어떤 자원에 적용하는 것은 이러한 응답이 캐시에서 왔다면 잘못된 행태로 이끄는 부작용을
갖지 않아야 한다. 그래도 부작용은 있을 수 있으나 캐시는 캐시 실행 여부에 대한 결정을 할
때 이러한 부작용을 고려하도록 요구 받지는 않는다. 캐시는 항상 원서버의 캐시에 대한 명백
한 제한 사항을 준수할 것으로 예상된다.

우리는 이 규칙에 대한 예외 하나를 기록하고자 한다: 몇몇 애플리케이션은 전통적으로 GET
과 HEAD를 질의 URL(rel_path part에 "?"를 포함한 URL)과 함께 사용하여 상당한 부작용을
가진 작업을 수행했다. 캐시는 서버가 분명한 유효 시간을 제공하지 않는 한 이러한 URL에
대한 응답을 새로운 것으로 취급해서는 안 된다. 이것은 특히 HTTP/1.0 서버로부터의 응답을
캐시에서 가져와서는 안 된다는 것을 의미한다. 관련된 정보를 9.1.1 절을 참고한다.

13.10 갱신 또는 삭제 후의 무효화

원서버에서 특정 method의 결과는 하나 또는 그 이상의 기존 캐시 엔트리를 투명하지 않게
무효한 것으로 만들 수 있다. 이는 비록 캐시가 계속해서 "새롭지만" 이것이 원서버가 새로운
요구를 받았을 때 리턴할 것을 정확하게 반영하지는 않는다.

HTTP 규약이 모든 이러한 캐시를 무효한 것으로 표시한다는 보장을 할 방법이 없다. 예를 들
어 원서버의 변화를 초래한 요구가 캐시 엔트리가 저장되어 있는 프락시를 거치지 않았을 수
도 있다. 그러나 몇몇 규칙이 잘못된 행태가 발생할 수 있는 경우를 감소시켜 준다.

이 섹션에서 "엔트리를 무효화 한다"는 것은 캐시가 해당 엔터티의 모든 경우(instance)를 저장
장소에서 삭제하고, "무효"로 표시하며 계속되는 요구에 대한 응답으로 리턴하기 전에 의무적
으로 재검증을 할 필요가 있다는 것을 의미한다.

[Page 92]


몇몇 HTTP method는 엔터티를 무효화할 수 있다. 그것은 Request-URI로 참조하거나  Location
또는 Content-Location Response-Header(존재한다면)로 참조하는 엔터티이다. 그러한 method는:

? PUT
? DELETE
? POST

서비스 시도의 거절을 방지하기 위해 Location 또는 Content-Location 헤더의 URI에 기초한 무
효화는 오직 호스트 부분이 Request-URI의 호스트 부분과 동일할 경우에만 실행해야 한다.

13.11 의무적으로 서버를 통하여 기입(Write-Through Mandatory)

원서버 자원에 대한 변경을 초래할 것으로 예상되는 모든 method는 원서버를 통하여 기입해
야 한다. 현재 이것은 GET 및 HEAD를 제외한 모든 method를 포함한다. 캐시는 수신하는 쪽
서버로 요구를 전달하기 전 및 수신하는 쪽 서버로부터 상응하는 응답을 수신하기 전에 절대
로 클라이언트에서 이러한 요구에 응답해서는 안 된다. 이것이 캐시가 수신하는 쪽 서버가 응
답하기 전에 100 (Continue) 응답을 발송하는 것을 방지하지는 못한다.

대안("역으로 쓰기(write-back)" 또는 "역으로 복사(copy-back)" 캐시로 알려진)은 역으로 쓰기
(write-back) 이전의 서버, 캐시 또는 네트워크 실패 때문에 발생하는 문제와 지속적인 갱신을
제공하기 어렵기 때문에 HTTP/1.1에서 허용되지 않는다.

13.12 캐시 대체

모든 동일한 자원에 대한 기존 응답이 캐시되었을 때 새로운 캐시할 수 있는(14.9.2, 13.2.5,
13.2.6 및13.8 절 참조) 응답을 자원으로부터 수신하였으면 캐시는 현재 의 요구에 대한 대답
을 할 때 새로운 응답을 사용해야 한다. 캐시는 그것을 캐시 저장소에 삽입하고 모든 다른 조
건이 충족되면 이전 응답이 리턴 되었을 수도 있는 미래의 요구에 대한 응답으로 사용한다.
새로운 응답을 캐시 저장소에 삽입한다면 13.5.3 절의 규칙을 따라야 한다.

주의 : 기존에 캐시된 응답보다 오래된 Date 헤더 값을 가진 새로운 응답을 캐시할 수 없다.

13.13 히스토리 목록(History list)

사용자 에이전트는 종종 "이전" 버튼과 history 목록과 같은 history 메커니즘을 사용한다. 이것은
세션에서 이전에 조회한 엔터티를 다시 화면에 표시하기 위해 사용한다.

[Page 93]


history 메커니즘과 캐시는 다르다. 특히 history 메커니즘은 자원의 현재 상태를 의미상 투명한
모양으로 보여 주려 시도해서는 안 된다. history 메커니즘은 자원을 조회했을 때 사용자가 본
것과 동일한 것을 보여 주기 위한 것이다.

기본적으로 유효 시간은 history 메커니즘에 적용되지 않는다. 엔터티가 여전히 저장소에 있으
면 history 메커니즘은 엔터티가 만료되었다 할지라도 사용자가 만료된 history 문서를 갱신하
도록 상세하게 에이전트의 환경을 설정하지 않은 한 이것을 보여 주어야 한다.

이것은 history 메커니즘이 사용자에게 현재 의 화면이 낡은 것일 수도 있음을 알리는 것을 금
지하는 것으로 해석해서는 안 된다.

주의 : History 목록 메커니즘이 불필요하게 사용자가 낡은 자원을 볼 수 없도록 한다면 이는
서비스 저작자들에게 그렇지 않았더라면 사용하고 싶어하는  HTTP 유효일 제어 및 캐시 제
어의 사용을 피하도록 강요할 수 있다. 서비스 저작자들은 그들이 운행 제어("이전" 버튼과
같은 navigation control)를 사용하여 이전에 가져온 자원을 보고자 할 때 사용자에게 에러 메
시지나 경고 메시지를 표시하지 않는 것이 중요하다고 생각할 수 있다. 때때로 이러한 자원
을 캐시하지 말거나 빨리 만료해야 할 수도 있지만 서비스 저작자들은 사용자 인터페이스를
고려하여 사용자가 history 메커니즘이 부적합하게 작동하여 고통을 받지 않도록 캐시를 방
지할 수 있는(예를 들어 "once-only" URL) 다른 방법에 호소하도록 만든다.

14 헤더필드 정의

이 섹션은 HTTP/1.1의 모든 표준 헤더 필드에 형식과 의미를 정의한다. Entity-Header 필드에
서 발송자와 수신측은 누가 엔터티를 발송하고 누가 엔터티를 수신하는가에 따라 클라이언
트 또는 서버 모두를 지칭할 수 있다.

[Page 94]


14.1 Accept

Accept request-header 필드는 응답에 사용할 수 있는 특정 media type을 명시하는 데 사용할 수
있다. Accept 헤더는 라인에 포함된 이미지(in-line image)에 대한 요구처럼 요구가 상세하게 원
하는 유형의 작은 세트에 한정되어 있음을 표시하는 데 사용한다.

          Accept          = "Accept" ":"
                            #( media-range [ accept-params ] )

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

          accept-params   = ";" "q" "=" qvalue *( accept-extension )

          accept-extension  = ";" token [ "=" ( token | quoted-string ) ]

별표("*") 문자는 media type을 영역으로 그룹핑하는 데 사용한다. "*/*"는 모든 media type을,
"type/*은 해당 type의 모든 subtype을 표시한다. Media-range는 해당 영역에 적용할 수 있는
media type 파라미터를 포함할 수 있다.

모든 media-range에는 하나 또는 그 이상의 상대적 품질 요소를 표시하는 "q" 파라미터로 시
작하는 accept-params가 뒤따른다. 처음의 "q" 파라미터(있다면)는 media-range 파라미터를
accept-params로부터 분리시킨다. 품질 요소(quality factor)는 사용자 또는 사용자 에이전트가
qvalue(섹션 3.9) 척도를 0부터 1까지 사용하여 해당 media-range에 대한 상대적 선호도를 표
시할 수 있도록 한다. 기본값은 q=1이다.

주의 : "q" 파라미터 이름을 media type 파라미터를 Accept 확장 파라미터로부터 분리하는 데
사용하는 것은 계속적인 관행 때문이다. 이 관행이 어떠한 media type 파라미터에도 "q"라는
이름을 media range에 사용할 수 없게 하지만 IATA media type 등록표에서 "q" 파라미터가 많
이 사용되지 않고 있고 Accept에서 media type 파라미터를 잘 사용하지 않는다는 점을 감안
할 때 이러한 경우는 발생하기 어렵다. 향후 media type은 "q"라는 이름의 파라미터를 등록
하지 말아야 한다.

예:

          Accept: audio/*; q=0.2, audio/basic

위의 문장은 "나는 audio/basic을 선호하지만 80% 이하로 질이 떨어지면 사용할 수 있는 가장
좋은 다른 audio type을 발송해 주시오."로 해석해야 한다.

[Page 95]


Accept 헤더 필드가 없다면 클라이언트가 모든 media type을 수용한다고 가정한다. Accept 헤더
필드가 있고 서버가 결합된 Accpet 필드 값에 적합한 응답을 발송할 수 없을 때 서버는 406
(not acceptable) 응답을 발송해야 한다.

좀더 자세한 예는

          Accept: text/plain ; q=0.5, text/html,
                 text/x-dvi; q=0.8, text/x-c

말로 표현한다면 이것을 "text/html 및 text/x-c가 선호하는 media type이지만 이것이 존재하지
않으면 text/x-dvi 엔터티를 발송하고 존재하면 text/plain 엔터티를 발송하시오."라고 해석할 수
있다.

Media ranges는 좀더 상세한 media range 및 media type에 의하여 무시될 수 있다. 특정 type에
하나 이상의 media range를 적용했을 때 가장 상세한 것이 우선권을 갖는다. 예를 들면,

          Accept: text/*, text/html, text/html;level=1, */*

은 다음의 우선순위를 가진다.

          1) text/html;level=1
          2) text/html
          3) text/*
          4) */*

특정 type과 관련된 media type 품질 요소는 해당 type에 일치하는 media range 중 최고의 우선
권을 갖는 것을 발견하여 결정한다. 예를 들어,

          Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
                  text/html;level=2;q=0.4, */*;q=0.5

는 아래와 같은 값이 연관되도록 한다.

          text/html;level=1          = 1
          text/html                 = 0.7
          text/plain                = 0.3
          image/jpeg               = 0.5
          text/html;level=2          = 0.4
          text/html;level=3          = 0.7

주의 : 사용자 에이전트는 특정 media range에 대한 품질의 기본 값 세트를 가지고 있을 수
있다.

[Page 96]


그러나 사용자 에이전트가 다른 표시 에이전트와 상호 작용할 수 없는 폐쇄된 시스템이 아
니라면 기본 값 세트는 사용자가 설정할 수 있어야 한다.

14.2 Accept-Charset

Accept-Charset request-header 필드는 응답에 사용할 수 있는 문자 조합을 표시하는 데 사용한다.
이 필드는 광범위하고 전문적인 목적의 문자 조합을 이해할 수 있는 클라이언트가 이러한 문
자 조합으로 문서를 표시할 수 있는 서버에게 자신의 능력을 알려 줄 수 있도록 한다. 모든
클라이언트는 ISO-8859-1문자 조합을 사용할 수 있는 것으로 가정한다.

          Accept-Charset = "Accept-Charset" ":"
                    1#( charset [ ";" "q" "=" qvalue ] )

문자 조합 값은 3.4 절에 설명되어 있다. 각각의 charset는 해당 charset에 대한 사용자의 선호
사항을 표시하는 관련된 품질 값을 가질 수 있다. 기본값은 q=1이며 예는 다음과 같다.

          Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

Accept-Charset 헤더가 있으면 기본값은 모든 문자 조합을 사용할 수 있다. Accept-Charset 헤더
가 있고 서버가 Accept-Charset 헤더를 사용할 수 있는 응답을 발송할 수 없을 때 비록 응답을
발송할 수는 있지만 서버는 406 (not acceptable) 상태 코드의 에러 메시지를 발송해야 한다.

14.3 Accept-Encoding

Accept-Encoding request-header 필드는 Accept와 유사하지만 응답에서 사용할 수 있는 content-
coding 값(섹션 14.12)에 제한이 있다.

          Accept-Encoding  = "Accept-Encoding" ":"
                                    #( content-coding )

이의 사용 예는,

          Accept-Encoding: compress, gzip

요청에 Accept-Encoding 헤더가 없으면 서버는 클라이언트가 어떠한 content coding도 접수할
수 있다고 가정할 수 있다. Accept-Encoding 헤더가 있고 서버가 Accept- Encoding 헤더를 사용
할 수 있는 응답을 발송할 수 없을 때 비록 응답을 발송할 수는 있지만 서버는 406 (not
acceptable) 상태 코드의 에러 메시지를 발송해야 한다.

[Page 97]


값이 비어 있으면 아무 것도 접수할 수 없음을 표시한다.

14.4 Accept-Language

Accept-Language request-header 필드는 Accept와 유사하지만 요구에 대한 응답으로 사용할 수
있는 자연스러운 언어(natural languages) 세트에 제한이 있다.

          Accept-Language  = "Accept-Language" ":"
                             1#( language-range [ ";" "q" "=" qvalue ] )

          language-range   = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )

각각의 language-range는 해당 range가 명시하는 언어에 대한 사용자의 예상 선호 상태를 표시
하는 관련 품질 값을 가지고 있다. 품질 기본 값은 "q=1" 이며 예는 다음과 같다.

          Accept-Language: da, en-gb;q=0.8, en;q=0.7

이것은 "나는 덴마크어를 선호하지만 영국 영어 및 다른 유형의 영어도 접수할 것이다."를 의
미한다. 태그가 완전히 동일하거나 접두사 뒤의 첫 태그 문자가 "-" 이면 language-range 는
language-tag 와 일치한다. 특수 영역(special range) "*"가 Accept-Language 필드에 있으면 Accept-
Language 필드에 있는 다른 range에 일치하지 않는 모든 태그를 일치시켜 준다.

주의 : 접두사 일치 원칙의 사용은 언어 태그가 "사용자가 특정 태그의 언어를 이해한다면
이 사용자는 이 태그가 접두사로 쓰인 모든 언어 태그를 이해할 것이다."라는 것이 항상 사
실이라는 방식으로 부여 되었다는 것을 의미하지는 않는다. 접두사 원칙은 단순히 이것이
사실일 경우에만 접두사 사용을 허락하는 것이다.

Accept-Language 필드의 language-tag가 부여한 언어 품질 요소는 language-tag와 일치하는 필드
의 가장 긴 language-range 품질 값이다. 필드의 language-range와 일치하는 태그가 없으면 언어
품질 요소는 0으로 부여된다. 요구에 Accept-Language 헤더가 없으면 서버는 모든 언어를 동
등하게 수용할 수 있다고 가정해야 한다. Accept-Language 헤더가 있으면 0 이상의 품질 요소
를 부여 받은 모든 언어를 수용할 수 있다.


모든 요구에 사용자의 전체적인 언어 선호 상태를 포함한 Accept-Language 헤더를 발송하는
것이 사용자의 사생활 보호에 대한 기대에 역행할 수도 있다. 이 문제에 관한 토의는 15.7 절
을 참조한다.

[Page 98]


주의 : 이해정도(intelligibility)는 개별적인 사용자에 따라 다르므로 클라이언트 애플리케이션
은 사용자가 원하는 언어를 선택할 수 있도록 할 것을 추천한다. 선택을 할 수 없으면 요구
에 Accept-Language 헤더 필드를 제공해서는 안 된다.

14.5 Accept-Ranges

Accept-Ranges response-header 필드는 서버가 자원에 대한 영역 요구(range requests)를 접수하였
다는 것을 표시한다.

          Accept-Ranges      = "Accept-Ranges" ":" acceptable-ranges

          acceptable-ranges   = 1#range-unit | "none"

Byte-range 요구를 접수한 원서버는 다음과 같이 발송할 수 있다.

          Accept-Ranges: bytes

그러나 반드시 이렇게 해야 하는 것은 아니다. 클라이언트는 관련된 자원에 대해 이 헤더를
수신하지 않고도 byte-range 요구를 생산할 수 있다.

어떠한 형태의 byte-range 요구도 접수하지 않는 원서버는 다음을 발송하여 클라이언트가 영역
요구를 시도하지 말도록 충고할 수 있다.

          Accept-Ranges: none

14.6 Age

Age response-header 필드는 원서버가 응답(또는 이의 검증)을 생성한 이후 시간에 대한 발송자
의 예상 값을 전달한다. 캐시된 응답은 경과 시간이 신선한 시간(freshness lifetime)을 초과하지
않았으면 "신선하다." 경과 시간 값은 13.2.3절에 기술한 바와 같이 산출한다.

           Age = "Age" ":" age-value

           age-value = delta-seconds

경과 시간 값은 음수가 아닌 십진수 정수이며 시간을 초로 표시한다.

[Page 99]


캐시가 가장 크게 표시할 수 있는 정수 값보다 큰 값을 수신하거나 경과 시간 계산이 오버플
로우(overflow)되면 Age 헤더의 값을 반드시 2147483648 (2^31)로 전송해야 한다. HTTP/1.1 캐시
는 모든 응답에 반드시 Age 헤더를 발송해야 한다. 캐시는 최소 31 비트 범위의 사칙연산 유
형 값을 사용해야 한다.

14.7 Allow

Allow entity-header 필드는 Request-URI 가 식별한 자원이 지원하는 method 세트 목록을 표시한
다. 이 필드의 용도는 엄격하게 자원과 관련된 유효한 method의 수신을 알리기 위함이다.
Allow 헤더 필드는 반드시 405 (Method Not Allowed) 응답 내에 표시되어야 한다.

          Allow          = "Allow" ":" 1#method

이의 사용 예는,

          Allow: GET, HEAD, PUT

이 필드는 클라이언트가 다른 methods를 사용하고자 시도하는 것을 방지할 수는 없다. 그러나
Allow 헤더 필드가 표시하는 내용은 준수해야만 한다. 사용할 수 있는 실제 세트는 각 요구가
발송되는 시점에서 원서버가 결정한다.

Allow 헤더 필드에 PUT 요청을 새롭거나 변경된 자원이 지원하는 method를 추천하기 위해
포함할 수 있다. 서버가 반드시 이러한 method를 지원할 필요는 없으나 실제적으로 사용할 수
있는 method를 제공하는 Allow 헤더 필드를 응답에 포함해야만 한다.

프락시는 명시된 모든 method를 이해하지 못하더라도 사용자 에이전트가 다른 수단을 통하여
원서버와 통신할 수도 있기 때문에 Allow 헤더 필드를 변경해서는 절대로 안 된다.

Allow 헤더 필드는 서버 수준에서 어떠한 method가 구현되었는가 표시하지 않는다. 서버는 전
체적으로 서버 상에서 어떠한 method가 구현되었는가 표시하기 위해 Public response-header 필
드(섹션 14.35)를 사용할 수 있다.

14.8 Authorization

서버에서 자신을 인증하고자 하는 사용자 에이전트는(꼭 그런 것은 아니지만 대개의 경우 401
응답을 수신한 후) 요구에 Authorization request-header 필드를 포함하여 자신의 인증 획득을 시
도할 수 있다. Authorization 필드 값은 요구하고 있는 자원의 영역에 대한 사용자 에이전트의
인증 획득 정보를 포함하고 있는 보증서(credentials)로 구성되어 있다.

[Page 100]


          Authorization  = "Authorization" ":" credentials

HTTP 접속 인증 획득은 11장에 기술되어 있다. 요구에 대한 인증을 획득하고 영역이 명시되
면 동일한 보증서는 해당 영역 내의 다른 요구에 대해서도 유효해야 한다.

공유된 캐시(13.절 참조)가 필드가 포함된 요구를 수신하면 캐시는 다음에 명시된 예외 사항
이외에는 다른 요구에 대한 대답으로서 해당 응답을 리턴해서는 절대 안 된다.

1.  응답이  "proxy-revalidate" Cache-Control 지시자를 포함하고 있지 않으면 캐시는 해당 응
답을 계속되는 요구에 대한 대답으로 사용할 수 있다. 그러나 프락시 캐시는 원서버가
새로운 요구를 인증할 수 있도록 새로운 요구의 request-header를 이용하여 반드시 먼저
새로운 요구를 재검증해야 한다.
2.  응답이  "proxy-revalidate" Cache-Control 지시자를 포함하고 있으면 캐시는 해당 응답을
계속되는 요구에 대한 대답으로 사용할 수 있다. 그러나 모든 캐시는 원서버가 모든 요
구를 인증할 수 있도록 새로운 요구의 request-header를 이용하여 반드시 먼저 새로운
요구를 재검증해야 한다.
3.  응답이 " public" Cache-Control 지시자를 포함하고 있으면 이를 계속되는 요구에 대한 대
답으로 리턴할 수 있다.

14.9 Cache-Control

Cache-Control general-header 필드는 Request/Response chain에 따라 모든 캐시 메커니즘이 반드
시 따라야 하는 지시자를 표시하는 데 사용한다. 지시자는 캐시가 요구나 응답을 바람직하지
못하게 방해하지 못하도록 하는 행태(behavior)를 명시한다. 이러한 지시자들은 대개 기본적인
캐시 알고리즘을 무시한다. 캐시 지시자 요구에 지시자가 존재한다는 것이 응답에도 동일한
지시자를 부여해야 한다는 것의 의미하지 않다는 의미에서 단 방향(unidirectional)이다.

HTTP/1.0 캐시는 Cache-Control을 구현하고 있지 않으면 Pragma: no-cache (14.32절 참조)만을
구현하고 있다는 것에 주의한다.

캐시 지시자는 Request/Response chain를 따라서 모든 수신측에게 적용할 수 있기 때문에 해당
애플리케이션에서 차지하는 중요도에 관계 없이 프락시나 게이트웨이 애플리케이션은 이 지시
자를 반드시 통과시켜야 한다. 특정한 캐시를 위한 cache-directive를 명시하는 것이 불가능하
지는 않다.

          Cache-Control    = "Cache-Control" ":" 1#cache-directive

          cache-directive   = cache-request-directive
                          |  cache-response-directive
[Page 101]


          cache-request-directive =
                           "no-cache" [ "=" <"> 1#field-name <"> ]
                          | "no-store"
                          | "max-age" "=" delta-seconds
                          | "max-stale" [ "=" delta-seconds ]
                          | "min-fresh" "=" delta-seconds
                          | "only-if-cached"
                          | cache-extension

          cache-response-directive =
                            "public"
                          | "private" [ "=" <"> 1#field-name <"> ]
                          | "no-cache" [ "=" <"> 1#field-name <"> ]
                          | "no-store"
                          | "no-transform"
                          | "must-revalidate"
                          | "proxy-revalidate"
                          | "max-age" "=" delta-seconds
                          | cache-extension

          cache-extension = token [ "=" ( token | quoted-string ) ]

지시자에 어떠한 1#field-name 파라미터도 없으면 그 지시자는 전체 요구 또는 응답에 적용된
다. 지시자에 1#field-name 파라미터가 있으면 그 지시자는 해당 필드 또는 필드들에게만 적용
되고 나머지 요구나 응답에는 적용되지 않는다. 이 메커니즘이 확장성을 지원한다. 향후 HTTP
규약의 구현은 HTTP/1.1에 정의되지 않은 헤더 필드에 이 지시자를 적용할 수도 있다.

Cache-control 지시자는 다음과 같은 일반적인 범주로 분류할 수 있다.

? 캐시할 수 있는 것에 대한 제한: 오직 원서버만이 제한을 둘 수 있다.
? 기본적인 유효일 메커니즘의 변경: 원서버 및 사용자 에이전트 모두가 부과할 수 있다.
? 캐시 검증이나 갱신에 대한 통제: 오직 원서버만이 통제할 수 있다.
? 엔터티의 변형에 대한 통제.
? 캐시 시스템에 대한 확장(extensions)

[Page 102]


14.9.1 무엇을 캐시할 수 있는가

기본적으로 요구 method의 요구사항, 요구 헤더 필드, 응답 상태가 캐시할 수 있다고 표시하
는 응답은 캐시할 수 있다. 13.4절은 캐시할 수 있는 기본값들에 대하여 요약해 놓았다. 다음
의 Cache-Control 응답 지시자는 원서버가 응답의 캐시 가능성을 무시할 수 있도록 한다.

public 
보통 비 공유 캐시 내에서만 캐시할 수 있거나 캐시할 수 없지만 어떤 캐시이든 응답을 캐
시할 수 있음(cachable)을 표시한다.(추가적인 정보는 14.8절의 Authorization 참조)

private
응답 메시지의 전체 혹은 일부분을 단일 사용자만이 사용하며 절대 공유 캐시(shared cache)
에 의해 캐시해서는 안됨을 표시한다. 원서버가 응답의 특정 부분이 단일 사용자만을 위한
것이며 다른 사용자의 요구에 대한 유효한 응답은 아니라는 것을 명시할 수 있도록 한다.
사적인(비 공유) 캐시는 응답을 캐시할 수도 있다.

주의 : 사적이라는 단어 사용의 의미는 응답을 캐시할 수 있는 부분만을 통제하는 것이며
메시지 내용에 대한 보호를 확보할 수는 없다.

no-cache
응답의 전체 혹은 부분을 반드시 캐시해야 함을 표시해야 한다. 원서버가 클라이언트 요구
에 낡은 응답(stale response)을 리턴하도록 설정된 캐시에 의해서도 캐시를 하지 못하도록 한
다.

주의 : 대부분의 HTTP/1.0 캐시는 이 지침을 인지하지 못하거나 따르지 않을 것이다.

14.9.2 캐시에 의해 무엇을 저장할 수 있는가

저장 금지(no-store) 지시자의 목적은 부주의하게 민감한 정보를 보유(예를 들어 백업 테이프
위에)하거나 배포하는 것을 방지하는 것이다. No-store 지시자는 전체 메시지에 적용되면 응답
및 요구 모두에 발송할 수 있다. 요구 내에 포함하여 발송했으면 캐시는 요구의 어떤 부분 또
는 이 요구에 대한 어떠한 응답도 캐시해서는 안 된다. 응답에 발송했으면 캐시는 이 응답의
어떤 부분 또는 응답을 이끌어 낸 요구를 저장해서는 안 된다. 이 지시자는 비 공유 및 공유
캐시에 모두 적용된다. 이 문장의 "저장해서는 안 된다"의 의미는 캐시가 의도적으로 고정 저
장 매체(non-volatile storage)에 정보를 저장해서는 안 되며 비 고정 저장 매체에서는 정보를 전
송한 후 최대한 빨리 정보를 삭제하도록 최선의 노력을 다해야 한다는 것이다.

[Page 103]


이 지시자가 응답과 관련 되었을 때도 사용자는 명백하게 이 응답을 캐시 시스템 외부에 저장
할 수 있다.(예를 들어 "Save As" 대화상자) 기록 버퍼는 이러한 응답을 일반적 작업의 일 부분
으로 저장할 수도 있다.

이 지시자의 목적은 특정 사용자의 명시된 필요 조건 및 캐시 데이터 구조체에 예상하지 못한
접속을 통한 우발적인 정보의 유출을 걱정하는 서비스 저작자의 필요 조건을 충족시키는 것이
다. 어떤 의미에서 이 지시자의 사용이 사생활 보호를 향상 시켜 줄 수 있지만 이것이 사생활
을 보호하는 신뢰하거나 충분한 메커니즘은 아니라는 점에 유의해야 한다. 특히 나쁜 의도를
가지거나 타협적인 캐시는 이 지시자를 인지하지 못하거나 복종하지 않을 수 있다. 또한 통신
네트워크는 정보 유출에 취약한 편이다.

14.9.3 기본적인 만기일 메커니즘의 변경

원서버는 Expires 헤더(14.21절 참조)를 이용하여 엔터티의 유효 시간을 명시한다.  대안으로
응답에 max-age 지시자를 사용하여 표시할 수도 있다.

응답에 Expires 및 max-age 지시자가 모두 포함되어 있으면 max-age 지시자가 Expires 헤더가
더 제한적이라 할지라도 이를 무시한다. 이 원칙은 원서버가 HTTP/1.0 캐시에 HTTP/1.1 캐시
(또는 이후 버전)보다 긴 유효시간을 응답에 부여할 수 있도록 한다. 어떠한 HTTP/1.0 캐시가
동시화되지 않은(desynchronized) 시계 때문에 부적절하게 경과 시간이나 유효 시간을 계산했을
때 유용하다.

주의 : 이 규격을 따르지 않는 대부분의 이전 캐시는 Cache-Control 지시자를 구현하지 않는
다. Cache-Control 지시자를 사용하기 원하지만 HTTP/1.1을 따른 캐시를 금지하는 않지만 제
한하는 원서버는 max-age 지시자가 Expires 헤더를 무시하며 HTTP/1.1을 따르지 않는 캐시
는 max-age 지시자를 준수하지 않는다는 사실을 이용할 수 있다.

다른 지시자는 사용자 에이전트가 기본적인 유효일 메커니즘을 변경할 수 있도록 한다. 이러
한 지시자는 요구에 명시할 수 있다.

   max-age
클라이언트가 초로 표시된 시간보다 크지 않은 경과 시간을 가진 응답을 기꺼이 접수한다는
것을 표시한다. Max-stale 지시자도 포함되어 있지 않으면 클라이언트는 낡은 응답을 접수할
의사가 없는 것이다.

   min-fresh
클라이언트가 신선한 기간이 초로 표시된 현재 의 경과 시간보다 크지 않은 응답을 기꺼이
접수한다는 것을 표시한다. 이는 클라이언트가 최소한 초로 표시된 기간 동안만은 신선한
응답을 원하는 것이다.

[Page 104]


   max-stale
클라이언트가 유효시간을 초과한 응답을 기꺼이 접수한다는 것을 표시한다. Max-stale에 값이
부여되었으면 클라이언트는 명시된 초를 초과하지 않는 응답을 기꺼이 접수한다. Max-stale에
값이 부여되지 않았으면 클라이언트는 모든 응답을 기꺼이 접수한다.

캐시가 요구의 max-stale지시자 응답의 유효 시간을 무시하도록 설정되어 낡은 응답을 리턴하
면 캐시는 반드시 Warning 10 (Response is stale)을 이용하여 Warning 헤더를 낡은 응답에 부착하
여야 한다.

14.9.4 캐시의 재검증 및 Reload 제어

때때로 사용자 에이전트는 캐시가 원서버에서 캐시를 재검증하거나 원서버에서 캐시 엔트리를
갱신할 것을(원서버로 향한 경로의 다음 캐시만이 아닌) 원하거나 고집할 수 있다. End-to-end
재검증은 캐시나 원서버가 캐시된 응답의 유효 시간을 과대 평가했을 때 필요할 수 있다. End-
to-end 갱신은 어떠한 이유 때문에 캐시 엔트리가 오염되었을 때 필요하다.

클라이언트가 자신의 지역 캐시 사본을 가지고 있지 않거나("명시되지 않은 end-to-end 재검증"
이라 부른다), 가지고 있을 때("명시된 end-to-end 재검증이라 부른다.)End-to-end 재검증을 요구
할 수 있다.

클라이언트는 Cache-Control 지시자를 사용하여 다음의 세 가지 처리를 명시할 수 있다.

   End-to-end reload
요구에 "no-cache" Cache-Control 지시자가 포함되어 있거나 HTTP/1.0클라이언트와의 호환성
유지를 위해 "Pragma: no-cache"를 포함하고 있다. 요청의 no-cache 지시자에는 아무런 필드
이름도 포함되지 않는다. 서버는 이러한 요구에 응답할 때 캐시된 사본을 사용해서는 안 된
다.

   Specific end-to-end revalidation
요구가 원서버로 향한 경로를 따라 각각의 캐시가 자신의 엔트리를 다음 캐시나 원 서버와
재검증하도록 강요하는 "max-age=0" Cache-Control 지시자를 포함하고 있다. 첫 요구는 클라
이언트의 현재 검증자와 더불어 캐시-검증 조건을 포함하고 있다.

[Page 105]


   Unspecified end-to-end revalidation
요구가 원서버로 향한 경로를 따라 각각의 캐시가 자신의 엔트리를 다음 캐시나 원 서버와
재검증하도록 강요하는 "max-age=0" Cache-Control 지시자를 포함하고 있다. 첫 요구는 클라
이언트의 현재 검증자와 더불어 캐시-검증 조건을 포함하고 있지 않다. 해당 자원의 캐시 엔
트리를 가지고 있는 경로의 첫 캐시가 현재 검증자와 더불어 캐시-검증 조건을 포함하고 있

Max-age=0 지시자 때문에 가장 가까운 캐시가 자신의 캐시 엔트리를 재검증하도록 강요 받
았을 때 클라이언트는 요구에 자신의 검증자를 제공하며 제공된 검증자는 캐시 엔트리에 현
재 저장된 검증자와 상이할 수 있다. 이 경우 캐시는 의미 투명성에 영향을 미치지 않고 자
신의 요구를 만드는 데 두 검증자 모두를 사용할 수 있다.

그러나 검증자의 선택이 성능에 영향을 미칠 수 있다. 최상의 접근법은 가장 가까운 캐시가
요구를 만들 때 자기 자신의 검증자를 사용하는 것이다. 서버는 304 (Not Modified)로 응답하
고 캐시는 새롭게 검증된 사본을 클라이언트에게 200 (OK) 응답과 함께 되돌려 주어야 한다.
서버가 새로운 엔터티나 캐시 검증자로 응답해도 가장 가까운 캐시는 강한 비교 기능(strong
comparison function)을 이용하여 클라이언트의 요구가 제공하는 검증자와 리턴 된 검증자를
비교해야 한다. 클라이언트 검증자가 원서버의 검증자와 동등할 때는 가장 가까운 캐시는
304 (Not Modified)를 리턴한다. 그렇지 않으면 200 (OK) 응답으로 새로운 엔터티를 리턴한다.

요구에 no-cache 지시자가 포함되어 있으면 요구는 min-fresh, max-stale, 또는 max-age를 포함
해서는 안 된다.

네트워크 연결이 극도로 약할 때와 같은 경우에 클라이언트는 원서버와 갱신하거나 재검증
하는 것이 아닌 현재 저장하고 있는 응답만을 리턴하기 위해 캐시를 원할 수 있다. 이를 위
해서 클라이언트는 요구에 only-if-cached 지시자를 포함할 수 있다. 클라이언트가 이 지시자
를 수신하면 캐시는 다른 응답의 제한 사항과 일치하는 캐시 엔트리를 사용하여 응답하던지
504 (Gateway Timeout) 상태로 응답할 수 있다. 그러나 캐시의 그룹을 안정된 내부 연결로 통
합된 시스템에 사용할 때 이러한 요구는 해당 캐시 그룹 내에서 전달될 수 있다.

캐시가 서버에서 명시된 유효 시간을 무시하도록 설정될 수 있기 때문에 또한 클라이언트
요구가 max-stale 지시자를 포함할 수 있기 때문에(유사한 영향을 미친다) 규약은 원서버가
계속되는 캐시 사용에 대한 캐시 엔트리 검증을 요구할 수 있는 메커니즘을 포함하고 있다.

[Page 106]


Must-revalidate 지시자가 캐시가 수신한 응답에 포함되어 있고 캐시가 계속되는 요구에 응답하
기는 낡아진 이후에 캐시는 먼저 원서버에 이를 재검증하기 전에는 엔트리를 사용해서는 안
된다. (예를 들어 캐시는 전적으로 원서버의 Expires 또는 max-age 값에 기초하여 캐시된 응답
이 낡았으면 매번 end-to-end 검증을 실행해야 한다.)

Must-revalidate 지시자는 특정 규약 기능의 안정된 운영을 위해서 필요하다. 어떠한 경우이든
HTTP/1.1 캐시는 must-revalidate 지시자를 반드시 따라야 한다. 특히 캐시가 어떠한 이유이든
원서버에 도달할 수 없을 때는 반드시  504 (Gateway Timeout) 응답을 생성해야 한다.

서버는 아무런 표시 없이 실행되지 않은 재무 트랜잭션의 경우처럼 엔터티에 대한 재검증이
실패하여 부정확한 운영을 초래할 경우 반드시 must-revalidate 지시자를 발송해야 한다. 수신측
은 결코 이 지시자를 위반하는 어떠한 자동화된 처리 방식을 갖고 있어서는 안 되며 재검증이
실패할 경우 자동적으로 검증되지 않은 엔터티 사본을 제공해서는 안 된다.

권하지는 않지만 극도로 악화된 연결 상태를 이용하는 사용자 에이전트는 이 지시자를 위반할
수는 있으나 사용자에게 반드시 검증되지 않은 응답을 제공했음을 명백하게 경고해야 한다.
경고는 검증되지 않는 접속 각각에 제공해야 하며 명백한 사용자 정보를 제공해야 한다.

Proxy-revalidate 지시자는 비 공유 사용자 에이전트 캐시에는 적용되지 않는다는 점을 제외하
고는 must-validate 지시자와 동일한 의미를 갖고 있다. 사용자의 캐시가 응답을 저장하고 나중
에 그것을 검증할 필요 없이 리턴할 수 있도록(그 사용자가 먼저 인증을 받았기 때문에) 하면
서도 프락시에게 많은 사용자가 재검증하도록 요구하여(각 사용자가 인증되었음을 확실하게
하기 위해) 인증되지 않은 요구에 대한 응답으로 사용할 수 있다.

14.9.5 비 변경 지시어(No-Transform Directive)

가장 가까운 캐시의 구현자(프락시)는 특정 엔터티 본문의 media type을 변환하는 것이 유용함
을 발견할 수 있다. 예를 들어 프락시는 캐시 공간을 절약하거나 느린 링크 상의 트래픽 양을
줄이기 위해 이미지의 포맷을 변환할 수 있다. HTTP는 오늘날까지 이러한 변환
(transformations)에 대해서는 침묵을 지키고 있다.

[Page 107]


벌써 이러한 변환을 특정 종류의 애플리케이션에 사용할 엔터티 본문에 적용했을 때 심각한
운영 문제가 발생하였다. 예를 들어 의료 이미지 처리, 과학적 자료 분석 및 end-to-end 인증에
사용되는 애플리케이션은 모두 원서버의 entity-body와 비트 단위까지 동일한 엔터티 본문을
수신하는 방식에 의존하고 있다.

따라서 응답이 no-transform 지시자를 포함하고 있으면 가장 가까운 캐시나 프락시는 13.5.2 절
에 열거된 이러한 헤더들은 no-transform 지시자에 종속적이기 때문에 이들을 절대로 변경해서
는 안 된다. 이것은 캐시 또는 프락시는 이러한 헤더가 명시한 어떠한 측면의 entity-body도
변경하지 말아야 한다는 것을 의미한다.

14.9.6 캐시 제어 확장

Cache-Control 헤더 필드는 하나 또는 그 이상의 cache-extension 토큰을 이용하여 각각 선택적
으로 부여된 값을 가지고 확장할 수 있다. 정보 확장(Informational extensions - 캐시 행태에 변
화를 요구하지 않는)은 다른 지시자의 의미를 변화시키지 않고도 추가할 수 있다. 행태 확장
(behavioral extensions)은 캐시 지시자의 기본 베이스에 대한 변경자의 역할을 수행하도록 디자
인되었다. 새로운 지시자 및 표준 지시자 모두가 제공되어 새로운 지시자를 이해하지 못하는
애플리케이션은 표준 지시자가 명시한 행태에 기본적으로 따르며 새로운 지시자를 이해하는
애플리케이션은 이를 표준 지시자와 관련된 필요 조건의 변경으로 인식한다. 이러한 방식으로
지시자를 기본 규약에 대한 변경을 요구하지 않고도 확장할 수 있다.

확장 메커니즘은 원초 HTTP 버전에 정의된 모든 지시자와 특정 확장에는 따르지만 이해할 수
없는 모든 지시자를 무시하는 HTTP 캐시에 달려 있다.

예를 들어 "private" 지시자의 변경자 역할을 수행하는 "community"로 불리는 가설의 새로운 응
답 지시자를 가정하자. 우리는 새로운 지시자를 모든 비 공유 캐시에 대한 추가로 값 내에 이
름이 등록된 공동체 구성원만이 공유하는 응답에 대한 캐시를 의미하는 것으로 규정한다.
"UCI" community를 공유된 캐시의 private 응답에 사용하길 원하는 원서버는 다음을 포함하여
이를 수행할 수 있다.

          Cache-Control: private, community="UCI"

이 헤더 필드를 만난 캐시는 캐시가 "community" cache-extension을 이해할 수 없더라도 "private"
지시자를 보고 이해할 수 있어 안전한 행태의 기본 행태로 전환할 수 있기 때문에 정확하게 작동
한다.

[Page 108]


인지할 수 없는 cache-directive는 무시해야 한다. HTTP/1.1캐시가 인지하지 못하는 모든 cache-
directive는 캐시가 확장을 이해하지 못하더라도 최소한도로 이러한 캐시 행태가 정확한 것으
로 유지되도록 표준 지시자(또는 응답의 기본 캐시 가능성(chchability))와 결합되어 있다고 가
정한다.

14.10 Connection

Connection 일반 헤더 필드는 발송측이 특정 연결이 원하는 선택 사항을 명시하는 데 사용
하며 추가적인 연결 시 프락시를 통하여 통신해서는 절대 안 된다.

Connection 헤더는 다음과 같은 문법을 가지고 있다.

Connection-header  = "Connection" ":" 1#(connection-token)
connection-token   = token

HTTP/1.1 프락시는 메시지가 전송되기 전에 Connection 헤더를 반드시 분석하여야 하며 이
필드의 각각의 connection-token에 대해 connection-token과 동일한 이름을 가진 메
시지에서 모든 헤더 필드를 삭제해야 한다. Connection 선택 사항은 해당 연결 선택 사항과
관련된 파라미터가 없으면 추가적인 헤더 필드가 발송되지 않기 때문에 관련 추가 헤더 필드
가 아닌 Connection 헤더 필드에 connection-token의 존재로 알 수 있다. HTTP/1.1 은
"close" 연결 선택 사항을 송신측이 응답을 완전히 받은 후에 연결이 종료된다는 것을 표시
하는 데 사용한다. 예를 들어,

Connection: close

위와 같이 close 옵션이 요구나 응답 헤더 필드에 있으면 연결이 현재 의 요구/응답에 완성된
후에 'persistent' (8.1 절)로 간주되어서는 안 된다는 것을 표시한다.

persistent 연결을 지원하지 않는 HTTP/1.1 응용은 반드시 모든 메시지에 "close" 연결 선택
사항을 포함하고 있어야 한다.

14.11 Content-Base

Content-Base 엔터티 헤더 필드는 엔터티 내의 상대 URL을 찾아내는 데 사용한다. 이 헤
더 필드는 RFC 1808에 Base로서 기술되어 있으며 곧 개정될 것이다.

Content-Base       = "Content-Base" ":" absoluteURI

Content-Base 필드가 없으면 엔터티의 기본 URI는 Content-Location (Content-
Location URI 가 절대 URI이면) 또는 요구를 시작하는 데 사용한 URI에 의하여 동일한 우
선 순위로 규정된다.

[Page 109]


그러나 entity-body 내 내용의 기본 URI는 해당 entity-body 내에서 재규정될 수 있다는 점에
주의한다.

14.12 Content-Encoding

Content-Encoding entity-header 필드는 entity-body에 대한 변경자로 사용한다. 이것이 있으면 그
값은 entity-body에 어떠한 추가 Content coding이 적용되었는지 표시하여 Content-Type 헤더 필
드가 참조하는 media-type을 얻기 위하여 어떠한 디코딩 메커니즘을 적용해야 하는지 표시한
다. Content-Encoding은 주로 문서를 기저의 media type의 정체(identity)를 상실하지 않고도 압축
할 수 있도록 하는 데 사용한다.

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

Content 코딩은 3.5절에 규정되어 있다. 이의 사용 예는,

          Content-Encoding: gzip

Content-Encoding은 Request-URI가 식별하는 엔터티의 특징이다. 전형적으로 entity-body는 이
인코딩에 저장되며 표시 또는 유추 목적으로 사용하기 전에만 해독할 수 있다.

엔터티에 복수의 인코딩을 적용했으면 내용 코딩은 적용된 순서로 열거해야 한다.

인코딩 파라미터에 관한 추가 정보는 이 규격에서 규정하지 않은 entity-header 필드에서 제공
한다.

14.13 Content-Language

Content-Language entity-header 필드는 포함하고 있는 엔터티 대상 청중자의 자연적인 언어를 기
술하고 있다. Entity-body내에서 사용된 모든 언어와 동등하지 않을 수도 있다는 점에 주의 한
다.

          Content-Language  = "Content-Language" ":" 1#language-tag

Language 태그는 3.10절에 정의되어 있다. Content-Language의 주된 목적은 사용자가 사용자
자신이 선호하는 언어에 따라 엔터티를 식별하거나 구별할 수 있도록 하는 것이다. 따라서 본
문 내용이 덴마크어를 이해할 수 있는 청중을 위한 것이라면 적절한 필드는 다음과 같다.

          Content-Language: da

[Page 110]


Content-Language가 명시되어 있지 않으면 기본은 내용이 모든 언어의 청중을 위한 것이다. 이
는 송신측이 이것이 특정 자연적 언어에 한정적인 것이 아니거나 사용하고 하는 언어를 알 수
없다는 것을 의미한다.

복수 언어는 복수의 청중을 위한 내용을 열거할 수 있다. 예를 들어 "Treaty of Waitangi,"의 번
역을 마오리(Maori)어 버전 및 영어 버전으로 번역하려면,

          Content-Language: mi, en

그러나 엔터티에 복수의 언어가 존재한다는 것이 여러 언어를 사용할 수 있는 청중을 위한 것
을 의미하는 것은 아니다. 이의 예는 "A First Lesson in Latin" 과 같은 초급자 언어 입문서이다.
이는 분명히 영어를 사용하는 청중을 위한 것이다. 이 경우 Content-Language는 "en"만을 포함
해야 한다.

Content-Language는 모든 media type에 적용할 수 있고 텍스트 문서에 한정된 것은 아니다.

14.14 Content-Length

Content-Length entity-header 필드는 message-body의 크기를 수신측에 발송된 octets의 십진수,
HEAD method의 경우에는 요구가 GET이었을 경우 발송되었을 entity-body의 크기를 표시한다.

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

예는,

          Content-Length: 3495

애플리케이션은 엔터티의 media type에 관계 없이 이 필드를 전송하는 message-body의 크기를
표시하는 데 사용한다. 수신측이 신뢰성 있게 entity-body를 포함하고 있는HTTP/1.1 요구의 종
료를 결정할 수 있어야 한다. 예를 들어 요구가 유효한 Content-Length 필드를 가지고 Transfer-
Encoding:chunked 또는multipart body를 사용할 수 있기 때문이다.

제로보다 크거나 동등한 모든 Content-Length는 유효한 값이다. 4.4절은 Content-Length가 주어
지지 않았을 때 message-body의 길이를 결정하는 방법을 기술하고 있다.

[Page 111]


주의 : 이 필드의 의미는 해당되는 "message/external-body" content-type에서 사용되는 선택 필
드인 MIME 규정과는 상당히 다르다. HTTP에서 메시지의 길이를 전송하기 전에 결정할 수
있으면 언제나 이 필드를 발송해야 한다.

14.15 Content-Location

Content-Location entity-header 필드는 메시지에 포함된 엔터티의 자원 위치를 제공하는 데 사용
한다. 자원이 자신과 관련된 복수의 엔터티를 가지고 있고 각 엔터티가 사실상 개별적으로 접
근하였을 때 구별된 위치를 가지고 있는 경우에는 서버는 리턴되는 특정 변형자(variant)에 대
한 Content-Location을 제공해야 한다. 또한 서버는 응답 엔터티에 상응하는 자원의 Content-
Location를 제공해야 한다.

          Content-Location  = "Content-Location" ":"
                             ( absoluteURI | relativeURI )

Content-Base 헤더 필드가 없으면 Content-Location 의 값은 엔터티의 URL을 규정한다.(14.11절
참조)

Content-Location 값은 원래 요청된 URI의 대체물이 아니다. 이것은 요구를 방송한 시점의 특
정 엔터티에 상응하는 자원의 위치를 표현하는 것일 뿐이다. 이후의 요구는 해당 특정 엔터티
의 자원을 식별하는 것이 목적이라면 Content-Location URI를 사용할 수 있다.

캐시는 Content-Location을 조회하는 데 사용되는 URI와 다른 Content-Location을 가진 엔터티
를 해당 Content-Location URI의 추후 요구에 대한 응답에 사용할 수 있다고 가정해서는 안 된
다. 그러나 Content-Location은 13.6절에서 기술한 대로 단일 요청 자원에서 조회한 복수의 엔
터티를 차별화하는 데 사용할 수 있다.

Content-Location이 상대적인 URI이면 응답에서 제공하는 어떠한 Content-Location URI에 상대
적인 것으로 해석해야 한다. 아무런 Content-Base도 제공되지 않았으면 상대적인 URI은
Request-URI에 상대적인 것으로 해석해야 한다.

[Page 112]


14.16 Content-MD5

RFC 1864 [23]에 규정된 바와 같이 entity-body의 end-to-end 메시지 무결성을(end-to-end message
integrity check (MIC)) 점검하기 위한 Content-MD5 entity-header 필드는 entity-body의 MD5 digest
이다.(주의: MIC는 전송되는 도중의 entity-body에 대한 우발적인 변경을 탐지하는 데 유용하
지만 악의적인 공격에 대한 증명은 아니다.)

           Content-MD5   = "Content-MD5" ":" md5-digest

           md5-digest   =

Content-MD5 헤더 필드는 원서버가 entity-body의 무결성을 확인하는 기능으로서 생성할 수 있
다. 원서버만이 Content-MD5 헤더 필드를 생성할 수 있으며 프락시나 게이트웨이는 그 값을
end-to-end  무결성 점검으로 사용하지 못하도록 변질시킬 수 있기 때문에 절대도 이것을 생산
하면 안 된다. 프락시나 게이트웨이를 포함한 어떠한 entity-body의 수신측도 이 헤더 필드의
digest value가 수신된 entity-body의 digest value와 일치하는지 점검할 수 있다.

MD5 digest는 적용된 모든 Content-Encoding을 포함하지만 message-body에 적용되었을 수 있
는 모든 Transfer-Encoding은 포함하지 않는 entity-body의 내용에 기초하여 산출할 수 있다. 수
신된 메시지에 Transfer-Encoding이 포함되어 있으면 해당 인코딩은 수신된 엔터티에 대한
Content-MD5값을 점검하기 이전에 삭제하여야 한다.

이것은 digest가 Transfer-Encoding을 적용하지 않고 발송했을 때의 entity-body와 정확하게 동
일한 entity-body의 octets에서 산출되는 결과를 초래한다.

HTTP는 RFC 1864를 확장하여 digest가 MIME 복합 media-type (예를 들어  multipart/* 및
message/rfc822)에서 산출될 수 있도록 허용한다. 그러나 이것이 이전 문장에서 규정한 digest
산출 방법을 변경하지는 않는다.

주의 : 이것은 몇몇 결과를 초래한다. 복합 유형의 entity-Body는 자신의 MIME 및 HTTP 헤
더에 복수의 body-parts를 가질 수 있다.( Content-MD5, Content-Transfer-Encoding 및 Content-
Encoding 헤더 포함) 만약 body-part 가 Content-Transfer-Encoding 또는 Content-Encoding 헤더
를 가지고 있으면 body-part의 내용이 인코딩되었고 body-part가 현재 처럼(예를 들어 적용
이후) Content-MD5 digest에 포함되어 있다고 가정할 수 있다.

주의 : Content-MD5 규정이 RFC 1864의 MIME entity-bodies에서와 규정과 동일하기는 하지만
Content-MD5를 HTTP entity-bodies에 적용하는 것이 MIME entity-bodies에 적용하는 것과 다
를 수 있는 몇 가지 경우가 있다.
[Page 113]


그 중의 하나가 MIME과는 달리 HTTP는 Content-Transfer-Encoding을 사용하지 않지만
Transfer-Encoding 및 Content-Encoding 을 사용한다는 것이다. 다른 것은 HTTP가 MIME보다
더 자주 이진 내용 유형을 사용하기 때문에 digest를 산출하는 데 사용된 바이트 순서는 해
당 유형에 정의된 전송 바이트 순서라는 점에 주의할 필요가 있다. 마지막으로 HTTP가
CRLF로 정규화된 폼뿐만 아니라 어떠한 복수 라인 줄바꿈 관례에 따른 텍스트 유형이든
전송을 허용한다는 것이다. 실제로 전송된 텍스트에 사용된 줄바꿈(line break) 관례는 digest
를 산출할 때 변경하지 말아야 한다.

14.17 Content-Range

Content-Range entity-header는 부분적 entity-body와 함께 전송하여 전체 entity-body 의 어느 부
분에 부분적 본문을 삽입해야 하는 가를 명시한다. 또한 이것은 전체 entity-body의 크기를 표
시하기도 한다. 서버가 클라이언트에게 부분적 응답을 리턴했을 때 서버는 응답이 차지하는
영역의 범위 및 전체 entity-body의 길이를 기술해야 한다.

          Content-Range = "Content-Range" ":" content-range-spec

          content-range-spec       = byte-content-range-spec

          byte-content-range-spec   = bytes-unit SP first-byte-pos "-"
                                    last-byte-pos "/" entity-length

          entity-length            = 1*DIGIT

Byte-ranges-specifier 값과는 달이 byte-content-range-spec은 하나의 영역만을 명시할 수 있으며
영역의 처음 및 마지막 바이트의 절대 위치를 포함하고 있어야 한다.

Byte-content-range-spec whose Last-byte-pos 값이 first-byte-pos 값보다 적은 byte-content-range-spec
이나 entity-length 값이 last-byte-pos 값보다 적거나 동등한 것은 무효이다. 유효하지 않은 byte-
content-range-spec의 수신측은 이것과 이에 따라 전송되는 모든 내용을 반드시 무시해야 한다.

[Page 114]


엔터티가 전체 1234 바이트를 포함하고 있다고 가정하면 byte-content-range-spec 값의 예는 다
음과 같다.

? The first 500 bytes:

          bytes 0-499/1234

? The second 500 bytes:

          bytes 500-999/1234

? All except for the first 500 bytes:

          bytes 500-1233/1234

? The last 500 bytes:

          bytes 734-1233/1234

HTTP 메시지가 단일 영역의 내용을 포함하고 있을 때 이 내용은 Content-Range 헤더 및 실제
적으로 전송되는 바이트 수를 표시하는 Content-Length 헤더와 함께 전송된다. 예를 들면,

          HTTP/1.1 206 Partial content
          Date: Wed, 15 Nov 1995 06:25:24 GMT
          Last-modified: Wed, 15 Nov 1995 04:58:08 GMT
          Content-Range: bytes 21010-47021/47022
          Content-Length: 26012
          Content-Type: image/gif

HTTP 메시지가 복수 영역의 내용을 포함하고 있을 때(예를 들어 복수의 중첩되지 않는 영역
에 걸친 요구에 대한 응답) 이 영역들은 multipart MIME 메시지로서 전달된다. 이 목적에 사용
된 multipart MIME content-type 은 이 규격에서"multipart/byteranges"로 규정하고 있다. 규정에 관
하여는 부록 19.2절을 참조한다.

MIME multipart/byteranges 메시지를 해독할 수 없는 클라이언트는 단일 요구의 복수 byte-ranges
를 요청해야 한다.

클라이언트가 단일 요구에 복수의 byte-ranges를 요청하면 서버는 요구에 나타난 순서 대로 이
것들을 되돌려 주어야 한다.

[Page 115]


서버가 byte-range-spec이 무효이기 때문에 무시했으면 서버는 요구를 유효하지 않은 Range 헤
더 필드가 존재하지 않는 것처럼 처리해야 한다.(대개의 경우 이것은 전체 엔터티를 포함하고
있는 200 메시지를 리턴함을 의미한다.) 이유는 클라이언트가 이러한 무효 요구를 하는 유일
한 시간은 엔터티가 이전 유구에 의해 수신된 엔터티보다 작을 때이기 때문이다.

14.18 Content-Type

Content-Type entity-header 필드는 수신측에 발송한 entity-body의 media type을 표시하거나, 요구
가 GET이었으면 발송되었을 media type를 표시한다.

          Content-Type   = "Content-Type" ":" media-type
Media types은 3.7장에 규정되어 있으며 이 필드의 사용 예는 다음과 같다.

          Content-Type: text/html; charset=ISO-8859-4

엔터티의 media type을 식별하는 method에 관한 토의는 7.2.1절에 기술되어 있다.

14.19 Date

Date general-header 필드는 메시지가 생성되었을 때의 날짜와 시간을 표시하며 RFC 822의 org-
date와 동일한 의미를 가진다. 필드 값은 3.3.1절에 기술된 것처럼 HTTP-date이다.

          Date  = "Date" ":" HTTP-date

이의 사용 예는,

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

사용자 에이전트(요구의 경우)나 원서버(응답의 경우)와 직접적인 접속을 통하여 메시지를 수
신하면 날짜는 수신측 끝의 현재 시간인 것으로 가정한다. 그러나 날짜가 캐시 응답을 평가하
는 데 중요하기 때문에(원서버가 그렇다고 믿기 때문에) 원서버는 모든 응답에 Date 헤더 필
드를 반드시 포함해야 한다. 클라이언트는 PUT 및 POST 요청의 경우처럼 entity-body를 포함
하고 있는 메시지의 Date 헤더 필드만을 발송해야 하기는 하지만 선택 사항이기도 하다. Date
헤더 필드를 가지고 있지 않은 수신 메시지는 수신측이 메시지를 캐시하거나 Date를 요구하
는 규약을 이용한 게이트웨이를 통과할 때 수신측이 하나를 지정해야 한다.

[Page 116]


이론상으로 날짜는 엔터티가 생성되지 바로 직전 순간을 표시해야 한다. 그러나 실제상으로
날짜는 의미 값에 영향을 미치지 않고 메시지 원문을 생성하는 동안 아무 시간에서나 생성될
수 있다.

Date의 포맷은 3.3절의 HTTP-date 가 규정하는 절대 날짜 및 시간이다. 반드시 RFC1123 [8]-날
짜 포맷으로 발송해야 한다.

14.20 ETag

ETag entity-header 필드는 관련된 엔터티의 엔터티 태그를 정의한다. 엔터티 태그와 함께 사용
하는 헤더는 14.20, 14.25, 14.26 및 14.43 절에 기술되어 있다. 엔터티 태그는 동일한 자원
(13.3.2절 참조)의 다른 엔터티와 비교하는 데도 사용할 수 있다.

         ETag = "ETag" ":" entity-tag

예:

         ETag: "xyzzy"
         ETag: W/"xyzzy"
         ETag: ""

14.21 Expires


Expires entity-header 필드는 그 시간 이후 응답이 낡았다고 간주해야 하는 날짜/날짜를 제공한
다. 캐시(프락시 캐시 또는 사용자 에이전트 캐시)는 대개 먼저 원서버(또는 엔터티의 신선한
복사본을 가지고 있는 가장 가까운 캐시)가 검증하지 않는 한 낡은 캐시 엔트리를 리턴하지
않는다. 유효일 모델에 관한 추가 논의는 13.2절을 참조한다.

Expires 필드가 존재한다는 것이 그 시간 이전 또는 이후에 원래의 자원이 변경되거나 사라진
다는 것을 의미하지는 않는다.

포맷은 3.3절에서 정의한 HTTP-date 절대 날짜와 시간이다. 반드시 RFC1123-date 포맷이어야
한다.

         Expires = "Expires" ":" HTTP-date

[Page 117]


이의 사용 예는 다음과 같다.

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

주의 : 응답이 max-age 지시자를 포함한 Cache-Control 필드를 포함하고 있으면 그 지시자는
Expires 필드를 무시한다.

HTTP/1.1 클라이언트와 캐시는 반드시 다른 유효하지 않는 날짜 포맷을, 특히 "0" 값을 포함
하고 있는 날짜 포맷을 지나간 날짜로 취급해야 한다.(예를 들면 "벌써 만료된"으로)

응답을 "벌써 만료된" 것으로 표시하기 위해서 원서버는 Expires 날짜를 Date 헤더 필드와 동
일한 것으로 사용해야 한다.(13.2.4절의 유효일 계산 원칙을 참조)

응답을 "결코 만료되지 않는" 것으로 표시하기 위해서 원서버는 Expires 날짜를 대략 응답이
발송된 후 시점부터 1 년 후를 지정한다. HTTP/1.1 서버는 향후 1년 이상 된 Expires 날짜를
발송하지 말아야 한다.

기본적으로 캐시할 수 없는 응답에 미래의 특정 시간의 시간 값과 함께 Expires 헤더 필드가
존재하면 Cache-Control 헤더 필드가(14.9절 참조) 다른 식으로 표시하지 않는 한 응답을 캐시
할 수 있다는 것을 표시한다.

14.22 From

From request-header 필드는, 존재한다면, 요청 사용자 에이전트를 통제하는 인간 사용자의 인터
넷 전자우편 주소를 포함하고 있어야 한다. 주소는 RFC 822의 우편함 (as updated by RFC 1123
에 의하여 갱신된 것처럼)이 규정한 것처럼 기계가 사용할 수 있는 것이어야 한다.

          From   = "From" ":" mailbox

사용 예는,

          From: webmaster@w3.org

이 헤더 필드는 로깅(logging) 목적이나 무효이거나 원하지 않는 요구의 출처를 확인하는 수단
으로 사용할 수 있다. 접속 금지의 불확실한 폼으로 사용해서는 안 된다. 이 필드는 요구가 주
어진 사람(수행된 method에 대한 책임을 지는 사람)을 대신하여 수행되고 있는 것으로 해석한
다. 특히 로봇 에이전트는 이 헤더를 포함하여 수신측 끝에서 문제가 발생하였을 때 로봇을
운영하는 책임을 진 사람과 연락할 수 있도록 해야 한다.

[Page 118]


이 필드의 인터넷 전자우편 주소는 요구를 발송한 인터넷 호스트와 구별될 수 있다. 예를 들
어 요구가 프락시를 통과할 경우 원서버의 주소를 사용할 수 있다.

주의: 클라이언트는 사용자의 동의 없이는 그것이 사용자의 사생활 보호나 사이트의 보안
정책과 충돌할 수 있기 때문에 From 헤더 필드를 발송해서는 안 된다. 사용자는 요구를 발
송하기 전 어떤 시점에라도 이 필드의 값을 무력화, 활성화 및 변경할 수 있도록 할 것을
강력히 추천한다.

14.23 Host

Host request-header 필드는 사용자나 참조하고자 하는 자원(보통 3.2.2 절에 기술한 HTTP
URL)이 부여한 원래의 URL에서 얻은 대로 요구 받고 있는 자원의 인터넷 호스트와 포트
숫자를 명시한다. Host 필드 값은 반드시 원서버나 원래의 URL이 부여한 게이트웨이 네트워
크 위치를 표시해야 한다. 이것은 원서버나 게이트웨이가 단일 IP 주소의 복수 호스트 이름
에 사용되는 호스트의 루트 "/" URL과 같이 내부적으로 모호한 URL을 구별할 수 있도록
한다.

          Host = "Host" ":" host [ ":" port ]    ; 섹션3.2.2

뒤 따르는 포트 정보가 없는 "호스트"는 요구된 서비스의 기본 포트를 의미한다.(HTTP URL
의 "80"). 예를 들어 원서버의 <http://www.w3.org/pub/WWW/>에 대한 요청은 반드시 다음을
포함해야 한다.

          GET /pub/WWW/ HTTP/1.1
          Host: www.w3.org

클라이언트는 인터넷 상의 모든 HTTP/1.1 요구 메시지에 Host 헤더 필드를 반드시 포함해야
한다. 기존에 Host 필드가 존재하지 않으면 HTTP/1.1 프락시는 요구를 인터넷 상에서 전송
하기 전에 요구 메시지에 Host 필드를 반드시 추가해야 한다. 인터넷을 기반을 둔 모든
HTTP/1.1 서버는 Host 헤더 필드가 없는 모든 HTTP/1.1 요구 메시지에 대하여 400 상태 코
드로 반드시 응답해야 한다.

Host와 관련된 다른 필요 조건 사항에 대해서는 5.2 및 19.5.1 절을 참조한다.

14.24 If-Modified-Since

If-Modified-Since request-header 필드는 GET method와 함께 사용하여 GET method를 조건적으
로 만든다. 요구된 변형자가 이 필드에 명시된 시간 이후에 변경되지 않았으면 엔터티는 서
버로부터 리턴 되지 않는다. 대신 304 (not modified) 응답이 message-body없이 리턴 될 것이
다.

[Page 119]


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

이 필드의 사용 예는,

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

If-Modified-Since 헤더는 있지만 Range 헤더가 없는 GET method는 식별된 엔터티가 If-
Modified-Since 헤더에 표시된 날짜 이후로 변경되었을 때만 전송되도록 요구한다. 이것을 결정
하는 알고리즘은 다음 경우의 수를 포함한다,

a)  요청이 보통 200(OK) 상태 이외의 것을 산출하거나 전달된 If-Modified-Since 날짜가 무효
이면 응답은 일반적인 GET와 완전히 동일하다. 서버의 현재 시간보다 이후인 날짜는 유
효하지 않다.

b)  변형자가 If-Modified-Since 날짜 이후에 변경되었으면 응답은 일반적인 GET와 완전히 동
일하다.

c)  변형자가 유효한 If-Modified-Since 날짜 이후 변경되지 않았으면 서버는 반드시 304 (Not
Modified) 응답을 리턴해야 한다.

이 기능의 목적은 트랜잭션 오버헤드(transaction overhead)를 최소화하면서 캐시된 정보를 효과
적으로 갱신할 수 있도록 하는 것이다.

Range request-header 필드는 If-Modified-Since의 의미를 변경한다는 점에 주의한다. 전체적인
내용은14.36절을 참조한다.

클라이언트와 동시화되지 않은 시계를 가진 서버가 If-Modified-Since 시간을 해석할 수 있음
을 주의해야 한다.

클라이언트가 동일한 요구에서 If-Modified-Since 헤더를 가져 오는 대신 If-Modified-Since 헤더
에 자의적인 날짜를 사용하였으면 클라이언트는 이 날짜가 서버의 시간 해석 방식에 의해 해
석된다는 사실을 인지해야만 한다는 것에 주의해야 한다. 클라이언트는 동시화되지 않는 시계
및 클라이언트와 서버의 사이의 각기 다른 시간 인코딩으로 인한 반올림을 고려해야 한다. 이
것은 처음 요구한 시간과 계속되는 요구의 If-Modified-Since 날짜 사이에서 문서가 변경되었을
경우 경쟁 상황(race conditions)이 발생할 가능성 및 If-Modified-Since 날짜를 클라이언트의 시계
에서 서버 시계와 연결 없이 추출하였을 경우 틀린 시계와 관련된(clock-skew-related) 문제가
발생할 가능성을 모두 포함한다. 클라이언트와 서버 사이의 틀린 시간의 교정은 기껏해야 네
트웍의 잠복기(network latency) 때문에 근사치일 뿐이다.

[Page 120]


14.25 If-Match

If-Match request-header 필드는 method와 함께 사용하여 method를 조건적으로 만든다. 이전에
자원에서 획득한 하나 또는 그 이상의 엔터티를 가진 클라이언트는 연관된 엔터티 태그의 목
록을 If-Match 헤더 필드에 포함하여 이러한 엔터티 중의 하나가 현재의 것임을 증명할 수 있
다. 이 기능의 목적은 트랜잭션 오버헤드(transaction overhead)를 최소화하면서 캐시된 정보를
효과적으로 갱신할 수 있도록 하는 것이다. 또한 요구를 갱신할 때 자원의 잘못된 버전에 대
한 부주의한 변경을 방지하는 데 사용할 수 있다. 특별한 경우로 "*" 값은 자원의 모든 현재
엔터티와 일치한다.

          If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

해당 자원에 유사한GET 요구(If-Match 헤더 없이)에 대한 응답으로 리턴되었을 수 있는 엔터
티의 엔터티 태그와 일치하는 어떠한 엔터티 태그나 "*"이 주어지고 해당 자원에 대한 현재
의 엔터티가 존재한다면 서버는 If-Match 헤더 필드가 존재하지 않는 것처럼 요구 받은
method를 수행할 것이다.

서버는 If-Match의 엔터티 태그를 비교하기 위하여 반드시 강한 비교 기능(strong comparison
function (3.11 절 참조))을 사용해야 한다.

아무런 엔터티 태그도 일치하지 않거나 "*" 이 주어졌는데도 아무런 현재의 엔터티가 존재하
지 않으면 서버는 요구 받은 method를 절대 수행해서는 안되고 반드시 412 (Precondition Failed)
응답을 리턴해야 한다. 이 행태는 클라이언트가 PUT과 같은 갱신 method가 클라이언트가 마
지막으로 조회한 이후 변경된 자원을 다시 변경하지 못하도록 한다.

If-Match 헤더 필드 없이 요구가 2xx 상태 이외의 어떤 것이라도 초래하게 되면 If-Match를 무
시해야 한다.

"If-Match: *" 의 의미는 원서버(또는 Vary 메커니즘을 이용한 캐시, 14.43절 참조)가 선택한 표
시 방법이 존재하면 method를 반드시 수행해야 하고 그렇지 않다면 절대 수행해서는 안 된다
는 것이다.

[Page 121]


자원을 갱신할 목적의 요구(예를 들어 PUT)는 If-Match값(단일 엔터티 태그)에 상응하는 엔터
티가 더 이상 해당 자원을 표시하는 않는다면 요구 method를 절대로 적용해서는 안 된다는
것을 표시하기 위하여 If-Match 헤더 필드를 포함할 수 있다. 이것은 사용자가 자신이 인지하
지 못하는 동안 자원이 변경되었으면 요구가 완료되는 것을 바라지 않음을 표시할 수 있도록
한다.
예를 들면,

          If-Match: "xyzzy"
          If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
          If-Match: *

14.26 If-None-Match

If-None-Match request-header 필드는 method와 함께 사용하여 method를 조건적으로 만든다. 이
전에 자원에서 획득한 하나 또는 그 이상의 엔터티를 가진 클라이언트는 연관된 엔터티 태그
의 목록을 If-None-Match 헤더 필드에 포함하여 이러한 엔터티 중의 하나가 현재의 것임을 증
명할 수 있다. 이 기능의 목적은 트랜잭션 오버헤드(transaction overhead)를 최소화하면서 캐시
된 정보를 효과적으로 갱신할 수 있도록 하는 것이다. 또한 요구를 갱신할 때 자원의 잘못된
버전에 대한 부주의한 변경을 방지하는 데 사용할 수 있다.

특별한 경우로 "*" 값은 자원의 모든 현재 엔터티와 일치한다.

          If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

해당 자원에 유사한GET 요구(If-Match 헤더 없이)에 대한 응답으로 리턴되었을 수 있는 엔터
티의 엔터티 태그와 일치하는 어떠한 엔터티 태그나 "*"이 주어지고 해당 자원에 대한 현재의
엔터티가 존재한다면 서버는 요구 받은 method를 절대로 수행해서는 안 된다. 대신 요구
method가 GET 또는 HEAD이면 서버는 일치하는 엔터티 중 하나의 캐시와 관련된 entity-
header 필드(특히 ETag)를 포함하여 304 (Not Modified) 응답으로 응해야 한다. 다른 모든 요구
method에 대해서 서버는 상태 412(Precondition Failed)로 응답해야 한다.

두 엔터티 태그가 일치하는지 결정하는 원칙에 대하여는 13.3.3절을 참조한다. GET 또는
HEAD 요구에는 약한 비교 기능(weak comparison function )만을 사용할 수 있다.

어떠한 엔터티 태그도 일치하지 않고 "*"이 주어지고 해당 자원에 대한 아무런 현재 엔터티도
존재하지 않는다면 서버는 If-None-Match 헤더 필드가 존재하지 않는 것처럼 요구 받은
method를 수행할 것이다.

[Page 121]


If-None-Match 헤더 필드 없이 요구가 2xx 상태 이외의 어떤 것이라도 초래하게 되면 If-None-
Match를 무시해야 한다.

" If-None-Match: *" 의 의미는 원서버(또는 Vary 메커니즘을 이용한 캐시, 14.43절 참조)가 선택
한 표시 방법이 존재하면 method를 반드시 수행해야 하고 그렇지 않다면 절대 수행해서는 안
된다는 것이다. 이 기능은 PUT 처리 시 경쟁(race)을 방지하는 데 유용하다.

   예:

          If-None-Match: "xyzzy"
          If-None-Match: W/"xyzzy"
          If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
          If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
          If-None-Match: *

14.27 If-Range

클라이언트가 자신의 캐시에 엔터티의 부분적 사본을 가지고 있고 전체 엔터티의 최신 갱신
사본을 가지고 싶다면 조건적인 GET(If-Unmodified-Since 및 If-Match 중 하나나 둘 모두를 이
용하여)의 Range request-header를 사용할 수 있다. 그러나 엔터티가 변경되어 조건이 실패한다
면 클라이언트는 현재의 전체 entity-body를 획득하기 위해 2차 요구를 할 수 있다.

If-Range 헤더는 클라이언트가 2차 요구를 "단축(short-circuit)"할 수 있도록 한다. 약식으로 말
하면 이것의 의미는 `엔터티가 변경되지 않았다면 내가 빠트린 부분만을 발송하고 그렇지 않
다면 새로운 전체 엔터티를 발송하시오. '이다.

           If-Range = "If-Range" ":" ( entity-tag | HTTP-date )

클라이언트가 엔터티의 엔터티 태그를 가지고 있지 않으나 Last-Modified 날짜를 가지고 있으
면 클라이언트는 그 날짜를 If-Range 헤더에서 사용할 수 있다. (서버는 2 문자 이내를 검사하
여 유효한 HTTP-date와 entity-tage의 어떠한 폼도 구별할 수 있다.) If-Range 헤더는 Range 헤
더와 함께만 사용할 수 있으며, Range 헤더를 포함하고 있지 않거나 서버가 하부-영역 운영
(sub-range operation)을 지원하지 않으면 요구를 반드시 무시해야 한다.

[Page 123]


If-Range 내의 엔터티 태그가 엔터티의 현재 엔터티 태그와 일치하면 서버는 206 (Partial
content)응답을 이용하여 자세한 엔터티의 하부-영역을 제공해야만 한다. 엔터티 태그가 일치하
지 않으면 서버는 200 (OK) 응답을 이용하여 전체 엔터티를 리턴해야 한다.

14.28 If-Unmodified-Since

If-Unmodified-Since request-header 필드는 method와 함께 사용하여 method를 조건적으로 만든다.
요구된 자원이 이 필드에 명시된 시간 이후 변경되지 않았으면 서버는 If-Unmodified-Since 헤
더가 존재하지 않는 것처럼 요구 받은 작업을 수행해야 한다.

요구 받은 변형자가 지정된 시간 이후에 변경되었으면 서버는 요구 받은 작업을 절대로 수행
해서는 안 되며 반드시 412 (Precondition Failed)를 리턴해야 한다.

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

이 필드의 사용 예는,

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

요구가 대개(예를 들어 If-Unmodified-Since 헤더 없이) 2xx 상태 이외의 어떤 것이라도 초래하
게 되면 If-Unmodified-Since를 무시해야 한다.

명시한 날짜가 유효하지 않으면 헤더를 무시해야 한다.

14.29 Last-Modified

Last-Modified entity-header 필드는 원서버가 변형자가 마지막으로 변경되었다고 믿는 날짜와 시
간을 표시한다.

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

사용 예는,

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

이 헤더 필드의 정확한 의미는 원서버의 구현 방식 및 원래 자원의 성격에 따라 달라진다. 파
일의 경우 의미는 파일 시스템에서 마지막으로 변경된 시간을 역동적으로 부분을 포함하는 엔
터티의 경우 의미는 부분 요소가 마지막으로 변경된 시간 세트가 될 수 있다. 데이터 베이스
게이트웨이의 경우에는 레코드의 최근 갱신 시간 스탬프(stamp)를 , 가상 객체의 경우에는 내
부 상태가 마지막으로 변경된 시간일 수 있다.
[Page 124]


원서버는 절대 서버의 메시지 발생 시간보다 늦은 Last-Modified 날자를 발송해서는 안 된다.
이처럼 자원의 최근 변경이 미래의 특정 시간을 표시하는 경우 서버는 그 날짜를 메시지 발생
날짜로 대체해야 한다.

기본 서버는 엔터티의 Last-Modified 값을 응답의 Date 값을 생성한 시간과 가능한 한 가까운
것을 얻어야 한다. 이것은 수신측이 특히 엔터티가 응답이 생성된 시간에 가깝게 변경되었을
때 정확하게 엔터티의 변경 시간을 평가할 수 있도록 한다.

HTTP/1.1 서버는 가능할 때 마다 반드시 Last-Modified를 발송해야 한다.

14.30 Location

Location response-header 필드는 요구의 완성 또는 새로운 자원의 식별을 위해 수신측의 방향을
Request-URI 가 아닌 다른 장소로 방향을 재설정하는 데 사용한다. 201 (Created) 응답의 경우
Location 은 요구에 의해 새롭게 생성된 자원의 위치이다. 3xx 응답의 경우 위치는 자원의 자
동 방향 재설정을 위해 서버가 선호하는 URL을 표시한다.

          Location       = "Location" ":" absoluteURI

예는,

          Location: http://www.w3.org/pub/WWW/People.html

주의 : Content-Location 헤더 필드(14.15절)는 Content-Location이 요구에 포함된 엔터티의 원
래 위치를 식별한다는 점에서 Location과 다르다. 따라서 응답이 Location 및 Content-
Location 헤더 필드를 모두 포함할 수 있다. 몇몇 methods의 캐시 필요 조건에 관해서는
13.10 절을 참조한다.

14.31 Max-Forwards

Max-Forwards request-header 필드는 TRACE method (14.31 절)와 함께 사용하여 다음의 들어오는
방향(inbound)의 서버에 요구를 전달할 수 있는 프락시나 게이트웨이의 숫자를 제한한다.

          Max-Forwards   = "Max-Forwards" ":" 1*DIGIT

[Page 125]


Max-Forwards 값은 이 요구 메시지가 전달될 수 있는 남은 횟수를 표시하는 십진수 정수이다.

Max-Forwards 헤더 필드를 포함하고 있는 TRACE 요구를 수신하는 각각의 프락시나 게이트웨
이는 요구를 전달하지 이전에 그 값을 점검하고 갱신해야만 한다. 수신된 값이 제로(0)이면 수
신측은 요구를 전달해서는 안 되며 대신 수신한 요구 메시지를 응답 entity-body(9.8 절에 기술
한 바와 같이)로서 포함하는 200 (OK) 응답으로 마지막 수신측의 입장에서 응답해야 한다. 수
신한 Max-Forwards 값이 제로보다 크면 전달된 메시지는 값이 1만큼 감소된 갱신된 Max-
Forwards 필드를 포함해야 한다.

Max-Forwards 헤더 필드는 이 규격에서 정의한 다른 모든 method 및 해당 method 정의의 일
부분으로 명백하게 참조되지 않는 모든 확장 method에서는 무시되어야 한다.

14.32 Pragma

Pragma general-header 필드는 request/response chain을 따라 어떤 수신측에도 적용할 수 있는 구
현 방식에 한정된 지시자(implementation-specific)를 포함하는 데 사용한다. 모든 pragma 지시자
는 규약의 관점에서 선택 사항적 행태를 명시한다. 그러나 몇몇 시스템은 그 행태가 지시자와
일치할 것을 요구한다.

          Pragma             = "Pragma" ":" 1#pragma-directive

          pragma-directive   = "no-cache" | extension-pragma
          extension-pragma   = token [ "=" ( token | quoted-string ) ]

No-cache 지시자가 요구 메시지에 존재하면 애플리케이션은 요구되고 있는 것의 캐시 사본을
가지고 있다 하더라도 요구를 원서버에 전달해야 한다. 이 pragma 지시자는 no-cache cache-
directive (14.9 절 참조)와 동일한 의미를 가지며 여기서는 HTTP/1.0과의 호환성 유지를 위해
규정하였다. 클라이언트는 No-cache 요구가 HTTP/1.1을 따르지 않는 것으로 알려진 서버로 전
달되었을 때 두 헤더 필드를 모두 포함해야 한다.

Pragma 지시자는 애플리케이션에서 가지는 중요도에 관계없이 지시자는 request/response chain을 따
라 모든 수신측에 적용할 수 있기 때문에 반드시 프락시나 게이트웨이 애플리케이션을 통과해
야 한다.

[Page 126]


HTTP/1.1 클라이언트는 Pragma request-header를 발송해서는 안 된다. HTTP/1.1 캐시는 "Pragma:
no-cache"를 클라이언트가 "Cache-Control: no-cache"를 발송한 것처럼 취급해야 한다. 더 이상의
새로운 Pragma 지시자는 HTTP에 규정되지 않을 것이다.

14.33 Proxy-Authenticate

Proxy-Authenticate response-header 필드는 407 (Proxy Authentication Required) 응답의 일 부분으로
반드시 포함해야 한다. 필드 값은 Request-URI의 프락시에 적용할 수 있는 인증 scheme이나
파라미터를 표시하는 인증 획득 시도로 구성되어 있다.

          Proxy-Authenticate  = "Proxy-Authenticate" ":" challenge

HTTP 접근 인증 처리는 11장에 기술되어 있다. WWW-Authenticate와는 달리 Proxy-
Authenticate 헤더 필드는 현재의 접속에만 적용되며 다운스트림(downstream) 클라이언트로 전
달해서는 안 된다. 그러나 가장 가까운 프락시는 다운스트림(downstream) 클라이언트에 요청하
여 자신의 증명서를 획득할 필요가 있을 수 있다. 어떤 상황에서는 프락시가 헤더 필드를 전
송하는 것처럼 보일 것이다.

14.34 Proxy-Authorization

Proxy-Authorization request-header 필드는 클라이언트가 인증을 요구하는 프락시 자신(또는 자신
의 사용자)을 식별시킨다. Proxy-Authorization 필드 값은 프락시 및/또는 요청되고 있는 자원의
영역에 관한 사용 에이전트의 인증 획득 정보를 포함하고 있는 증명서로 구성되어 있다.

       Proxy-Authorization     = "Proxy-Authorization" ":" credentials

HTTP 접근 인증 획득 절차는 11 장에 기술되어 있다. Authorization와는 달리  Proxy-
Authorization 헤더 필드는 Proxy-Authenticate 필드를 이용한 인증 획득을 요구하는 다음의 외부
로 향한(outbound) 프락시에만 적용된다. Chain에서 복수의 프락시가 사용되었을 때 Proxy-
Authorization 헤더 필드는 보증서를 수신할 예정인 외부로 향한 첫 프락시에 의해 사용된다.
프락시는 그것이 프락시가 주어진 요구를 상호 협조적으로 인증하는 메커니즘이라면 보증서를
클라이언트 요구에서 다음 프락시로 중계할 수 있다.

14.35 Public

Public response-header 필드는 서버가 지원하는 methods 세트를 열거한다. 이 필드의 목적은 엄
격하게 수신측에 이례적인 methods에 관한 서버의 능력을 알리는 데 있다.
[Page 127]


열거된 method는 Request-URI에 적용할 수 도 할 수 없을 수도 있다. Allow 헤더 필드(14.7절)
는 특정 URI에 사용할 수 있는 method를 표시하는 데 사용한다.

          Public         = "Public" ":" 1#method

사용 예는,

          Public: OPTIONS, MGET, MHEAD, GET, HEAD

이 헤더 필드는 클라이언트(예를 들어 연결 고리의 가장 가까운 이웃)에 직접적으로 접속된
서버에만 적용된다. 응답이 프락시를 통과한다면 프락시는 Public 헤더 필드를 삭제하든지 자
신의 능력에 적용할 수 있는 것으로 대체해야 한다.

14.36 Range

14.36.1 Byte Ranges

모든 HTTP 엔터티는 연속적인 바이트로서 HTTP 메시지 내에 표현되기 때문에 바이트 범위의
개념은 모든 HTTP 엔터티에 의미가 있다.(그러나 모든 클라이언트나 서버가 byte-range 작업을
지원할 필요는 없다.)

HTTP 내의 바이트 영역 규격은 entity-body(반드시 message-body와 동일할 필요는 없다.) 내의
바이트 연속에 적용된다.

바이트 영역 작업은 단일 바이트 영역이나 단일 엔터티 내의 영역 세트를 명시할 수 있다.

       ranges-specifier  = byte-ranges-specifier

       byte-ranges-specifier = bytes-unit "=" byte-range-set

       byte-range-set   = 1#( byte-range-spec | suffix-byte-range-spec )

       byte-range-spec   = first-byte-pos "-" [last-byte-pos]

       first-byte-pos    = 1*DIGIT

       last-byte-pos     = 1*DIGIT

Byte-range-spec의 first-byte-pos 값은 영역에서 첫 바이트의 byte-offset을 제공한다. Last-byte-pos
값은 영역에서 마지막 바이트의 byte-offset을 제공한다. 말하자면 명시된 바이트 위치는 포괄
적인 것이다. 바이트 오프셋(byte offsets)은 0부터 시작한다.
[Page 128]


Last-byte-pos 값이 존재하면 해당byte-range-spec의 first-byte-pos보다 크거나 같아야 한다. 그렇
지 않으면 byte-range-spec은 유효하지 않다. 유효하지 않는 byte-range-spec의 수신측은 이를 무
시해야 한다.

Last-byte-pos 값이 없거나 entity-body의 현재 길이보다 크거나 같으면 last-byte-pos 은 바이트
단위로 entity-body의 현재 길이보다 작은 것과 동일한 것을 사용해야 한다.

클라이언트는 last-byte-pos 선택을 통하여 엔터티의 크기를 모른 채 수신한 바이트의 숫자를
제한할 수 있다.

          suffix-byte-range-spec = "-" suffix-length

          suffix-length = 1*DIGIT

Suffix-byte-range-spec은 suffix-length 값이 부여한 길이의 entity-body 접미사를 명시하는 데 사
용한다.(말하자면 이 폼이 entity-body의 마지막 N 바이트를 명시한다.) 엔터티가 명시된 suffix-
length보다 짧으면 전체 entity-body가 사용된다.

Byte-ranges-specifier 값의 사용 예이다.(entity-body 의 길이가 10000이라고 가정했을 때)

? 첫 500 바이트 (byte offsets 0-499, inclusive):

          bytes=0-499

? 두 번째 500 바이트 (byte offsets 500-999, inclusive):

          bytes=500-999

? 마지막 500 바이트(byte offsets 9500-9999, inclusive):

          bytes=-500

? 또는

          bytes=9500-

? 처음과 마지막 바이트만(bytes 0 and 9999):

          bytes=0-0,-1

[Page 129]


? 규범적이지는 않지만 유효한 두 번째 500 바이트 명시 (byte offsets 500-999, inclusive):

          bytes=500-600,601-999

          bytes=500-700,601-999

14.36.2 Range Retrieval Requests

조건적 또는 무조건적 GET method를 이용하는 HTTP 조회 요구는 Range 요구 헤더를 이용하
여 요구의 결과로 리턴되는 엔터티에 적용할 수 있는 전체 엔터티 대신 하나 또는 그 이상의
엔터티의 하부 영역을 요청할 수 있다.

         Range = "Range" ":" ranges-specifier

서버는 Range 헤더를 무시할 수 있다. 그러나 HTTP/1.1 원서버 및 가장 가까운 캐시는 Range
가 부분적으로 실패한 전송을 효과적으로 복구하고 큰 엔터티의 효과적인 부분적 조회를 지원
하기 때문에 가능하면 바이트 영역을 지원해야 한다.

서버가 Range 헤더를 지원하고 명시된 영역 이나 영역들이 엔터티에 적합하다면:

? 무조건적인 GET에 Range 헤더가 있으면 GET이 성공했을 때 리턴되는 것을 변경한다.
달리 표현하면 응답은 상태 코드 200 (OK) 대신에 206 (Partial Content)을 가지고 온다.
 
? 조건적인 GET(If-Modified-Since 및 If-None-Match 중 하나나 둘 모두, 또는If-Unmodified-
Since 및 If-Match 중 하나나 둘 모두를 이용하는 요구)에 Range 헤더가 있으면 GET이
성공하고 조건이 참일 때 리턴되는 것을 변경한다. 이것은 조건이 거짓일 경우 리턴되
는 304 (Not Modified) 응답에 영향을 미치지 않는다.

어떤 경우에는 Range 헤더에 첨가형 If-Range 헤더(14.27 절 참조)를 사용하는 것이 더 적절할
수도 있다.

Range를 지원하는 프락시가 Range 요구를 수신하고 안으로 향하는(inbound) 서버에 요구를 전
달하고 이의 응답으로 전체 엔터티를 수신하면 프락시는 클라이언트에게 요구 받은 영역만을
리턴해야 한다. 프락시는 그것이 캐시 할당 정책과 부합된다면 전체 수신 응답을 자신의 캐시
에 저장해야 한다.

[Page 130]


14.37 Referer

Referer[sic] request-header 필드는 클라이언트가 서버를 위해 Request-URI를 얻은("referrer", 헤더
필드의 스펠링이 틀렸다.) 자원의 주소(URI)를 명시하는 데 사용한다. Referer request-header는
서버가 취미, 로깅 또는 최적화된 캐시 등의 목적으로 자원에 대한 back-links 목록을 생성할
수 있도록 한다. 또는 폐기되었거나 타이핑을 잘못한 링크를 유지관리하기 위해 추적할 수 있
도록 한다. Referer 필드는 사용자 키보드에서의 입력 등 자신의 URI를 가지고 있지 않는 출처
에서 얻은 Request-URI를 절대로 발송해서는 안 된다.

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

예:

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

필드 값이 부분적 URI이면 값을 Request-URI에 상대적으로 해석해야 한다. URI는 절대로 파
편을 포함해서는 안 된다.

주의: 링크의 출처가 개인적인 정보이거나 개인적인 정보 출처를 누설할 수 있기 때문에 사용
자는 Referer 필드를 발송할 것인지 여부를 선택할 수 있도록 할 것을 강력하게 추천한다. 예
를 들어 브라우저 클라이언트는 공개/무명 브라우징(browsing)의 토글 스위치(toggle switch)를
가질 수 있으며 이는 각각 Referer 및 From 정보의 발송을 확성화/무력화한다.

14.38 Retry-After

Retry-After response-header 필드는 503 (Service Unavailable) 응답과 함께 사용하여 요청하는 클라
이언트에게 얼마나 오랫동안 서비스를 사용할 수 있는지 표시할 수 있다. 이 필드의 값은 응
답 시간 이후의 HTTP-date 또는 초의 정수(십진수)가 될 수 있다.

          Retry-After  = "Retry-After" ":" ( HTTP-date | delta-seconds )

사용의 두 예는,

          Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
          Retry-After: 120

후자의 예에서 지연시간은 2 분이다.

[Page 131]


14.39 Server

Server response-header 필드는 요구를 처리하는 원서버가 사용하는 소프트웨어에 관한 정보를
포함하고 있다. 이 필드는 서버와 중요한 하부 제품을 식별하는 복수의 제품 토큰(3.8 절) 및
주석을 포함하고 있다. 제품 토큰은 애플리케이션을 식별하는 중요도의 순서에 따라 열거되어
있다.

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

예:

          Server: CERN/3.0 libwww/2.17

응답이 프락시를 통하여 전달된다면 프락시 애플리케이션은 절대 Server response-header를 변
경해서는 안 된다. 대신 프락시는 Via 필드(14.44 절에 기술된 대로)를 포함하여야 한다.

주의: 서버의 특정 소프트웨어 버전을 누설하는 것은 서버가 보안 허점(security holes)을 가진
것으로 알려진 소프트웨어에 대한 공격에 더욱 취약하도록 만들 수 있다. 서버 구현자는 이
필드를 설정할 수 있는 선택 사항으로 만들 것을 권고한다.

14.40 Transfer-Encoding

Transfer-Encoding general-header 필드는 송신측과 수신측 사이에 메시지를 안전하게 전송하기
위해 어떤(적용되었다면) 유형의 변형이 메시지에 적용되었는지 표시한다. 이것은 전송 코딩
(transfer coding)이 메시지의 특성이지 엔터티의 특성이 아니라는 점에서 Content-Encoding과 다
르다.

          Transfer-Encoding     = "Transfer-Encoding" ":" 1#transfer-coding

Transfer codings은 3.6 절에 규정되어 있으면 그 예는,

          Transfer-Encoding: chunked

많은 이전 HTTP/1.0 애플리케이션은 Transfer- Encoding 헤더를 이해하지 못한다.

14.41 Upgrade

Upgrade general-header는 클라이언트가 추가적으로 어떤 통신 규약을 지원하며 규약을 전환하
는 것이 적절할 때 어떤 통신 규약을 사용하고자 하는지 명시할 수 있도록 한다.

[Page 132]


서버는 반드시 Upgrade 헤더 필드를 101 (Switching Protocols) 응답에 사용하여 어떤 규약이 전
환되고 있는지 표시해야 한다.

          Upgrade        = "Upgrade" ":" 1#product

   For example,

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

Upgrade 헤더 필드는 HTTP/1.1에서 다른 호환되지 않는 규약으로 이전하는 간단한 메커니즘
을 제공할 목적으로 사용된다. 클라이언트가 비록 현재 의 요구를 HTTP/1.1을 이용하여 작성
하였다 하더라도 높은 주요 변경 버전 번호를 가진 HTTP의 이후 버전과 같은 다른 규약을
사용하고 싶다는 것을 광고할 수 있도록 하여 이를 성취한다. 이것은 클라이언트가 사용할 수
있다면 "좀더 낳은" 규약을 사용하고 싶어한다는 것을 표시하면서도 클라이언트가 좀더 보편
적으로 지원되는 규약에서 요구를 시작할 수 있도록 하여 호환되지 않는 규약간의 어려운 이
전을 용이하게 한다. ("좀더 낳은" 규약은 가능하면 요구하고 있는 method 및/또는 자원의 기본
적인 성격에 따라 서버가 결정한다.)

Upgrade 헤더 필드는 기존의 전송-계층 연결 위에서 애플리케이션-계층 규약을 전환하는 것에
만 적용된다. Upgrade는 규약의 전환을 고집하는 데 사용할 수 없다. 전환의 수용 및 사용은
서버의 선택 사항이다. 규약 변경 후의 첫 작업은 Upgrade 헤더 필드를 포함하고 있는 첫
HTTP  요구에 대한 응답이어야 하지만 규약 변경 이후의 애플리케이션-계층 통신의 능력 및
기본적인 성격은 새롭게 선택된 규약에 전적으로 달려 있다.

Upgrade 헤더 필드는 오직 가장 가까운 연결에만 적용된다. 따라서 Upgrade 핵심어는 Upgrade
헤더 필드가 HTTP/1.1 메시지에 존재할 때 Connection 헤더 필드(14.10 절) 내에서만 제공하여
야 한다.

Upgrade 헤더 필드는 다른 연결로의 규약 전환을 표시하는 데 사용할 수 없다. 이러한 목적에
는 301, 302, 303 또는 305 방향 재설정 응답이 더 적절하다.

이 규격은 3.1절의 HTTP 버전 규칙 및 이 규격의 향후 개정에서 규정한 것과 같이 하이퍼텍
스트 전송 규약 집단에서 사용할 목적으로 오직 "HTTP"라는 이름의 규약만을 규정한다. 규약
이름을 위해 어떠한 토큰을 사용해도 되지만 클라이언트와 서버 모두가 해당 이름을 동일한
규약으로 연관시킬 때문에 유용할 것이다.

[Page 133]


14.42 User-Agent

User-Agent request-header 필드는 요구를 만들어 낸 사용자 에이전트에 관한 정보를 포함하고
있다. 이것은 통계 목적, 규약 위반의 추적, 특정 사용자 에이전트 한계를 피하기 위해 응답을
고칠 목적으로 사용자 에이전트를 자동 인지하기 위함이다. 사용자 에이전트는 요구에 이 필
드를 포함해야 한다. 이 필드는 사용자 에이전트의 중대한 부분을 형성하는 에이전트, 모든 하
부 제품을 식별할 수 있는 복수의 제품 토큰(3.8절) 및 주석을 포함할 수 있다. 관례상 제품
토큰은 애플리케이션을 식별하는 중요도의 순서에 따라 열거되어 있다.

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

예:

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

14.43 Vary

Vary response-header 필드는 서버가 응답 엔터티를 서버가 주도하는 협상( 12장)을 이용한 이용
가능한 응답의 표시 방법에서 선택하였음을 표시하는 데 사용한다. Vary 헤더에 열거된 field-
names은 request-headers의 field-names이다. Vary 필드 값은 주어진 헤더 필드 세트가 표시 방
식이 변화할 수 있는 차원을 넘어선다는 것을 나타내거나, 변형의 차원이 명시되지 않아("*")
향후 요구의 어떠한 측면에서도 변형될 수 있다는 것을 나타낸다.

          Vary  = "Vary" ":" ( "*" | 1#field-name )

HTTP/1.1 서버는 반드시 서버가 주도하는 협상에 종속되는 모든 캐시할 수 있는 응답에 적절
한 Vary 헤더 필드를 포함해야 한다. 이렇게 하면 캐시가 해당 자원에 대한 향후 요구를 적절
하게 해석할 수 있도록 하며 사용자 에이전트에게 해당 자원에 대한 협상이 존재함을 알릴 수
있다. 서버는 서버가 주도하는 협상에 종속되는 캐시할 수 없는 응답에 적절한 Vary 헤더 필
드를 포함해야 한다. 이것이 사용자 에이전트에게 응답이 변형될 수 있는 차원에 관한 유용한
정보를 제공할 수 있기 때문이다.

Vary 헤더 필드 값에 의하여 명명되는 헤더 필드의 세트는 "selecting" request-headers로 알려져
있다.

캐시가 Request-URI가 Vary 헤더를 포함한 하나 또는 그 이상의 캐시 엔트리를 명시하는 계속
적인 요구를 수신했을 때 캐시된 Vary 헤더에 명명된 모든 헤더가 새로운 요구에 있거나 이전
요구의 모든 저장된 selecting request-headers가 새로운 요구의 해당 헤더와 일치하지 않는 한
캐시는 절대 이러한 캐시 엔트리를 이용하여 새로운 요구에 대한 응답을 구성해서는 안 된다.
[Page 134]


두 요구는 메시지 헤더에 관한 4.2 절의 규칙에 따라 동일한 필드 이름의 복수 message-header
필드를 결합하거나 또한/또는 선형 공백문자(LWS)를 상응하는 BNF가 허용하는 지점에 추가
하거나 삭제하여 첫 요구의 selecting request-headers가 두 번째 요구의 selecting request-headers
로 변환될 수 있을 때만 일치하는 것으로 규정된다.

"*" 의 Vary 필드 값은 아마도 request-header 필드 내용이 아닌(예를 들어 클라이언트의 네트워
크 주소) 명시되지 않은 파라미터가 응답 표시 방법의 선택에 어떤 역할을 수행하고 있음을
표시한다. 해당 자원에 대해 계속되는 요구는 원서버에 의하여 적절히 해석될 수 있기 때문에
자원의 캐시된 신선한 응답을 가지고 있을 때도 캐시는 반드시 요구를(조건적일 수 있다.) 전
송해야 한다. 캐시가 사용하는 Vary 헤더에 대해서는 13.6 절을 참조한다.

Field-names 목록으로 구성된 Vary 필드 값은 응답을 위해 선택된 표시 방식이 최적의 표시 방
법을 선택할 때 열거된 request-header 필드 값만을 고려하는 선택 알고리즘에 기초하고 있다는
것을 표시한다. 캐시는 열거된 필드 이름을 위해 동일한 값으로 응답이 신선한 시간 동안만
향후의 요구에서 동일한 선택을 하게 되리라 가정해도 된다.

주어진 field-names은 이 규격에서 규정한 표준 request-header 세트에 한정된 것은 아니다. 필
드 이름은 대소문자를 구별한다.

14.44 Via

게이트웨이나 프락시는 반드시 Via general-header 필드를 사용하여 요구를 만들었을 때는 사용
자 에이전트와 서버 사이의, 응답을 수신했을 때는 원서버와 클라이언트 사이의 가장 가까운
규약 및 수신측을 표시해야 한다. 이것은 RFC 822의 "Received" 필드와 유사하다. 또한 이것을
메시지 전달(message forwards)을 추적하고, 요구 루프(request loops)를 피하며 request/response
chain을 따라 모든 송신측의 규약 능력을 식별하는 데 사용하도록 계획되었다.

[Page 135]


      Via =  "Via" ":" 1#( received-protocol received-by [ comment ] )

      received-protocol  = [ protocol-name "/" ] protocol-version
      protocol-name      = token
      protocol-version   = token
      received-by        = ( host [ ":" port ] ) | pseudonym
      pseudonym        = token

Received-protocol은 request/response chain의 각 부분(segment)을 따라 서버가 클라이언트가 수신
하는 메시지의 규약 버전을 표시한다. Received-protocol은 업스트림(upstream) 애플리케이션에
관한 정보를 모든 수신측이 볼 수 있도록 하기 위해 메시지가 전달되었을 때 Via 필드 값에
추가된다.

Protocol-name 은 그것이 "HTTP"일 때만 선택 사항이다. Received-by 필드는 보통 계속적으로
메시지를 전달하는 수신측 서버나 클라이언트의 호스트나 선택적인 포트 번호이다. 그러나 진
짜 호스트가 민감한 정보를 가진 것으로 간주된다면 가명(pseudonym)으로 대체할 수 있다. 포
트가 주어지지 않았으면 received-protocol의 기본 포트인 것으로 가정할 수 있다.

복수의 Via 필드 값은 메시지를 전달한 각각의 프락시나 게이트웨이를 표시한다. 각각의 수신
측은 마지막 결과가 전송한 애플리케이션의 순서에 따라 순서를 정할 수 있도록 자신의 정보
를 반드시 추가해야 한다.

Via 헤더 필드에 주석을 사용하여 User-Agent나 Server 헤더 필드와 유사하게 수신측 프락시나
게이트웨이의 소프트웨어를 식별할 수 있다. 그러나 Via 필드의 모든 주석은 선택적이며 메시
지를 전달하기 이전에 수신측이 삭제할 수 있다.

예를 들어 HTTP/1.0 사용자 에이전트에서 요구 메시지를 HTTP/1.1을 이용하여 "fred"라는 코
드 이름이 붙은 내부 프락시로 전달할 수 있다. 내부 프락시는 요구를 nowhere.com에 있는 공
공 프락시로 전달하며 nowhere.com은 요구를 www.ics.uci.edu에 있는 원서버에 전달하여 요구
처리를 완료한다면 www.ics.uci.edu가 수신한 요구는 다음의 Via 헤더 필드를 가지게 될 것이
다.

          Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)

네트워크 방화벽(firewall)의 입구로 사용되는 프락시나 게이트웨이는 기본적으로 방화벽 영역
내의 호스트의 이름이나 포트를 전달해서는 안 된다. 이 정보는 명백하게 활성화되었을 때만
전파할 수 있다. 활성화되지 않았으면 방화벽 뒤의 모든 호스트의 received-by host는 해당 호
스트의 적절한 가명(pseudonym)으로 대체되어야 한다.

[Page 136]


내부 조직을 숨겨야 한다는 강한 사생활 보호 필요 조건을 가진 조직을 위해 프락시는 동일한
received-protocol 값을 가진 Via 헤더 필드 엔트리의 순서가 정해진 순차를 단일 엔트리로 결합
할 수도 있다. 예를 들면,

          Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

을 다음과 같이 축소할 수 있다.

          Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

애플리케이션은 복수의 엔트리를 그것들이 동일한 조직 통제 밑에 있거나 호스트가 가명으로
대체되지 않는 한 결합해서는 안 된다. 애플리케이션은 상이한 received-protocol 값을 가지고
있는 엔트리를 절대로 결합해서는 안 된다.

14.45 Warning

Warning response-header 필드는 응답 상태 코드가 반영하지 않은 응답 상태에 관한 정보를 전
송하는 데 사용한다. 이 정보는 비록 배타적이진 않지만 대개 캐시 작업에 발생할 수 있는 의
미 투명성(semantic transparency)의 결여에 대한 경고를 하는 데 사용한다.

Warning 헤더는 다음을 이용하여 응답과 함께 발송된다.

          Warning     = "Warning" ":" 1#warning-value

          warning-value  = warn-code SP warn-agent SP warn-text
          warn-code    = 2DIGIT
          warn-agent   = ( host [ ":" port ] ) | pseudonym
                          ; Warning 헤더를 추가하는 서버의 이름 또는 별명
  ; 디버깅에 사용한다.
          warn-text    = quoted-string

하나의 응답은 하나 이상의 Warning 헤더를 포함할 수 있다.

Warn-text는 응답을 수신하는 인간 사용자가 가장 잘 이해할 수 있는 자연적인 언어 및 문자
집합으로 표시해야 한다. 이에 대한 결정은 캐시나 사용자의 위치, 요구의 Accept-Language 필
드, 응답의 Content-Language 필드 등 사용 가능한 어떤 정보에 기초해도 된다. 기본적인 언어
는 영어이며 기본 문자 집합은 ISO-8859-1이다.

ISO-8859-1 이외의 문자 집합이 사용되었으면 RFC 1522 [14]에 기술한 method를 사용하여
warn-text 내에 인코딩해야 한다.

[Page 137]


어떠한 서버나 캐시도 응답에 Warning 헤더를 추가할 수 있다. 새로운 Warning 헤더는 모든
기존 Warning 헤더 다음에 추가해야 한다. 캐시는 응답과 함께 수신한 어떠한 Warning 헤더도
삭제해서는 안 된다. 그러나 캐시가 성공적으로 캐시 엔트리를 검증했으면 특정 Warning 코드
가 명시한 경우를 제외하고는 해당 엔트리에 이전에 첨가된 모든 Warning 헤더는 삭제해야 한
다. 그런 다음 캐시는 응답을 검증하는 동안 수신한 어떠한 Warning 헤더라도 추가할 수 있다.
달리 표현하면 Warning 헤더는 가장 최근에 관련된 응답에 추가된 헤더이다.

응답에 복수의 Warning 헤더가 첨부되었으며 사용자 에이전트는 응답에서 나타난 순서 대로
가능한 한 많은 Warning 헤더를 표시해야 한다. 모든 경고문을 표시할 수 없을 때 사용자 에
이전트는 다음의 발견법(heuristics)에 따라야 한다.

? 응답의 초기에 나타난 warnings이 나중에 나타난 것보다 우선권을 갖는다.
? 사용자가 선호하는 문자 집합에서 발생한 warning이 다른 문자 집합의 warnings보다 우
선권을 갖는다. 그러나 warn-codes 및 warn-agents는 동일하다.

복수의 Warning 헤더를 생성하는 시스템은 이러한 사용자 에이전트의 행태를 염두에 두고 순
서를 정해야 한다.

다음은 현재 정의된 warn-codes이며 영어로 추천 warn-text 및 의미를 기술하고 있다.

10 Response is stale
리턴 된 응답이 낡을 때는 언제나 반드시 포함해야 한다. 캐시는 이 경고를 어떠한 응답에
도 추가할 수 있지만 응답이 새로운 것으로 알려지기 전에는 절대 삭제해서는 안 된다.

11 Revalidation failed
서버에 도달하지 못하기 때문에 응답을 재검증하려는 시도가 실패하여 캐시가 낡은 응답을
리턴하게 되면 반드시 포함해야 한다. 캐시는 이 경고를 어떠한 응답에도 추가할 수 있지만
응답을 성공적으로 재검증하기 전에는 절대 삭제해서는 안 된다.

12 Disconnected operation
캐시가 의도적으로 일정기간 동안 나머지 네트워크로부터 단절되었을 때는 포함해야 한다.

13 Heuristic expiration
캐시가 발견법 상 신선한 기간을 24 시간 이상으로 선택하거나 응답의 경과 시간이 24시간
이상일 때는 반드시 포함해야 한다.

[Page 138]


14 Transformation applied

가장 가까운 캐시나 프락시가 이 Warning 코드가 응답에 포함되어 있지 않은 한 content-
coding(Content-Encoding 헤더에 명시된 것처럼) 또는 응답의 media-type (Content -Type 헤더에 명
시된 것처럼)에 변형을 가하는 변경 사항을 적용했을 때 반드시 추가해야 한다. 재검증 후에
도 응답에서 삭제해서는 안 된다.

99 Miscellaneous warning
경고 텍스트는 인간 사용자에게 제공하기 위해 또는 로깅하기 위해 자의적인 정보를 포함할
수 있다. 이 경고를 수신한 시스템은 절대로 어떠한 자동 작업도 수행해서는 안 된다.

14.46 WWW-Authenticate

WWW-Authenticate response-header 필드를 반드시 401(Unauthorized) 응답 메시지에 포함해야 한
다. 필드 값은 Request-URI에 적용할 수 있는 인증 획득 scheme 및 파라미터를 나타내는 최소
한 하나의 인증 시도(challenge)로 구성된다.

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

11 장에 HTTP 접근 인증 획득 절차가 기술되어 있다. 사용자 에이전트는 WWW-Authenticate
필드 값을 분석할 때 하나 이상의 WWW-Authenticate 헤더 필드가 있으면 인증 시도의 내용이
인증 파라미터의 콤마로 분리된 목록을 포함하고 있기 때문에 각별한 주의를 해야 한다.

15 보안에 대한 고려 사항

이 절에서는 이 문서가 기술한 바와 같이 애플리케이션 개발자, 정보 제공자 및 사용자에게
HTTP/1.1의 보안 제한 사항을 알리고자 한다. 토론이 규정적인 해결 방안을 포함하지는 않지
만 보안의 위험성을 감소시킬 수 있는 몇몇 안을 제시한다.

15.1 클라이언트의 인증

Basic authentication scheme은 운반용기(carrier)로 사용되어 명백한 텍스트로 물리적인 네트워크
위에서 전송되는 안정된 사용자 인증 method도 아니며 엔터티를 어떤 식이든 보호하지도 않
는다. HTTP는 보안을 증가 시키기 위하여 추가적인 인증 schemes이나 암호화 메커니즘을 사
용하는 것을 금지하는 않는다.(일회 암호 사용 scheme처럼)

[Page 139]


Basic authentication의 가장 심각한 단점은 근본적으로 물리적인 네트워크 위로 사용자의 암호
가 명백한 텍스트로 전달된다는 것이다. Digest Authentication이 언급하고자 하는 것이 바로 이
문제이다.

Basic authentication이 암호의 명백한 텍스트 전송을 수반하기 때문에 민감하고 소중한 정보를
보호하기 위해서(기능 향상 없이는) 결코 사용해서는 안 된다.

Basic authentication의 일반적인 용도는 식별(identification) 목적이다. 예를 들어 정확한 서버의
사용 빈도에 관한 통계를 수집하기 위해서 식별의 수단으로서 사용자의 이름과 암호를 사용자
가 제공하도록 요구한다. 이런 식으로 사용했을 때 보호된 문서에 불법으로 접근하는 것이 주
요 관심사가 아닌 경우 위험성이 없는 것으로 생각할 수 있다. 이것은 서버가 사용자 이름 및
암호를 사용자에게 발행할 때, 특히 사용자가 자신의 암호를 선택할 수 없도록 했을 때 올바
른 생각이다. 순진한 사용자는 종종 복수의 암호를 유지하는 일을 피하기 위해 단일 암호를
재사용하기 때문에 위험이 발생한다.

서버가 사용자로 하여금 자신의 암호를 선택하게 한다면 위험성은 서버의 문서에 불법으로 접
근하는 것뿐만 아니라 자신의 계정 암호를 사용하기로 결정한 모든 사용자의 계정에 불법으로
접근하는 것이다. 사용자가 자신의 암호를 선택하도록 허용한다는 것은 서버가 암호(아마도
암호화된)를 포함하고 있는 파일을 유지해야만 한다는 것을 의미한다. 많은 것들이 원격지 사
이트의 계정 암호일 것이다. 이러한 시스템의 소유주 또는 관리인은 이러한 정보가 안전한 방
법으로 유지되지 않으면 책임 발생을 초래할 수도 있다. 

Basic Authentication는 또한 모조 서버에 의한 속임수에도 취약하다. 사실상 사용자가 적대적인
서버나 게이트웨이에 접속하고 있는데도 기본 인증에 의하여 보호 받는 정보를 포함하고 있는
호스트에 연결되어 있다고 사용자가 믿도록 하였으면 공격자는 암호를 요청하여 이것을 나중
용도를 위해 저장하고 에러인 것처럼 위장할 수 있다.

이런 유형의 공격은 Digest Authentication[32]에서는 가능하지 않다. 서버 구현자는 이와 같은
종류의 게이트웨이나 CGI 스크립트 위조 가능성에 대비하여야 한다. 특히 서버가 연결을 게이
트웨이로 전달하는 것은 상당히 위험하다.

그런 다음 게이트웨이는 지속적인 연결 메커니즘을 이용하여 클라이언트가 탐지할 수 없는 방
식으로 원서버인 것처럼 작동하면서 클라이언트와의 복수 트랜잭션에 참여할 수 있기 때문이
다.

15.2 인증 scheme을 선택할 수 있도록 함

HTTP/1.1 서버는 복수의 인증 시도(challenge)를 401(Authenticate) 응답으로 리턴하며 각각의 인
증 시도는 별도의 scheme을 사용할 수 있다.

[Page 140]


사용자 에이전트에게 리턴되는 인증 시도 순서는 서버가 선호하는 순서이다. 서버는 "가장 안
전한" 인증 획득을 우선으로 하여 자신의 인증 시도 순서를 정해야 한다. 사용자 에이전트는
자신이 이해하는 것을 사용자가 처음 인증을 시도하는 것으로 선택해야 한다.

서버가 WWW-Authenticate헤더를 이용하여 선택한 인증 획득 scheme을 제공할 때 악의의 사
용자가 일련의 인증 시도를 약탈하여 인증 획득 scheme의 가장 약한 부분을 이용하여 자신을
인증하려 하기 때문에 인증 획득의 "안전" 만을 제공하는 것이다. 따라서 순서는 서버의 정보
보다는 사용자의 증명서를 보호하는 데 사용된다.

사람이 중간이 낀 공격(man-in-the-middle (MITM) attack)은 약한 인증 획득 scheme를 선택 사항
세트에 추가하여 클라이언트가 사용자의 증명서(예를 들면 암호)를 노출시키는 것을 하나 사
용할 것이라는 기대하는 것이다. 이러한 이유 때문에 클라이언트는 항상 접수한 선택 사항 중
자신이 이해하는 가장 강한 scheme을 사용해야 한다.

좀더 향상된 MITM 공격은 제공된 모든 선택 사항을 삭제하고 Basic authentication을 요청하는
인증 시도를 삽입하는 것이다. 이러한 이유로 인하여 이러한 공격을 염려하는 사용자 에이전
트는 서버가 요청했던 가장 강력한 인증 획득 scheme을 기억하고 약한 것을 사용하기 전에
사용자의 확인을 요구하는 경고 메시지를 생성할 수 있다. 특히 이러한 공격을 가하려는 음흉
한 방법은 속기 쉬운 사용자에게 "무료" 프락시 캐시를 제공하는 것이다.

15.3 서버 로그 정보의 남용

서버는 사용자의 읽는 유형 및 관심사를 알려 줄 수 있는 사용자의 요청에 관한 개인적인 데
이터를 저장하는 입장에 있다. 이러한 정보는 기본 성격상 분명히 비밀이며 특정 국가에서는
이러한 정보의 처리가 법에 의하여 제한을 받고 있다. 데이터를 제공하기 위해 HTTP 규약을
사용하는 사람은 발행된 결과로 식별할 수 있는 이러한 자료가 개인의 허락 없이 배포되지 않
도록 하는 책임을 갖고 있다.

15.4 민감한 정보의 전송

일반적인 자료 전송 규약처럼 HTTP는 전송되는 데이터의 내용을 통제할 수 없으며 사전에
특정 요구의 문맥에서 정보의 특정 부분의 민감성을 결정할 방법이 없다. 따라서 애플리케이
션은 이러한 정보에 대한 통제를 해당 정보의 제공자에게 가능한 한 많이 제공하여야 한다.
네 개의 필드가 이러한 의미에서 특별히 언급할 가치가 있다. - Server, Via, Referer 및 From.

[Page 141]


서버의 특정 소프트웨어 버전을 표시함으로 해서 서버가 보안 허점을 가진 것으로 알려진 소
프트웨어에 대한 공격에 좀더 취약하도록 만들 수 있다. 구현자는 Server 헤더 필드를 설정할
수 있는 선택 사항으로 만들어야 한다.

네트워크 방화벽을 따라 입구의 역할을 하는 프락시는 방화벽 뒤의 호스트를 식별하는 헤더
정보의 전달에 관하여 특별한 주의를 기해야 한다. 특히 프락시는 방화벽 뒤에서 생성된 모든
Via 필드를 삭제하던지 청소된(sanitized) 버전으로 대체해야 한다.

Referer 필드는 읽기 유형을 연구하고 역 링크를 구성할 수 있도록 한다. 비록 매우 유용하기
는 하지만 Referer에 포함된 정보에서 사용자의 인적 사항을 분리하지 않으면 이러한 능력이
남용될 수 있다. 개인적 정보가 삭제된 이후에도 Referer 필드는 발행하는 것이 적절하지 않는
개인적 문서의 URI를 표시할 수 있다.

From 필드에서 전달하는 정보가 사용자의 사생활 보호나 사용자 사이트의 보안 정책과 충돌
될 수 있다. 따라서 사용자가 필드의 내용을 무력화, 활성화 및 변경할 수 없을 때는 From 필
드는 전달되어서는 안 된다. 사용자는 사용자 선택 사항이나 애플리케이션의 기본 환경 설정
에서 이 필드의 내용을 설정할 수 있어야 한다.

우리는 비록 요구하지는 않지만 편리한 토글(toggle) 인터페이스를 사용자에게 제공하여 사용
자가 From 및 Referer 정보를 활성화 또는 무력화 할 수 있도록 하는 것을 추천한다.

15.5 파일 및 경로 이름에 기초한 공격

HTTP 원서버의 구현 방식은HTTP 응답이 리턴하는 문서를 서버 관리자가 의도한 것만으로
한정하도록 주의하여야 한다. 만약 HTTP 서버가 HTTP URI를 파일 시스템 호출로 바로 해석
하면 서버는 HTTP 클라이언트에게 제공하지 않으려는 파일이 제공되지 않도록 특별한 주의를
해야 한다. 예를 들어 UNIX, Microsoft Windows 및 다른 운영 체계는 현재 디렉토리 바로 위를
표시하기 위해 ".."를 경로 구성원으로 사용한다. 이러한 시스템에서 HTTP 서버는 이것이
HTTP 서버를 통하여 접근하도록 계획된 것 이외의 자원에 접근할 수 있도록 할 수 있기 때문
에 Request-URI에 이러한 구성 형식을 허용하지 말아야 한다. 마찬가지로 서버 내부 참조만을
위한 파일(접근 제어 파일, 환경 설정 파일 및 스크립트 코드 등)은 민감한 정보를 포함하고
있을 수도 있기 때문에 부적절한 조회에서 보호해야 한다. 경험에 따르면 이러한 HTTP 서버
구현 방식의 사소한 버그가 보안 허점으로 바뀔 수도 있음을 보여 주고 있다.

[Page 142]


15.6 개인적인 정보

HTTP 클라이언트는 종종 대량의 개인 정보(사용자의 이름, 위치, 우편 주소, 암호, 암호화 키
등)에 관계되어 있으며 이러한 정보가 HTTP 규약을 통하여 다른 출처로 원하지 않게 누출되
는 것을 방지하도록 주의해야 한다. 우리는 이러한 정보의 배포를 통제할 수 있도록 사용자에
게 편리한 인터페이스를 제공할 것과 디자이너와 구현자들이 이 분야에서 특히 조심할 것을
강력히 추천한다. 전례를 보면 이 분야에서의 에러는 종종 심각한 보안 및/또는 사생활 보호
문제가 되며, 또한 구현자 회사의 평판에 심각한 손상을 입힌다.

15.7 Accept 헤더와 연결된 사생활 보호의 이슈

Accept request-headers는 사용자에 대한 정보를 접근하는 모든 서버에 노출시킬 수 있다. 특히
Accept-Language 헤더는 특정 언어의 이해는 특정 인종 그룹의 멤버십과 강하게 상호 연관되
어 있기 때문에 사용자가 사적인 것으로 간주하는 정보를 노출할 수 있다. 요구를 발송할 때
마다 Accept-Language 헤더의 내용을 설정할 수 있는 선택 사항을 제공하는 사용자 에이전트
는 설정 과정에 사용자가 사생활 보호를 상실할 수도 있음을 인지할 수 있도록 하는 메시지를
포함하도록 강력히 추천한다.

사생활 보호 손실을 제한할 수 있는 접근법은 사용자 에이전트가 기본적으로 Accept-Language
헤더 발송을 생략할 수 있게 하는 것이며 서버가 생성한 Vary response-headers를 검색하여 이
러한 헤더 발송이 서비스의 질을 향상시키는 것임을 알게 된다면 사용자에게 Accept-Language
헤더의 서버 발송을 시작할 것인지 질문하는 것이다.

서버는 모든 요구에 발송하는 정교하고 user-customized된 Accept 헤더 필드를, 특히 이것이 품
질 값을 포함하고 있다면, 비교적 신뢰할 수 있고 오래 지속되는 사용자 식별자로 이용한다.
이러한 사용자 식별자는 내용 제공자가 클릭-흔적 추적(click-trail tracking)을 할 수 있도록 하며
상호 협력하는 내용 제공자가 서버에 걸쳐 클릭-흔적을 일치시키거나 개인 사용자의 폼을 제
출할 수 있도록 한다. 프락시를 사용하지 않는 많은 사용자의 경우 사용자 에이전트를 운영하
는 호스트의 네트워크 주소를 오래 지속되는 사용자 식별자로 사용할 수 있음을 주의한다. 프
락시를 사생활 보호를 향상시키기 위해 사용하는 환경에서 사용자 에이전트는 사용자에게
Accept 헤더를 설정할 수 있도록 할 때 상당히 조심해야 한다. 최대한도의 사생활 보호 조치
로 프락시는 중계되는 요구에서 Accept 헤더를 여과시킬 수 있다. 높은 수준의 헤더 설정 방
법을 제공하는 일반 목적의 사용자 에이전트는 사용자에게 사생활 보호의 손실을 경고해야 한
다.
 
[Page 143]


15.8 DNS Spoofing(속이기)

HTTP를 사용하는 클라이언트는 Domain Name Service에 상당히 의존하고 있으며 일반적으로
교묘하게 IP 주소와 DNS 이름을 잘못 연관시킨 것에 기반을 둔 보안 공격에 취약하다. 클라
이언트는 IP number/DNS name 상관 관계가 지속적으로 유효하다고 가정할 때 주의해야 한다.

특히 HTTP 클라이언트는 이전의 호스트 이름 조회 결과를 캐시하기보다는 이름 분석자(name
resolver)가 IP number/DNS name 상관 관계를 확인하는 것에 의존해야 한다. 많은 플랫폼이 적
절한 경우 호스트 이름 검색을 지역에 캐시할 수 있게 하며 그렇도록 환경을 설정해야 한다.
그러나 이러한 조회는 네임 서버(name server)가 보고한 TTL (Time To Live) 정보가 캐시된 정보
에 따라 유용한 것으로 유지되고 있는 경우에만 캐시해야 한다.

HTTP 클라이언트가 성능 향상을 위해 호스트 이름 조회 결과를 캐시하였으면 DNS가 보고한
TTL 정보를 반드시 준수해야 한다.

HTTP 클라이언트가 이 원칙을 준수하지 않으면 이전에 접근한 서버의 IP 주소가 변경될 경우
속임을 당할 수 있다. 네트워크 주소 숫자의 변경이 점점 더 일반적인 것이 되고 있기 때문에
이러한 유형의 공격은 증가할 것이다. 이 필요 조건을 준수하는 것이 잠재적인 보안 취약성을
감소시켜 준다.

이 필요 조건은 또한 동일한 DNS 이름을 사용하는 중복된 서버의 클라이언트 행태의 load-
balancing을 향상시키며 그 전략을 사용하는 사이트에 접근했을 때 사용자가 실패를 경험할
가능성을 감소시켜 준다.

15.9 Location 헤더와 Spoofing(속이기)

단일 서버가 서로 신뢰하지 않는 복수의 조직을 지원하고 있다면 서버는 언급한 조직의 통제
하에서 생성되는 응답의 Location 및 Content-Location 헤더 값을 다른 조직이 권한이 없는 자
원을 무효화하려 시도하지 말도록 하기 위해 점검해야 한다.

16 감사의 말

이 규격은 첨가된 BNF 및 David H. Crocker 이 RFC 822에서 규정한 일반 구축법을(generic
constructs) 많이 사용하고 있다. 마찬가지로 Nathaniel Borenstein 와 Ned Freed의 MIME이 제공
하는 많은 규정을 재사용하였다. 우리는 이 규격에 MIME을 포함하여 HTTP와 인터넷 전자
우편 메시지 포맷과의 관계에 대한 이전의 혼란이 감소하리라 기대한다.

[Page 144]


HTTP 규약은 지난 4년간 비약적인 발전을 해 왔다. 이 규약은 크고 활동적인 개발자 공동체
의 혜택을 많이 받았으며 이 공동체가 HTTP 및 일반적인 World Wide Web의 성공에 대한 찬
사를 들어야 한다. Marc Andreessen, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks,
Jean-Francois Groff, Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob McCool, Lou Montulli,
Dave Raggett, Tony Sanders, Marc VanHeyningen 등에게 이 규약의 첫 측면을 규정하는 데 노력한
데 대하여 특별한 감사를 표한다.

이 문서는 HTTP-WG에 참가한 많은 사람들의 코멘트에서 많은 혜택을 받았다. 이전에 언급한
사람들 이외에 다음의 사람들이 이 규격에 공헌했다.

          Gary Adams   Albert Lunde
          Harald Tveit Alvestrand  John C. Mallery
          Keith Ball  Jean-Philippe Martin-Flatin
          Brian Behlendorf             Larry Masinter
          Paul Burchard                Mitra
          Maurizio Codogno             David Morris
          Mike Cowlishaw               Gavin Nicol
          Roman Czyborra               Bill Perry
          Michael A. Dolan             Jeffrey Perry
          David J. Fiander              Scott Powers
          Alan Freier                  Owen Rees
          Marc Hedlund                 Luigi Rizzo
          Greg Herlihy                 David Robinson
          Koen Holtman                 Marc Salomon
          Alex Hopmann                 Rich Salz
          Bob Jernigan                 Allan M. Schiffman
          Shel Kaphan                  Jim Seidman
          Rohit Khare                  Chuck Shotton
          John Klensin                 Eric W. Sink
          Martijn Koster                Simon E. Spero
          Alexei Kosut                 Richard N. Taylor
          David M. Kristol              Robert S. Thau
          Daniel LaLiberte              Bill (BearHeart) Weinman
          Ben Laurie                   Francois Yergeau
          Paul J. Leach                 Mary Ellen Zurko
          Daniel DuBois

이 규격의 대부분의 캐시 디자인에 관한 내용이나 프리젠테이션은 다음의 사람들이 준 제안
및 코멘트에 기초하였다. - Shel Kaphan, Paul Leach, Koen Holtman, David Morris, Larry Masinter.

[Page 145]


이 규격의 대부분의 영역에 관한 것은 처음 Ari Luotonen이 행한 연구에 기초하고 있으며
Steve Zilles로부터 추가적인 정보를 구했다.

Palo Alto의 "cave men"에게 감사한다. 당신은 당신이 누구인지 알고 있다.

Jim Gettys (이 문서의 현재 편집장) 은 이전 편집장인 Roy Fielding에게 특별히 감사하며 John
Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Alex Hopmann 및 Larry
Masinter에게 그들의 도움에 감사한다.

17 참고 문헌

   [1] Alvestrand, H., "Tags for the identification of languages", RFC
   1766, UNINETT, March 1995.

   [2] Anklesaria, F., McCahill, M., Lindner, P., Johnson, D., Torrey,
   D., and B. Alberti. "The Internet Gopher Protocol: (a distributed
   document search and retrieval protocol)", RFC 1436, University of
   Minnesota, March 1993.

   [3] Berners-Lee, T., "Universal Resource Identifiers in WWW", A
   Unifying Syntax for the Expression of Names and Addresses of Objects
   on the Network as used in the World-Wide Web", RFC 1630, CERN, June
   1994.

   [4] Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform Resource
   Locators (URL)", RFC 1738, CERN, Xerox PARC, University of Minnesota,
   December 1994.

   [5] Berners-Lee, T., and D. Connolly, "HyperText Markup Language
   Specification - 2.0", RFC 1866, MIT/LCS, November 1995.

   [6] Berners-Lee, T., Fielding, R., and H. Frystyk, "Hypertext
   Transfer Protocol -- HTTP/1.0.", RFC 1945 MIT/LCS, UC Irvine, May
   1996.

   [7] Freed, N., and N. Borenstein, "Multipurpose Internet Mail
   Extensions (MIME) Part One: Format of Internet Message Bodies", RFC
   2045, Innosoft, First Virtual, November 1996.

   [8] Braden, R., "Requirements for Internet hosts - application and
   support", STD 3,  RFC 1123, IETF, October 1989.

   [9] Crocker, D., "Standard for the Format of ARPA Internet Text
   Messages", STD 11, RFC 822, UDEL, August 1982.

[Page 146]


   [10] Davis, F., Kahle, B., Morris, H., Salem, J., Shen, T., Wang, R.,
   Sui, J., and M. Grinbaum. "WAIS Interface Protocol Prototype
   Functional Specification", (v1.5), Thinking Machines Corporation,
   April 1990.

   [11] Fielding, R., "Relative Uniform Resource Locators", RFC 1808, UC
   Irvine, June 1995.

   [12] Horton, M., and R. Adams. "Standard for interchange of USENET
   messages", RFC 1036, AT&T Bell Laboratories, Center for Seismic
   Studies, December 1987.

   [13] Kantor, B., and P. Lapsley. "Network News Transfer Protocol." A
   Proposed Standard for the Stream-Based Transmission of News", RFC
   977, UC San Diego, UC Berkeley, February 1986.

   [14] Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
   Three: Message Header Extensions for Non-ASCII Text", RFC 2047,
   University of Tennessee, November 1996.

   [15] Nebel, E., and L. Masinter. "Form-based File Upload in HTML",
   RFC 1867, Xerox Corporation, November 1995.

   [16] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821,
   USC/ISI, August 1982.

   [17] Postel, J., "Media Type Registration Procedure", RFC 2048,
   USC/ISI, November 1996.

   [18] Postel, J., and J. Reynolds, "File Transfer Protocol (FTP)", STD
   9, RFC 959, USC/ISI, October 1985.

   [19] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC
   1700, USC/ISI, October 1994.

   [20] Sollins, K., and L. Masinter, "Functional Requirements for
   Uniform Resource Names", RFC 1737, MIT/LCS, Xerox Corporation,
   December 1994.

   [21] US-ASCII. Coded Character Set - 7-Bit American Standard Code for
   Information Interchange. Standard ANSI X3.4-1986, ANSI, 1986.

   [22] ISO-8859. International Standard -- Information Processing --
     8-bit Single-Byte Coded Graphic Character Sets --
     Part 1: Latin alphabet No. 1, ISO 8859-1:1987.
     Part 2: Latin alphabet No. 2, ISO 8859-2, 1987.
     Part 3: Latin alphabet No. 3, ISO 8859-3, 1988.
     Part 4: Latin alphabet No. 4, ISO 8859-4, 1988.
[Page 147]


     Part 5: Latin/Cyrillic alphabet, ISO 8859-5, 1988.
     Part 6: Latin/Arabic alphabet, ISO 8859-6, 1987.
     Part 7: Latin/Greek alphabet, ISO 8859-7, 1987.
     Part 8: Latin/Hebrew alphabet, ISO 8859-8, 1988.
     Part 9: Latin alphabet No. 5, ISO 8859-9, 1990.

   [23] Meyers, J., and M. Rose "The Content-MD5 Header Field", RFC
   1864, Carnegie Mellon, Dover Beach Consulting, October, 1995.

   [24] Carpenter, B., and Y. Rekhter, "Renumbering Needs Work", RFC
   1900, IAB, February 1996.

   [25] Deutsch, P., "GZIP file format specification version 4.3." RFC
   1952, Aladdin Enterprises, May 1996.

   [26] Venkata N. Padmanabhan and Jeffrey C. Mogul. Improving HTTP
   Latency. Computer Networks and ISDN Systems, v. 28, pp. 25-35, Dec.
   1995.  Slightly revised version of paper in Proc. 2nd International
   WWW Conf. '94: Mosaic and the Web, Oct. 1994, which is available at
   http://www.ncsa.uiuc.edu/SDG/IT94/Proceedings/DDay/mogul/
   HTTPLatency.html.

   [27] Joe Touch, John Heidemann, and Katia Obraczka, "Analysis of HTTP
   Performance", http://www.isi.edu/lsam/ib/http-perf/>,
   USC/Information Sciences Institute, June 1996

   [28] Mills, D., "Network Time Protocol, Version 3, Specification,
   Implementation and Analysis", RFC 1305, University of Delaware, March
   1992.

   [29] Deutsch, P., "DEFLATE Compressed Data Format Specification
   version 1.3." RFC 1951, Aladdin Enterprises, May 1996.

   [30] Spero, S., "Analysis of HTTP Performance Problems"
   <URL:http://sunsite.unc.edu/mdma-release/http-prob.html>.

   [31] Deutsch, P., and J-L. Gailly, "ZLIB Compressed Data Format
   Specification version 3.3", RFC 1950, Aladdin Enterprises, Info-ZIP,
   May 1996.

   [32] Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
   Luotonen, A., Sink, E., and L. Stewart, "An Extension to HTTP :
   Digest Access Authentication", RFC 2069, January 1997.

[Page 148]


18 저자의 주소

   Roy T. Fielding
   Department of Information and Computer Science
   University of California
   Irvine, CA 92717-3425, USA

   Fax: +1 (714) 824-4056
   EMail: fielding@ics.uci.edu

   Jim Gettys
   MIT Laboratory for Computer Science
   545 Technology Square
   Cambridge, MA 02139, USA

   Fax: +1 (617) 258 8682
   EMail: jg@w3.org

   Jeffrey C. Mogul
   Western Research Laboratory
   Digital Equipment Corporation
   250 University Avenue
   Palo Alto, California, 94305, USA

   EMail: mogul@wrl.dec.com

   Henrik Frystyk Nielsen
   W3 Consortium
   MIT Laboratory for Computer Science
   545 Technology Square
   Cambridge, MA 02139, USA

   Fax: +1 (617) 258 8682
   EMail: frystyk@w3.org

   Tim Berners-Lee
   Director, W3 Consortium
   MIT Laboratory for Computer Science
   545 Technology Square
   Cambridge, MA 02139, USA

   Fax: +1 (617) 258 8682
   EMail: timbl@w3.org

[Page 149]


.19 부록

19.1 Internet Media Type message/http

HTTP/1.1 규약을 규정하는 것과 더불어 이 문서는 Internet media type "message/http"에 대한 규
격으로도 사용한다. 다음 사항을 IANA에 등록해야 한다.

       Media Type name:         message
       Media subtype name:       http
       Required parameters:      none
       Optional parameters:      version, msgtype

        version: 동봉된 메시지의 HTTP-Version 번호(예를 들어 1.1)
                가 없으면 버전은 본문의 첫 라인으로 결정한다.

        msgtype: 메시지 유형 - "요구" 또는 "응답". 표시되지 않았으면
                 유형은 본문의 첫 라인으로 결정한다.

       Encoding considerations: "7bit", "8bit", 또는 "binary" 만 허용된다.

       Security considerations: none

19.2 Internet Media Type multipart/byteranges

HTTP메시지가 복수 영역의 내용(예를 들어 복수의 중첩되지 않는 영역에 대한 요구의 응답)
을 포함하고 있을 때, 이것은 multipart MIME 메시지로서 전송된다. 이러한 목적의 multipart
media type을 "multipart/byteranges".라고 부른다.

Multipart/byteranges media type은 둘 또는 그 이상의 부분을 포함하며 각각 자신의 Content-Type
과 Content-Range 필드를 가진다. 이 부분들은 MIME 경계 파라미터(boundary parameter)를 이용
하여 구분한다.

          Media Type name:       multipart
          Media subtype name:      byteranges
          Required parameters:      boundary
          Optional parameters:      none

          Encoding considerations: "7bit", "8bit", 또는 "binary" 만 허용된다.

          Security considerations: none

[Page 150]


예를 들면,

   HTTP/1.1 206 Partial content
   Date: Wed, 15 Nov 1995 06:25:24 GMT
   Last-modified: Wed, 15 Nov 1995 04:58:08 GMT
   Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

   --THIS_STRING_SEPARATES
   Content-type: application/pdf
   Content-range: bytes 500-999/8000

   ...첫 영역...
   --THIS_STRING_SEPARATES
   Content-type: application/pdf
   Content-range: bytes 7000-7999/8000

   ...두 번째 영역
   --THIS_STRING_SEPARATES--

19.3 Tolerant Applications

이 문서가 HTTP/1.1 메시지를 생성하는 데 필요한 조건들을 명시하고 있지만 모든 애플리케이
션이 이것을 정확하게 구현하지는 않을 것이다. 따라서 우리는 실제적인 애플리케이션이 이러
한 이탈(deviations)이 명확하게 해석될 수 없을 때는 언제나 이탈에 대해 관대할 것을 추천한
다.

클라이언트는 Status-Line을 분석하는 데 관대하고 서버는 Request-Line을 분석하는 데 관대해
야 한다. 특히 둘 모두 필드 사이에 비록 단 하나의 SP만 필요하다 하더라도 SP 및 HT 문자
의 수에 관계없이 이를 수용하여야 한다.

Message-header의 라인 종결자는 연속적인 CRLF이다. 그러나 우리는 애플리케이션이 이러한
헤더를 분석할 때 단일 LF를 라인 종결자로 인식하고 앞에 있는 CR을 무시할 것을 추천한다.

Entity-body의 문자 집합은 해당 본문에 사용된 문자 집합의 최저 공동 명칭(lowest common
denominator)으로 라벨을 붙여야 하나 예외적으로 US-ASCII 또는 ISO-8859-1 라벨에는 아무 것
도 붙이지 않는 것이 좋다.

날짜의 분석과 인코딩 필요 조건에 관한 추가 규칙 및 날짜 인코딩과 관련된 다른 잠재적 문
제점은 다음과 같다.

? HTTP/1.1 클라이언트와 캐시는 향후 50년 이후 이상의 RFC-850 날짜는 사실상 과거의 날
짜라고 가정해야 한다.(이것이 "2000 년" 문제를 해결하는 데 도움을 준다.)
[Page 151]


? HTTP/1.1 구현 방식은 내부적으로 적절한 값보다 이전으로 분석된 Expires 날짜를 표시할
수는 있으나 절대로 적절한 값보다 이후 날짜를 표시해서는 안 된다.

? 유효일에 관련된 모든 계산은 GMT로 해야 한다. 지역적인 시간대는 경과 시간이나 유효
시간을 계산하거나 비교하는 데 영향을 미쳐서는 안 된다.

? HTTP 헤더가 부정확하게 GMT 이외의 시간 대 날짜 값을 가지고 있다면 가장 조심스러운
환산 방법을 사용하여 GMT로 변환하여야 한다.

19.4 HTTP 엔터티와 MIME 엔터티의 차이점

HTTP/1.1은 인터넷 메일(RFC 822) 및 다목적 인터넷 메일 확장(Multipurpose Internet Mail
Extensions (MIME ))을 위해 규정된 많은 구성물(construct)을 이용하여 엔터티가 공개된 다양한
표시 방식 및 확장 가능한 메커니즘을 통하여 전달될 수 있도록 한다. 그러나 MIME [7] 또한
전자 우편에 대해 논의하고 있으며 HTTP에는 MIME에서 기술된 것과 상이한 기능이 몇몇
있다. 이러한 차이점은 바이너리 접속의 성능을 최적화하고, 새로운 media type을 사용하는 최
대한의 자유를 허용하며, 날짜 비교를 용이하게 하며, 이전 HTTP 서버 및 클라이언트의 행태
를 인정할 수 있도록 주의 깊게 선택하였다.

이 부록은 HTTP와 MIME의 차이를 기술하고 있다. 프락시에서 엄격한 MIME 환경으로의 게
이트웨이는 이러한 차이점을 인식하고 필요하다면 적절한 변환을 해 주어야 한다. 프락시와
MIME 환경으로부터 HTTP로의 게이트웨이 또한 약간의 변환이 필요할 수 있으므로 이 차이
점을 인지할 필요가 있다.

19.4.1 규범적인 폼으로 변환

MIME은 인터넷 메일 엔터티를 전송되기 전에 규범적인 폼(canonical form)으로 변환할 것을
요구한다. 이 문서의 3.7.1절은 HTTP로 전송될 때 폼에 사용할 수 있는 "text" media type의
subtype을 기술하고 있다. MIME에서 텍스트 유형의 내용은 줄바꿈을 CRLF로 표시해야 하고
줄바꿈 이외는 CR 또는 LF를 사용하지 말아야 한다. HTTP는 메시지가 HTTP를 통하여 전달
될 때 텍스트 내용 안에서 줄 바꿈을 표시하기 위해 CRLF, 단일 CR 및 LF를 허용한다.

가능하다면 프락시에서 엄격한 MIME 환경으로의 게이트웨이는 3.7.1절에서 기술한 text media
type 내의 모든 줄바꿈을 CRLF의 MIME 정규 폼으로 해석해야 한다. 그러나 Content-Encoding
이 있으면 이 해석이 복잡해질 수 있으며 또한 HTTP가 multi-byte 문자 집합의 경우처럼
octets 13 및 10을 CR 및 LF를 표시하는데 사용하지 않는 다른 문자 조합을 허용한다는 사실
때문에 복잡해질 수 있다.

[Page 152]


19.4.2 날짜 형식의 변환

HTTP/1.1은 한정된 날자 포맷(3.3.1)을 사용하여 날짜 비교 과정을 단순화시켜 준다.  프락시
에서 다른 규약의 게이트웨이는 확실하게 HTTP/1.1 포맷 중 하나를 따르는 메시지에 Date 헤
더 필드가 있고 필요하다면 날짜를 재기입하도록 해야 한다.

19.4.3 Content-Encoding 소개

MIME은 HTTP/1.1의 Content-Encoding 헤더 필드와 동등한 개념을 아무것도 포함하고 있지
않다. 이것이 media type에 변경자로서 작동하기 때문에 HTTP에서 MIME을 준수하는 규약으
로의 프락시나 게이트웨이는 반드시 Content-Encoding 헤더 필드의 값을 변경하거나 메시지를
전달하기 전에 entity-body를 해독해야 한다. (인터넷 메일을 위한 몇몇 실험적인 응용프로그램
은 media type 파라미터 ";conversions="를 Content-Encoding과 동등한 기능 수행
을 위해 사용한다. 그러나 이 파라미터는 MIME의 일부분이 아니다.)

19.4.4 No Content-Transfer-Encoding

HTTP는 MIME의 Content-Transfer-Encoding (CTE) 필드를 사용하지 않는다. HTTP에서 MIME
을 준수하는 규약으로의 프락시나 게이트웨이는 응답 메시지를 HTTP 클라이언트에게 배달하
기 전에 반드시 모든 non-identity CTE ("quoted-printable" 또는 "base64") 인코딩을 제거해야 한다.

HTTP에서 MIME을 준수하는 규약으로의 프락시나 게이트웨이는 메시지가 해당 규약에서 안
전하게 전송될 수 있도록, 또한 정확한 포맷과 인코딩이 되도록 확실하게 해야 한다. 여기서 "
안전한 전송"은 사용되고 있는 규약의 제한 사항에 의해 규정된다. 이러한 프락시나 게이트웨
이는 그렇게 하는 것이 목적지 규약으로 안전하게 전송할 가능성을 높여준다면 데이타에 적절
한 Content-Transfer-Encoding 라벨을 붙어야 한다.

19.4.5 Multipart Body-Part의 HTTP 헤더 필드

MIME에서 multipart body-parts의 거의 모든 헤더 필드는 필드 이름이 "Content-"로 시작하지
않는 한 보통 무시된다. HTTP/1.1에서는 multipart body-parts가 해당 부분의 의미에 상당히 중
요한 HTTP 헤더 필드를 포함할 수 있다.

[Page 153]


19.4.6 Transfer-Encoding 소개

HTTP/1.1은 Transfer-Encoding 헤더 필드(14.40 절)를 소개하고 있다. HTTP/1.1은 프락시/게이트
웨이가 MIME을 준수하는 규약을 통하여 메시지를 전달하기 전에 모든 전송 코딩을 제거해야
만 한다는 점을 소개하고 있다.

덩어리 전송 코딩(3.6 절)을 해독하는 절차를 다음과 같이 유사 코드(pseudo-code) 형식으로 표
현할 수 있다.

          length := 0
          read chunk-size, chunk-ext (if any) and CRLF
          while (chunk-size > 0) {
             read chunk-data and CRLF
             append chunk-data to entity-body
             length := length + chunk-size
             read chunk-size and CRLF
          }
          read entity-header
          while (entity-header not empty) {
             append entity-header to existing header fields
             read entity-header
          }
          Content-Length := length
          Remove "chunked" from Transfer-Encoding

19.4.7 MIME-Version

HTTP는 MIME을 준수하는 규약이 아니다.(부록 19.4 절 참조). 그러나 HTTP/1.1 메시지는 단
일 MIME-Version general-header 필드를 포함하여 메시지를 생성하기 위하여 어떤 MIME 규약
버전을 사용했는지 표시할 수 있다. MIME-Version 헤더 필드의 사용은 메시지가 MIME 규약에
전적으로 따르고 있다는 것을 표시한다. 프락시/게이트웨이는 HTTP 메시지를 엄격한 MIME
환경으로 전송할 때 완전한 규약 준수(가능 하다면)를 확실하게 할 책임이 있다.

          MIME-Version   = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT

MIME 버전 "1.0"이 HTTP/1.1에서 사용할 때 기본 값이다. 그러나 HTTP/1.1 메시지 분석 및
의미는 MIME 규격이 아닌 이 문서에 규정되어 있다.

19.5 HTTP/1.0 이후 변경 사항

이 절에서 HTTP/1.0과 HTTP/1.1 사이의 주요 차이점을 요약하였다.

[Page 154]


19.5.1 복수의 홈을 가진 웹 서버를 단순하게 하기 위한 변경 사항 및 IP 주소 보존

클라이언트와 서버가 Host request-header를 지원해야 한다는 요구 조건 때문에 Host request-
header(14.23절)가 빠졌으면 에러를 발생시킨다. 또한 절대 URI(5.1.2 절)는 이 규격이 규정한
변경 사항 중 가장 중요한 것이다.

이전 HTTP/1.0 클라이언트는 IP 주소와 서버의 일대일 관계(one-to-one relationship)를 가정했다.
요구를 발송하고자 하는 서버와 요구가 발송된 IP 주소를 구별할 확립된 메커니즘이 없었다.
위에 대략적으로 설명한 변경 사항은 인터넷이, 단일 호스트에 복수의 IP 주소를 할당하는 것
이 심각한 문제를 발생시켰던 이전 HTTP 클라이언트가 더 이상 보편적인 것이 아닐 때, 단일
IP 주소가 복수의 웹 사이트를 지원하여 대량의 웹 서버 운영을 단순하게 할 것이다. 인터넷
은 또한 단지 루트 수준 HTTP URl에 사용할 특수 용도의 도메인 이름을 사용할 목적으로 할
당되었던 IP 주소를 복구할 수 있게 될 것이다. 웹의 성장 속도 및 이미 배치된 서버의 숫자
를 감안할 때 HTTP의 모든 구현 방식(기존 HTTP/1.0 애플리케이션 갱신을 포함하여)이 다음
의 필요 조건을 정확하게 구현하는 것이 매우 중요하다.

? 클라이언트와 서버 모드 반드시 Host request-header를 지원해야 한다.

? HTTP/1.1 요구에는 반드시 Host request-header를 사용해야 한다.

? HTTP/1.1 요구가 Host request-header를 포함하고 있지 않으면 반드시 에러 메시지400
(Bad Request)을 발생시켜야 한다.

? 서버는 반드시 절대 URI를 수용해야 한다.

[Page 155]


19.6 추가 기능

이 부록은 기존 HTTP 구현 방식이 사용하고 있는 규약 요소를 문서화하고 있지만 대부분의
HTTP/1.1 애플리케이션 전반에 걸쳐 일관성 있고 정확한 것은 아니다. 구현자가 이러한 기능
을 인지해야 하지만 다른 HTTP/1.1 애플리케이션 내에서의 이러한 기능의 존재나 상호 운영성
(interoperability)에 의존할 수는 없다. 이것들 중 몇몇은 제안된 실험적 기능을 기술하고 있으
며 다른 것들은 현재 기본 HTTP/1.1 규격에 언급되었지만 실험적으로 배포했을 때 부족한 것
으로 발견된 기능을 기술하고 있다.

19.6.1 추가적인 요구 method

19.6.1.1 PATCH

PATCH method 는 엔터티가 Request-URI가 식별한 자원의 원래 버전과 PATCH 작업을 적용했
을 때 희망하는 자원의 차이점 목록을 포함하고 있다는 것을 제외하고는 PUT과 유사하다. 차
이점 목록은 엔터티의 media type(예를 들어 "application/diff")에서 규정한 포맷이며 서버가 자
원의 원래 버전을 희망하는 버전으로 변화하는 데 필요한 변경 사항을 재생성할 수 있도록 하
는 충분한 정보를 반드시 포함해야 한다.

요구가 캐시를 통과하거나 Request-URI가 현재 캐시된 엔터티를 식별하면 해당 엔터티는 반드
시 캐시에서 삭제해야 한다. 이 method에 대한 응답을 캐시할 수 없다.

패치한 자원을 배치하는 방법 및 선행자에 미치는 영향에 대한 실제적인 method는 전적으로
원서버가 규정한다. 만약 패치하고 있는 자원의 원래 버전이 Content-Version 헤더 필드를 포함
하고 있다면 요구 엔터티는 반드시 원래 Content-Version 헤더 필드에 상응하는 Derived-From
헤더 필드를 포함해야 한다. 애플리케이션은 이러한 필드를 버전 부여 관계 및 버전 충돌을
해결하는 데 사용하도록 추천한다.

PATCH 요구는 8.2절에서 설정한 메시지 전송 필요 조건에 따라야 한다.

PATCH를 구현하는 캐시는 13.10 절 PUT에서 규정한 대로 캐시된 응답을 무효화해야 한다.

19.6.1.2 LINK

LINK method 는 Request-URI가 식별하는 기존 자원과 다른 기존 자원의 하나 또는 그 이상의
Link 관계를 확립한다.

[Page 156]


LINK와 자원 사이의 링크를 설정할 수 있도록 하는 다른 method와의 차이점은 LINK method
는 어떠한 message-body도 요구와 함께 발송하지 못하도록 한다는 것과 직접적으로 새로운 자
원을 생성하지 않는다는 것이다.

요구가 캐시를 통과하거나 Request-URI가 현재 캐시된 엔터티를 식별하면 해당 엔터티는 반드
시 캐시에서 삭제해야 한다. 이 method에 대한 응답을 캐시할 수 없다.

LINK를 구현하는 캐시는 13.10 절 PUT에서 규정한 대로 캐시된 응답을 무효화해야 한다.

19.6.1.3 UNLINK

UNLINK method 는 Request-URI가 식별하는 기존 자원과 다른 기존 자원의 하나 또는 그 이
상의 Link 관계를 삭제한다. 이러한 관계는 LINK를 이용하거나 Link 헤더를 지원하는 다른
method에 의하여 확립되었을 수 있다. 자원에 대한 링크를 삭제하는 것은 자원이 더 이상 존
재하지 않는다거나 향후 참조를 위해 접근할 수 없다는 것을 의미하는 것은 아니다.

요구가 캐시를 통과하거나 Request-URI가 현재 캐시된 엔터티를 식별하면 해당 엔터티는 반드
시 캐시에서 삭제해야 한다. 이 method에 대한 응답을 캐시할 수 없다.

UNLINK를 구현하는 캐시는 13.10 절 PUT에서 규정한 대로 캐시된 응답을 무효화해야 한다.

19.6.2 Additional Header Field Definitions

19.6.2.1 Alternates

Alternates response-header 필드를 원서버가 클라이언트에게 요구 받은 자원을 표시할 수 있는
다른 방식을 각각의 독특한 속성과 함께 알려 주는 수단으로 제의하였다. 이렇게 하여 사용자
에이전트가 사용자의 희망 사항에 더 적합한(12장에서 에이전트가 주도하는 협상(agent-driven
negotiation)으로 기술되었다.) 다른 표시 방식을 계속적으로 선택할 수 있는 신뢰할 수 있는 방
안을 제공한다.

[Page 157]


Alternates 헤더 필드는 응답의 해석이나 사용할 수 있는 표시 방법에 영향을 미치지 않고 메
시지에 둘 다 존재할 수 있다는 점에서 Vary 헤더 필드와 직교하고 있다. Alternates가 Vary 필
드가 제공하는 유형 및 언어와 같이 공동 차원(common dimensions)에 걸쳐 변형될 수 있는 자
원에 관한 서버 주도 협상(server-driven negotiation)에 대해 상당한 개선을 할 수 있을 것으로
기대되고 있다.

Alternates 헤더 필드는 향후 규격에서 규정될 예정이다.

19.6.2.2 Content-Version

Content-Version entity-header 필드는 진행되고 있는 엔터티의 해석에 관련된 버전 태그를 규정
한다. 19.6.2.3 절에서 기술한 Derived-From 필드와 더불어 이것은 사람들이 작업을 반복적인 절
차로 동시에 진행할 수 있도록 한다. 이 필드는 특정 작업의 진행이 파생된 작업이나 다른 표
현 방법에 의한 해석이 아닌 단일 경로를 따를 수 있도록 하는 데 사용한다.


          Content-Version = "Content-Version" ":" quoted-string

Content-Version 필드의 사용 예는 다음과 같다.

           Content-Version: "2.1.2"
           Content-Version: "Fred 19950116-12:26:48"
           Content-Version: "2.5a4-omega7"

19.6.2.3 Derived-From

Derived-From entity-header 필드는 발송측이 변경하기 전 상태에서 엔터티가 파생된 자원의 버
전 태그를 표시하기 위해 사용한다. 이 필드는 또한 자원에 대한 계속적인 변경을, 특히 이러
한 변경이 복수의 자원과 병행하여 이루어 질 때 혼합하는 과정을 관리할 수 있도록 한다.

          Derived-From   = "Derived-From" ":" quoted-string

이 필드의 사용 예는,

          Derived-From: "2.1.1"

PUT 및 PATCH 요구에는 발송되는 엔터티가 이전에 동일한 URI에서 조회된 것이고 마지막
으로 조회했을 때 Content-Version 헤더를 포함하고 있었다면 Derived-From 필드가 필요하다.

 [Page 158]


19.6.2.4 Link

Link entity-header 필드는 보통 요구 받은 자원과 다른 자원과의 관계인 두 자원과의 관계를 기
술하는 수단을 제공한다. 엔터티는 복수의 Link 값을 포함할 수 있다. 메타 정보 수준의 링크
는 대개 계서적 구조나 항해 경로(navigation paths)와 같은 관계를 표시한다. Link 필드는 의미
상 HTML.[5]의 요소와 동등하다.

          Link            = "Link" ":" #("<" URI ">" *( ";" link-param )

          link-param      = ( ( "rel" "=" relationship )
                             | ( "rev" "=" relationship )
                             | ( "title" "=" quoted-string )
                             | ( "anchor" "=" <"> URI <"> )
                             | ( link-extension ) )

          link-extension   = token [ "=" ( token | quoted-string ) ]

          relationship     = sgml-name
                          | ( <"> sgml-name *( SP sgml-name) <"> )

          sgml-name      = ALPHA *( ALPHA | DIGIT | "." | "-" )

관계 값은 대소문자를 구별하며 sgml-name 구문법의 제한 사항 내에서 확장될 수 있다. "title"
파라미터는 링크의 목적지를 표시하는 데 사용하여 사람이 읽을 수 있는 메뉴에서 식별자로
사용할 수 있다. 앵커 파라미터(anchor parameter)는 이 자원 또는 제 삼의 자원의 한 단편과 같
이 현재의 전체 자원이 아닌 소스 앵커(source anchor)를 표시하는 데 사용한다.

사용 예를 보면,

       Link: <http://www.cern.ch/TheBook/chapter2>; rel="Previous"

       Link: <mailto:timbl@w3.org>; rev="Made"; title="Tim Berners-Lee"

첫 번째 예는 chapter2가 논리적 운항 경로에서 이 자원의 이전 것임을 표시한다. 두  번째 예
는 자원을 사용할 수 있도록 만드는 책임을 진 사람을 주어진 전자우편 주소로 식별한다는 것
을 표시한다.

19.6.2.5 URI

이 규격의 이전 버전에서 URI 헤더 필드는 기존 Location, Content-Location, Vary 헤더 필드 및
향후 Alternates의 결합체로 사용했었다.

[Page 159]


이 필드의 주요 목적은 이름 및 미러 위치(name and mirror location)를 포함하는 자원의 추가
URI 목록을 포함하는 것이었다. 그러나 이 단일 필드 내에 많은 별도의 기능을 결합하는 것은
이러한 기능을 일관성 있고 정확하게 구현하는 데 장애물이 되고 있다는 것이 명백해졌다. 더
더욱 우리는 이름 및 미러 위치의 식별은 Link 헤더 필드를 통하여 더 잘 수행할 수 있다고
믿는다. 따라서 URI 헤더 필드는 그러한 필드를 선호하여 경시되고 있다.


          URI-header    = "URI" ":" 1#( "<" URI ">" )

19.7 추가 헤더 필드 정의

이전 버전에 따르도록 강제하는 것은 규약 규격의 범위를 벗어나는 것이다. 그러나 HTTP/1.1
은 이전 버전을 쉽게 지원하도록 정교하게 디자인 되었다. 이 규격을 작성하는 순간 우리는
상업적 HTTP/1.1 서버가 다음 사항을 수행할 것으로 기대하고 있음에 주의하기 바란다.

? HTTP/0.9, 1.0, 또는 1.1 요구의 Request-Line 포맷을 인식한다.


? HTTP/0.9, 1.0, 또는 1.1 포맷으로 된 어떠한 요구도 이해한다.

? 클라이언트가 사용하는 주요 버전에서 적절하게 메시지에 응답한다.

또한 우리는 HTTP/1.1 클라이언트가 다음을 수행하기를 기대한다.

? HTTP/1.0 및 1.1 응답의 Status-Line 포맷을 인지한다.

? HTTP/0.9, 1.0, 또는 1.1 포맷으로 된 어떠한 요구도 이해한다.
 

대부분의 HTTP/1.0 구현 방식은 각각의 연결은 요구가 발생되기 이전에 클라이언트가 설정하
며 응답을 발송한 후 서버가 종료한다. 소수의 구현 방식은 19.7.1.1에서 기술한 Keep-Alive 지
속적 접속의 버전을 구현한다.

[Page 160]


19.7.1 HTTP/1.0 지속적인 연결과의 호환성

몇몇 클라이언트 및 서버는 이전 HTTP/1.0 클라이언트 및 서버의 지속적 연결과 호환성 유지
를 원할 수 있다. HTTP/1.0의 지속적 연결은 이것이 기본 행태가 아니기 때문에 반드시 명백
하게 협상해야 한다. HTTP/1.0 지속적 접속의 실험적 구현 방법은 잘못이었으며 HTTP/1.1은
이러한 문제를 인증하도록 디자인 되었다. 문제는 몇몇 기존 1.0 클라이언트가 Keep-Alive를
Connection을 이해하지 못하는 프락시 서버에 발송한다는 것이었다. Keep-Alive를 발송한 후
이것을 다음의 내부를 향한 서버(inbound server)에 실수도 전달하여 Keep-Alive 연결을 설정하
고 HTTP/1.0 프락시가 응답의 종료를 무한정 기다리는 결과를 초래하였다. 결과는 HTTP/1.0
클라이언트가 프락시와 통신할 때 Keep-Alive를 사용하지 못하도록 하는 것이었다.

그러나 프락시와의 통신은 지속적인 접속의 가장 중요한 용도였기 때문에 이러한 금지 사항은
명백하게 수용할 수 없는 것이었다. 따라서 우리는 Connection을 무시하는 이전 프락시와 통
신할 때도 사용하기에 안전한 지속적인 접속을 바란다는 것을 표시하는 다른 메커니즘이 필요
하다. 지속적인 연결(persistent connection)은 HTTP/1.1 메시지의 기본 값이다. 우리는 지속적이
지 않은 연결을 위해 새로운 핵심어(Connection: close)를 소개한다.

다음은 원래의 HTTP/1.0 형식 지속적 접속을 기술하고 있다.

원서버와 연결되었을 때 HTTP 클라이언트는 Persist connection-token에 추가하여 Keep-Alive
connection-token을 발송할 수도 있다.

          Connection: Keep-Alive

그러면 HTTP/1.0 서버가 Keep-Alive connection token으로 응답하고 클라이언트는 HTTP/1.0 (또
는 Keep-Alive) persistent connection으로 계속 진행할 것이다.

또한 HTTP/1.1 서버는 Keep-Alive connection token을 수신하자마자 HTTP/1.0 클라이언트와의
지속적인 접속을 확립할 수 있다. 그러나 HTTP/1.0 클라이언트와의 지속적인 접속에는 덩어리
전송 코딩(chunked transfer-coding)을 활용할 수 없기 때문에 각 메시지의 종료 경계(ending
boundary)를 표시하기 위해서는 반드시 Content-Length를 이용하여 표시를 해야 한다.

클라이언트는 HTTP/1.0 프락시 서버가 Connection 헤더 필드를 분석하기 위한 HTTP/1.1 원칙
을 따르지 않기 때문에 Keep-Alive connection token을 프락시 서버에 발송하지 말아야 한다.

[Page 161]


19.7.1.1 The Keep-Alive Header

요구나 응답에 Keep-Alive connection-token 이 전송되었으면 Keep-Alive 헤더 필드가 포함될 수
있다. Keep-Alive 헤더 필드는 다음의 형식을 취한다.

          Keep-Alive-header = "Keep-Alive" ":" 0# keepalive-param

          keepalive-param = param-name "=" value

Keep-Alive 헤더 자체는 선택 사항이며 파라미터가 발송되었을 때만 사용된다. HTTP/1.1은 어
떠한 파라미터도 규정하지 않고 있다.

Keep-Alive가 발송되었으면 상응하는 연결 토큰(corresponding connection token)도 반드시 전송되
어야 한다. 연결 토큰 없이 수신되었으면 Keep-Alive 헤더를 무시해야 한다.

반응형
visual studio 2005  단축키 포스터 입니다.

+ Recent posts