HTTP 완벽 가이드 1부 - HTTP: 웹의 기초

Updated:

HTTP 완벽 가이드 시리즈를 정리한 내용입니다.

1장 HTTP 개관

1.2 웹 클라이언트와 서버

  • 웹 서버는 HTTP 프로토콜로 의사소통하기 때문에 보통 HTTP 서버라고 불린다.
  • 클라이언트가 웹브라우저를 통해 HTTP요청을 서버로 보내면, 서버는 요청받은 객체를 찾고 HTTP응답에 실어서 클라이언트에게 보낸다.

1.3 리소스

  • 텍스트파일, HTML파일, JPEG 이미지 파일 과 같은 정적 파일 뿐 아니라 요청에 따라 콘텐츠를 생산하는 프로그램(동적 콘텐츠 리소스) 까지 모두 리소스가 될 수 있다.

1.3.1 미디어 타입

Content-type: image/jpeg
└MIME타입

  • HTTP는 웹에서 전송되는 객체 각각에 MIME 타입이라는 데이터 포맷 라벨을 붙인다.
  • 웹 브라우저는 서버로부터 객체를 받았을 때 MIME타입을 통해 다룰 수 있는지 확인한다.
  • MIME타입은 사선(/)으로 구분된 주 타입과 부 타입으로 이루어진 문자열 라벨이다.

HTML : text/html
plain ASCII : text/plain
JPEG : image/jpeg
GIF : image/gif

1.3.2 URI

  • 서버 리소스 이름은 URI(uniform resource identifier, 통합 자원 식별자) 라고 불린다.

    http://www.joes-hardware.com/specials/saw-blade.gif

  • URL, URN으로 세분화할 수 있다.

1.3.3 URL

  • 특정 서버의 한 리소스에 대한 구체적인 위치를 서술한다.

    http://www.joes-hardware.com/specials/saw-blade.gif

  • 위 URL의 경우 스킴(http://)과 주소(www.joes-hardware.com), 리소스(/specials/saw-blade.gif)로 나눌 수 있다.
  • 오늘날의 대부분의 URI는 URL이다.

1.3.4 URN

  • 콘텐츠를 이루는 한 리소스에 대해, 그 리소스의 위치에 영향 받지 않는 유일무이한 이름 역할을 한다.
  • 리소스의 위치가 변하더라도 영향을 받지 않는다.
  • 아직 인프라의 부재로 인해 널리 채택되지 못했다.

1.4 트랜잭션

  • HTTP 트랜잭션은 요청 명령과 응답 결과로 구성되어 있다.

1.4.1 메서드

  • HTTP는 HTTP 메서드라고 불리는 여러가지 종류의 요청 명령을 지원하며, 요청 메세지는 한개의 메서드를 갖는다.
HTTP 메서드 설명
GET 서버에서 클라이언트로 지정한 리소스를 보내라.
PUT 클라이언트에서 서버로 보낸 데이터를 지정한 이름의 리소스로 저장하라.
DELETE 지정한 리소스를 서버에서 삭제하라.
POST 클라이언트 데이터를 서버 게이트웨이 애플리케이션으로 보내라.
HEAD 지정한 리소스에 대한 응답에서, HTTP 헤더 부분만 보내라.

1.4.2 상태코드

  • HTTP 응답 메세지는 상태 코드를 포함한다.
  • 세자리 숫자와 사유 구절로 이루어진다.

1.5 메세지

  • 요청 메세지 : 클라이언트 -> 서버
GET /test/hi-there.txt HTTP/1.0    시작줄
-------------------------------
Accept: text/*                     헤더
Accept-Language: en,fr
  • 응답 메세지 : 서버 -> 클라이언트
HTTP/1.0 200 OK                    시작줄
------------------------------
Content-type: text/plain           헤더
Content-length: 19

------------------------------
Hi! I'm a message !                본문
  • 시작줄 : 요청이라면 무엇을 해야하는지, 응답이라면 무슨 일이 일어났는지 표기
  • 헤더 : 0개 이상의 헤더 필드로 구성. 각 헤더 필드는 :으로 구분되어 하나의 이름과 하나의 값으로 구성. 빈줄로 헤더가 끝났음을 표시.
  • 본문 : 모든 종류의 데이터가 포함될 수 있다.

1.6 TCP 커넥션

1.6.1 TCP/IP

  • HTTP는 애플리케이션 계층 프로토콜이므로 네트워크 통신의 핵심적인 세부사항에 대해서는 신경쓰지 않는다.
  • TCP/IP는 다음 기능들을 통하여 이를 대신한다.
    • 오류 없는 데이터 전송
    • 순서에 맞는 전달 (데이터는 언제나 보낸 순서대로 도착)
    • 조각나지 않는 데이터 스트림 (언제든 어떤 크기로든 보낼 수 있음)
  • TCP/IP : TCP와 IP가 층을 이루는, 패킷 교환 네트워크 프로토콜의 집합
  • HTTP > TCP > IP 의 계층구조

1.6.2 접속, IP 주소 그리고 포트번호

  • 클라이언트와 서버가 메세지를 주고받기 위해서는 IP주소와 포트번호를 사용해 TCP/IP 커넥션을 맺어야 한다.
  • 통신 과정
    • a. 웹브라우저는 서버의 URL에서 호스트 명을 추출
    • b. 웹브라우저는 서버의 호스트 명을 IP로 변환(DNS)
    • c. 웹브라우저는 URL에서 포트번호를 추출(없을 시 http는 80, https는 443)
    • d. 웹브라우저는 웹 서버와 TCP 커넥션을 맺음(3-way handshake)
    • e. 웹브라우저는 서버에 HTTP 요청을 보냄
    • f. 서버는 웹브라우저에 HTTP 응답을 돌려줌
    • g. 커넥션이 닫히면, 웹브라우저는 문서를 보여줌




2장 URL과 리소스

2.2 URL 문법

  • 대부분의 URL 문법은 일반적으로 9개 부분으로 나뉜다.
    <스킴>://<사용자 이름="">:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터>?<질의>#<프래그먼트>
컴포넌트 설명 기본값
스킴 리소스를 가져오려면 어떤 프로토콜을 사용하여 서버에 접근해야 하는지 가리킴 없음
사용자 이름 몇몇 스킴은 리소스에 접근을 하기 위해 사용자 이름을 필요로 함 anonymous
비밀번호 사용자의 비밀번호를 가리키며, 사용자 이름에 콜론(:)으로 이어서 기술한다. <이메일 주소="">
호스트 리소스를 호스팅하는 서버의 호스트 명이나 IP 주소 없음
포트 리소스를 호스팅하는 서버가 열어놓은 포트번호. 많은 스킴이 기본 포트를 가지고 있다. 스킴에 따라 다름
경로 이전 컴포넌트와 빗금(/)으로 구분되어 있으며, 서버 내 리소스가 서버 어디에 있는지를 가리킨다. 경로 컴포넌트의 문법은 서버와 스킴에 따라 다르다. 없음
파라미터 특정 스킴들에서 입력 파라미터를 기술하는 용도로 사용한다. 파라미터는 이름/값을 쌍으로 가진다. 파라미터는, 다른 파라미터나 경로의 일부와 세미콜론(;)으로 구분하여 기술하며, 여러개를 가질 수 있다. 없음
질의 스킴에서 애플리케이션에 파라미터를 전달하는데 쓰인다. 질의 컴포넌트를 작성하는데 쓰이는 공통 포맷은 없다. 이는 URL의 끝에 “?”로 구분한다. 없음
프래그먼트 리소스의 조각이나 일부분을 가리키는 이름이다. URL이 특정 객체를 가리킬 경우에 프래그먼트 필드는 서버에 전달되지 안흔ㄴ다. 이는 클라이언트에서만 사용한다. URL의 끝에서 “#”문자로 구분한다. 없음

2.2.1 스킴 : 사용할 프로토콜

  • 주어진 리소스에 어떻게 접근할지 나타냄
  • 알파벳으로 시작해야 하고 나머지 부분들과 첫번째 “:”로 구분하며 대소문자를 구분하지 않는다.

2.2.2 호스트와 포트

  • 리소스를 호스팅하고 있는 장비와 그 장비 내에서 리소스에 접근할 수 있는 서버가 어디인지를 가리킨다.
  • 호스트 컴포넌트는 접근하려고 하는 리소스를 가지고 있는 인터넷상의 호스트 장비를 가리킨다.
    • 호스트 명이 될 수도 있고, IP주소가 될 수도 있다.
  • 포트 컴포넌트는 서버가 열어놓은 네트워크 포트를 가리킨다.

2.2.3 사용자 이름과 비밀번호

  • FTP 서버 등에서는 데이터에 접근을 허용하기 전에 사용자 이름과 비밀번호를 요구한다.

2.2.4 경로

  • URL의 경로 컴포넌트는 리소스가 서버의 어디에 있는지 표기한다.
  • 유닉스 파일 시스템의 파일 경로와 유사하게 ‘/’문자를 기준으로 경로 조각으로 나뉜다.

2.2.5 파라미터

  • 많은 프로토콜은 리소스에 접근하기 위해 사용자 이름과 비밀번호 뿐 아니라 더 많은 정보를 요구한다.
  • 파라미터 컴포넌트는 애플리케이션이 서버에 정확한 요청을 하기 위해 필요한 입력 파라미터를 받는데 사용한다.
  • 이름/값 쌍의 리스트들로 ‘;’문자로 구분하여 기술한다.

2.2.6 질의 문자열

  • 데이터베이스 같은 서버들은 요청받을 리소스 형식의 범위를 좁히기 위해서 질문이나 질의를 받을 수 있다.

    http://www.joes-hardware.com/inventory-check.cgi?item=12731&color=blue&size=large

  • 위 질의는 제푸번호가 12731이고, 큰 치수에, 파란색인 물품의 재고가 있는지 검사한다.

2.2.7 프래그먼트

  • 프래그먼트 컴포넌트를 통해 리소스 내의 조각을 가리킬 수 있다.
  • 일반적으로 HTTP 서버는 객체 일부가 아닌 전체만 다루기 때문에, 클라이언트는 서버에 프래그먼트를 전달하지 않고 브라우저가 서버로부터 전체 리소스를 내려받은 후 프래그먼트를 사용하여 리소스의 일부를 보여준다.

2.3 단축 URL

2.3.1 상대 URL

./hammers.html

  • 절대 URL과 달리 상대 URL은 모든 정보를 담고 있지 않다.
  • 리소스에 접근하기 위해 필요한 모든 정보를 얻기 위해서는 기저라고 하는 다른 URL을 사용해야 한다.
  • 상대 URL을 사용하면 리소스 집합을 쉽게 변경할 수 있다.
  • 문서 집합의 위치를 변경하더라도, 새로운 기저 URL에 의해 해석되므로 정상적으로 동작한다.

2.3.2 URL 확장

  • 호스트 명 확장
    • 단순한 휴리스틱만을 사용해서 입력한 호스트 명을 전체 호스트 명으로 확장한다.
    • 주소란에 yahoo를 입력하면 브라우저는 자동으로 www..com을 붙여 www.yahoo.com을 만든다.
    • 사용자의 시간을 절약하고 혼란을 막는다.
  • 히스토리 확장
    • 브라우저는 과거에 사용자가 방문했던 URL의 기록을 저장한다.
    • URL을 입력하면 입력된 URL의 앞 글자들을 포함하는 완결된 형태의 URL들을 선택하게 해준다.

2.4 안전하지 않은 문자

  • 안전한 전송이란 정보가 유실될 위험 없이 URL을 전송할 수 있다는 것을 의미한다.
  • URL은 상대적으로 작고 일반적으로 안전한 알파벳 문자만 포함하도록 허락한다.
  • 사람들이 URL에 이진 데이터나 일반적으로 안전한 알파벳 외에 문자도 포함하려고 할 때가 있다는 것을 알고 이스케이프 기능을 추가하여 안전하지 않은 문자를 안전한 문자로 인코딩할 수 있게 했다.

2.4.1 URL 문자 집합

  • 많은 애플리케이션이 7비트로 이루어진 US-ASCII 문자 집합을 사용하나, 이는 굉장히 적은 문자만 포함한다(영어).
  • 뿐 아니라 URL이 특정 이진 데이터를 포함해야 하는 경우도 있으므로 설계자들은 URL에 이스케이프 문자열을 쓸 수 있도록 설계했다.

2.4.2 인코딩 체계

  • 몇몇 안전하지 않은 문자들을 표현할 수 있는 인코딩 방식을 고안했다.
  • 안전하지 않은 문자를 퍼센티지 기호로 시작해 두개의 16진수 숫자로 이루어진 이스케이프문자로 바꾼다.
문자 ASCII 코드 URL 예
~ 126 (0x7E) http://www.joes-hardware.com/%7Ejoe
빈 문자 32 (0x20) http://www.joes-hardware.com/more%20tools.html
% 37 (0x25) http://www.joes-hardware.com/100%25satisfaction.html

2.4.3 문자 제한

  • 몇몇 문자는 URL 내에서 특별한 의미로 사용되고, US-ASCII의 출력 가능한 문자 집합에 포함되어 있지 않고, 몇몇 인터넷 게이트웨이와 프로토콜에서 혼동되는 것으로 알려져 있어 사용이 꺼려지기도 한다.
  • 이러한 예약된 문자들을 본래 목적이 아닌 다른 용도로 사용하려면 반드시 인코딩해야 한다.
  • 예) % / . .. # ? ; : 등

2.4.4 좀더 알아보기

  • 안전하지 않은 문자를 그대로 사용해도 문제가 발생하지 않을 순 있지만, 혼동의 여지가 있기 때문에 모두 변환해야 한다.
  • 어떤 문자를 인코딩해야 하는가는 브라우저와 같이 최초로 URL을 입력받는 애플리케이션에서 하는 것이 적절하다.
  • 모든 문자를 인코딩하는 방법도 있으나, 선호되지 않는다.

2.6 미래

  • URL은 주소이지 실제 이름이 아니므로 완벽하지 않다. 리소스가 옮겨지면 더는 사용할 수 없다.
  • 이상적인 방법은 그 객체를 가리키는 실제 객체의 이름을 사용하는 것이다. -> URN
  • URL에서 URN으로 주소 체계를 바꾸는 것은 매우 큰 작업이다. 이러한 전환을 위해서는 굉장히 많은 시간이 걸릴 것이다.




3장 HTTP 메시지

3.1 메세지의 흐름

  • 인바운드 : 클라이언트 -> 프록시 -> 서버 방향
  • 아웃바운드 : 서버 -> 프록시 -> 클라이언트 방향
  • 업스트림 / 다운스트림 : 발송지에 가까울수록 업스트림, 수신지에 가까울수록 아웃스트림

3.2 메세지의 각 부분

  • 메세지는 시작줄, 헤더 블록, 본문으로 나누어진다.
  • 시작줄 및 헤더와 달리 본문은 비어있을 수도 있다.

3.2.1 메세지 문법

  • 메서드
    • 클라이언트 측에서 서버가 리소스에 대해 수행해주길 바라는 동작.
    • GET, HEAD, POST
  • 요청 URL
    • 요청 대상이 되는 리소스를 지칭하는 완전한 URL 혹은 URL의 경로 구성요소
  • 버전
    • HTTP/<메이저>.<마이너> 의 형태
    • 메이저, 마이너는 모두 정수
  • 상태 코드
    • 요청 중에 무엇이 일어났는지 설명하는 세자리 숫자
    • 각 코드의 첫번째 자릿수는 일반적인 분류를 나타낸다.
  • 사유 구절
    • 상태 코드를 사람이 이해할 수 있게 설명해주는 문구
    • 사유 구절이 직접적으로 처리과정에 영향을 미치진 않는다.
  • 헤더
    • 0개 이상의 헤더를 나열할 수 있다.
    • 모든 헤더를 기입하면 빈줄(CRLF)을 통해 헤더가 끝났음을 알린다. (본문이 없더라도)
  • 엔티티 본문
    • 모든 메시지가 엔티티 본문을 갖지는 않는다.

3.2.2 시작줄

요청줄

  • 메서드 + 리소스URL + HTTP버전으로 구성
  • 메서드
    • 메서드의 종류
    • 모든서버가 모든 메서드를 구현하고 있는 것은 아니다.

응답줄

  • HTTP버전 + 상태코드 + 사유구절로 구성
  • 상태 코드
  • 사유구절
    • 표준은 있으나 엄격한 규칙은 없다.
  • HTTP 버전 번호
    • 1.1버전과 통신하는 1.2버전은 1.2버전의 새 기능을 사용할 수 없다. (낮은 쪽에 맞추어 통신)
    • 해당 애플리케이션이 지원하는 가장 높은 HTTP 버전을 가리킨다.
    • HTTP/1.1이라고 보냈다면, 1.1버전으로 통신한것이라는 뜻이 아닌 1.1버전까지 수신할 수 있음을 표시
    • 버전번호는 소숫점단위가 아니다. 즉 HTTP/1.22버전은 HTTP/1.3버전보다 높다.

3.2.3 헤더

  • 일반 헤더 : 요청과 응답 양쪽에 모두 나타날 수 있음
  • 요청 헤더 : 요청에 대한 부가 정보를 제공
  • 응답 헤더 : 응답에 대한 부가 정보를 제공
  • 엔티티 헤더 : 본문 크기와 콘텐츠, 혹은 리소스 그 자체를 서술
  • 확장 헤더 : 명세에 정의되지 않은 새로운 헤더
  • 헤더가 길다면 줄을 나눌 수 있다. 단 추가줄 앞에 최소 하나의 스페이스 혹은 탭 문자가 와야 한다.

3.2.4 엔티티 본문

  • 이미지, 비디오, 신용카드 트랜잭션 등 여러 종류의 데이터를 실어나를 수 있다.

3.3 메서드

3.3.1 안전한 메서드

  • GET, HEAD 등 요청을 보내도 서버에 어떠한 변화도 주지 않는 메서드

3.3.2 GET

  • 서버에게 리소스를 달라고 요청할 때 주로 사용한다.
GET /seasonal/index-fall.html HTTP/1.1
Host: www.joes-hardware.com
Accept: *

3.3.3 HEAD

  • GET과 똑같이 행동하지만, 헤더만을 반환받는다.
  • 사용 이유
    • 리소스를 가져오지 않고도 리소스에 대한 정보를 알 수 있다.
    • 응답의 상태 코드를 통해 개체의 존재여부를 알 수 있다.
    • 헤더를 확인하여 리소스의 변경여부를 알 수 있다.
// 요청메세지
HEAD / seasonal/index-fall.html HTTP/1.1 
Host: www.joes-hardware.com
Accept: *

// 응답메세지
HTTP/1.1 200 OK
Content-Type: text/html
Context-Length: 617

3.3.4 PUT

  • PUT으로 요청하면 서버는 요청의 본문을 가지고 요청 URL의 이름대로 새 문서를 만들거나, 이미 있다면 대체한다.
PUT /product-list.txt HTTP/1.1
Host: www.joes-hardware.com
Content-type: text/plain
Content-length: 34

Updated product list coming soon!

3.3.5 POST

  • 서버에 입력 데이터를 전송하기 위해 설계되었다.
  • HTML폼을 지원하기 위해 흔히 사용되고 이는 서버로 전송되어진다.
POST /inventory-check.cgi HTTP/1.1
Host: www.joes-hardware.com
Content-type: text/plain
Content-length: 18

item=bandsaw 2647 // HTML폼이 사용자에 의해 채워진 내용

3.3.6 TRACE

  • 요청은 프록시, 게이트웨이, 방화벽등을 통과하게 되고 이들은 HTTP 요청을 수정할 수 있다.
  • TRACE메서드는 이러한 애플리케이션들을 거쳐서 최종적으로 서버에 도달했을때의 모습을 알고싶을 때 사용한다.
  • 요청이 의도된대로 흘러가는지를 확인하는 등 진달을 위하여 주로 사용된다.
  • 많은 HTTP 애플리케이션은 메서드에 따라 다르게 동작하는데, TRACE는 이러한 점을 고려할 수 없다는 문제가 있다.
// 요청 메세지(클라이언트 -> 프록시)
TRACE /product-list.txt HTTP/1.1
Accpt: *
Host: www.joes-hardware.com

// 요청 메세지(프록시 -> 서버)
TRACE /product-list.txt HTTP/1.1
Accpt: *
Host: www.joes-hardware.com
Via: 1.1 proxy3.company.com

// 응답 메세지(서버 -> 프록시)
HTTP/1.1 200 OK
Content-type: text/plain
Content-length: 96

TRACE /product-list.txt HTTP/1.1
Accpt: *
Host: www.joes-hardware.com
Via: 1.1 proxy3.company.com

// 응답 메세지(프록시 -> 클라이언트)
HTTP/1.1 200 OK
Content-type: text/plain
Content-length: 96
Via: 1.1 proxy3.company.com

TRACE /product-list.txt HTTP/1.1
Accpt: *
Host: www.joes-hardware.com
Via: 1.1 proxy3.company.com

3.3.7 OPTIONS

  • 웹 서버에게 특정 리소스에 대해 어떤 메서드가 지원되는 지를 물어본다.
// 요청메세지
OPTIONS * HTTP/1.1
Host: www.joes-hardware.com
Accept: *

// 응답 메세지
HTTP/1.1 200 OK
Allow: GET, POST, PUT, OPTIONS
Context-length: 0

3.3.8 DELETE

  • 서버에게 요청 URL로 지정한 리소스를 삭제할 것을 요청한다.
  • 서버는 이를 무시할 수 있다. 따라서 클라이언트는 삭제의 수행을 보장받지 못한다.
DELETE /product-list.txt HTTP/1.1
Host: www.joes-hardware.com

3.3.9 확장메서드

  • HTTP는 필요에 따라 메서드를 확장해도 상관없도록 설계되어 있다.
  • 명세에는 정의되어있지 않으나 수많은 메서드들이 존재한다.

3.4 상태 코드

3.4.1 100-199: 정보성 상태 코드

  • 작업의 최적화를 위한 의도로 도입되었으나 잘 사용되지 않는다.

3.4.2 200-299: 성공 상태 코드

3.4.3 300-399: 리다이렉션 상태 코드

  • 클라이언트가 관심있어 하는 리소스에 대해 다른 위치를 사용하라고 말해주거나 리소스의 내용 대신 다른 대안 응답을 제공한다.
  • Location헤더를 통하여 리소스가 옮겨졌다면 어느 위치로 옮겨졌는지 전달할 수 있다.
  • 리다이렉션 상태 코드의 종류

3.4.4 400-499: 클라이언트 에러 상태 코드

3.4.5 500-599: 서버 에러 상태 코드

3.5 헤더

3.5.1 일반 헤더

  • 메세지에 대한 기본 정보를 제공한다.
헤더 설명
Connection 클라이언트와 서버가 요청/응답 연결에 대한 옵션을 정할 수 있게 해준다.
Date 메세지가 언제 만들어졌는지에 대한 날짜와 시간을 제공한다.
MIME-Version 발송자가 사용한 MIME의 버전을 알려준다.
Trailer chunked transfer 인코딩으로 인코딩된 메세지의 끝 부분에 위치한 헤더들의 목록을 나열한다.
Transfer-Encoding 수신자에게 안전한 전송을 위해 메세지의 어떤 인코딩이 적용되었는지 말해준다.
Upgrade 발송자가 ‘업그레이드’하길 원하는 새 버전이나 프로토콜을 알려준다.
Via 이 메세지가 어떤 중개자(프록시, 게이트웨이)를 거쳐 왔는지 보여준다.
  • 일반 캐시 헤더
    • 매번 원 서버로부터 객체를 가져오는 대신 로컬 복사본으로 캐시할 수 있다.
헤더 설명
Cache-Control 메세지와 함께 캐시 지시자를 전달하기 위해 사용한다.
Pragma 메세지와 함께 지시자를 전달하는 또 다른 방법. 캐시에 국한되지 않는다.
  • 현재 Pragma는 Cache-Control로 인해 더이상 사용되지 않을 예정이다.

3.5.2 요청 헤더

  • 요청에서만 의미를 갖는 헤더
  • 누가, 무엇이 그 요청을 보냈는지에 대한 정보나 클라이언트의 선호나 능력에 대한 정보를 준다.
헤더 설명
Client-IP 클라이언트가 실행된 컴퓨터의 IP를 제공한다.
From 클라이언트 사용자의 메일 주소를 제공한다.
Host 요청의 대상이 되는 서버의 호스트 명과 포트를 준다.
Referer 현재의 요청 URI가 들어있었던 문서의 URL을 제공한다.
User-Agent 요청을 보낸 애플리케이션의 이름을 서버에게 말해준다.
  • Accept 관련 헤더
    • 클라이언트는 Accept 관련 헤더들로 서버에게 자신의 선호와 능력을 알려줄 수 있다.
    • 서버는 이 정보를 통해 무엇을 보낼 것인가에 대해 더 똑똑한 결정을 내릴 수 있다.
    • 많은 시간과 대역폭 낭비를 막을 수 있다.
헤더 설명
Accept 서버에게 서버가 보내도 되는 미디어 종류를 말해준다.
Accept-Charset 서버에게 서버가 보내도 되는 문자집합을 말해준다.
Accept-Encording 서버에게 서버가 보내도 되는 인코딩을 말해준다.
Accept-Language 서버에게 서버가 보내도 되는 언어를 말해준다.
TE 서버에게 서버가 보내도 되는 확장 전송 코딩을 말해준다.
  • 조건부 요청 헤더
    • 특정 조건에 맞추어 응답을 요청할 수 있다.
헤더 설명
Expect 클라이언트가 요청에 필요한 서버의 행동을 열거할 수 있게 해준다.
If-Match 문서의 엔티티 태그가 주어진 엔티티 태그와 일치하는 경우에만 문서를 가져온다. (7장)
If-Modified-Since 주어진 날짜 이후에 리소스가 변경되지 않았다면 요청을 제한한다.
If-None-Match 문서의 엔티티 태그가 주어진 엔티티 태그와 일치하지 않는 경우에만 문서를 가져온다.
If-Range 문서의 특정 범위에 대한 요청을 할 수 있게 해준다.
If-Unmodified-Since 주어진 날짜 이후에 리소스가 변경되었다면 요청을 제한한다.
Range 서버가 범위 요청을 지웒나다면, 리소스에 대한 특정 범위를 요청한다.
  • 요청 보안 헤더
    • 보안에 대해서는 14장에서 자세히 다룬다.
    • 쿠키에 대해서는 11장에서 자세히 다룬다.
헤더 설명
Authorization 클라이언트가 서버에게 제공하는 인증 그 자체에 대한 정보를 담고 있다.
Cookie 클라이언트가 서버에게 토큰을 전달할 때 사용한다. 진짜 보안 헤더는 아니지만, 보안에 영향을 줄 수 있다.
Cookie2 요청자가 지원하는 쿠키의 버전을 알려줄 떄 사용한다.
  • 프록시 요청 헤더
    • 프록시에 대해서는 6장에서 자세히 다룬다.
헤더 설명
Max-Forwards 요청이 원 서버로 향하는 과정에서 다른 프록시나 게이트웨이로 전달될 수 있는 최대 횟수
Proxy-Authorization Authorization과 같으나 프록시에서 인증을 할 때 쓰인다.
Proxy-Connection Connection과 같으나 프록시에서 연결을 맺을 때 쓰인다.

3.5.3 응답 헤더

  • 응답 헤더는 클라이언트에게 부가 정보를 제공한다.
  • 클라이언트가 응답을 잘 다루고 나중에 더 나은 요청을 할 수 있도록 도와준다.
헤더 설명
Age 응답이 얼마나 오래되었는지
Public 서버가 특정 리소스에 대해 지원하는 요청 메서드의 목록
Retry-After 현재 리소스가 사용 불가능한 상태일 때, 언제 가능해지는지 날짜 혹은 시간
Server 서버 애플리케이션의 이름과 버전
Title HTML 문서에서 주어진 것과 같은 제목
Warning 사유 구절에 있는 것보다 더 자세한 경고 메세지
  • 협상 헤더
    • 협상에 대해서는 17장에서 자세히 다룬다.
헤더 설명
Accept-Ranges 서버가 자원에 대해 받아들일 수 있는 범위의 형태
ary 서버가 확인해 보아야 하고 그렇기 때문에 응답에 영향을 줄 수 있는 헤더들의 목록
  • 응답 보안 헤더
    • 보안에 대해서는 14장에서 자세히 다룬다.
헤더 설명
Proxy-Authenticate 프라깃에서 클라이언트로 보낸 인증요구의 목록
Set-Cookie 진짜 보안 헤더는 아니지만, 보안에 영향을 줄 수 있다. 서버가 클라이언트를 인증할 수 있도록 클라이언트 측에 토큰을 설정하기 위해 사용한다.
Set-Cookie2 Set-Cookie와 비슷하게 RFC 2965로 정의된 쿠키
WWW-Authenticate 서버에서 클라이언트로 보낸 인증요구의 목록

3.5.4 엔티티 헤더

  • 엔티티에 대해 설명하는 헤더
  • 개체 타입, 요청할 수 있는 유효 메서드 등 광범위한 정보 제공
헤더 설명
Allow 이 엔티티에 대해 수행될 수 있는 요청 메서드들을 나열
Location 클라이언트에게 엔티티가 실제로 어디에 위치하고 있는지 말해준다. 수신자에게 리소스에 대한 위치를 알려줄 때 사용한다.
  • 콘텐츠 헤더
    • 엔티티의 콘텐츠에 대한 구체적인 정보를 제공
    • 종류, 크기, 기타 콘텐츠를 처리할 떄 유용하게 활용될 수 있는 것들
헤더 설명
Content-Base 본문에서 사용된 상대 URL을 계산하기 위한 기저 URL
Content-Encoding 본문에 적용된 어떤 인코딩
Content-Language 본문을 이해하는데 가장 적절한 자연어
Content-Length 본문의 길이나 크기
Content-Location 리소스가 실제로 어디에 위치하는지
Content-MD5 본문의 MD5 체크섬
COntent-Range 전체 리소스에서 이 엔티티가 해당하는 범위를 바이트 단위로 표현
COntent-Type 이 본문이 어떤 종류의 객체인지
  • 엔티티 캐싱 헤더
    • 엔티티 캐싱에 대한 정보를 제공
    • 리소스에 대해 캐시된 사본이 아직 유효한지에 대한 정보, 캐시된 리소스가 더이상 유효하지 않게 되는 시점 등
헤더 설명
ETag 이 엔티티에 대한 엔티티 태그
Expires 이 엔티티가 더 이상 유효하지 않아 원본을 다시 받아와야 하는 일시
Last-Modified 가장 최근 이 엔티티가 변경된 일시




4장 커넥션 관리

4.1 TCP 커넥션

  • 서버와 클라이언트는 TCP/IP 커넥션을 맺으며 일단 커넥션이 맺어지면 주고받는 메세지들은 손실 혹은 손상되거나 순서가 바뀌지 않고 안전하게 전달된다.

4.1.1 신뢰할 수 있는 데이터 전송 통로인 TCP

  • HTTP커넥션은 몇몇 사용 규칙을 제외하고는 TCP 커넥션에 불과하다.

4.1.2 TCP 스트림은 세그먼트로 나뉘어 IP 패킷을 통해 전송된다

  • HTTP메세지를 전송할 때, TCP는 세그먼트라는 단위로 데이터 스트림을 잘게 나누고, 세그먼트를 IP패킷에 담아서 인터넷을 통해 전달한다.
  • IP패킷의 구성요소
    • IP 패킷 헤더 : 발신지와 목적지 IP 주소, 크기, 기타 플래그
    • TCP 세그먼트 헤더 : TCP 포트 번호, TCP 제어 플래그, 데이터의 순서와 무결성을 검사할 때 사용되는 숫자값
    • TCP 데이터 조각

4.1.3 TCP 커넥션 유지하기

  • TCP커넥션은 발신지 IP 주소, 발신지 포트, 수신지 IP 주소, 수신지 포트 네가지 값으로 식별하며 이는 유일하다.

4.1.4 TCP 소켓 프로그래밍

  • 운영체제는 TCP 커넥션의 생성과 관련된 소켓 API를 제공한다.
  • 소켓 API를 사용하면, TCP 종단 데이터 구조를 생성하고, 원격 서버의 TCP 종단에 그 종단 데이터 구조를 연결하여 데이터 스트림을 읽고 쓸 수 있다.

4.2 TCP의 성능에 대한 고려

4.2.1 HTTP 트랜잭션 지연

  • 실제 트랜잭션을 처리하는 시간은 TCP커넥션을 설정하고, 요청을 보내고 응답을 받는 시간에 비해 매우 짧다.
  • 즉 HTTP 지연은 대부분 TCP 네트워크 지연 떄문에 발생한다.
  • HTTP 트랜잭션을 지연시키는 원인
    • (1) DNS로부터 URI에 있는 호스트명을 IP로 변환하는데에 시간이 걸린다. (현재는 인프라의 발전으로 굉장히 적은시간이 소요된다.)
    • (2) 새로운 TCP 커넥션마다 커넥션 설정 시간이 소요된다.
    • (3) 요청 메세지가 인터넷을 통해 서버로 전달되고 처리되는 과정에서 시간이 소요된다.
    • (4) 웹 서버가 HTTP 응답을 보내는 과정에서 시간이 소요된다.

4.2.3 TCP 커넥션 핸드쉐이크 지연

  • TCP 커넥션을 위해 3-way handshake과정에 있어서 시간이 소요된다.
  • 3-way handshake의 순서
    • (1) 클라이언트는 작은 TCP 패킷을 서버에게 보내고, 그 패킷은 SYN이라는 특별한 플래그를 가진다. 이는 커넥션 생성 요청이라는 뜻이다.
    • (2) 서버가 커넥션을 받으면 몇 가지 커넥션 매개변수를 산출하고 커넥션 요청이 받아들여졌음을 의미하ㅎ는 SYNACK플래그를 포함한 TCP 패킷을 보낸다.
    • (3) 클라이언트는 커넥션이 잘 맺어졌음을 알리는 ACK플래그를 포함한 TCP 패킷을 서버에 보낸다.
  • 크기가 작은 HTTP 트랜잭션은 이러한 TCP를 설정하는데에 많은 시간을 소요한다.

4.2.4 확인응답 지연

  • 인터넷은 패킷 전송을 완벽보장하지 않으므로, TCP가 자체적인 확인 체계를 가진다.
  • 각 TCP 세그먼트는 순번과 데이터 무결성 체크섬을 가진다.
  • 세그먼트 수신자는 세그먼트를 온전히 받으면 작은 확인응답 패킷을 송신자에게 반환한다.
  • 송신자는 이를 수신하지 못한다면 패킷이 파기되었거나 오류가 있다고 판단하고 재전송한다.
  • 확인응답 패킷은 크기가 작으므로 다른 TCP 패킷에 편승시켜 묶음으로써 더 네트워크를 효율적으로 사용한다.
  • 보통 0.1~0.2초정도의 시간동안 저장해두는데, 그 안에 편승시킬 데이터를 찾지 못한다면 확인응답끼리 묶어서 별도의 패킷으로 전송한다.
  • 하지만 정작 확인 응답이 편승할 데이터가 많이 발생하지 않으면 이러한 확인응답 지연 알고리즘으로 인한 지연이 자주 발생한다.

4.2.5 TCP 느린 시작(slow start)

  • TCP 커넥션은 최초에는 최대 속도를 제한하고 데이터가 성공적으로 전송됨에 따라서 속도제한을 점점 높여나간다 -> TCP 느린 시작
  • 인터넷의 급작스러운 부하와 혼잡을 방지한다.
  • 따라서 새로운 커넥션은 이미 어느정도 데이터를 주고 받은 튜닝된 커넥션보다 느리다.

4.2.6 네이글(Nagle) 알고리즘과 TCP_NODELAY

  • TCP 세그먼트는 40바이트 상당의 플래그와 헤더를 포함하기 때문에, TCP가 작은 크기의 데이터를 많이 전송할수록 네트워크 성능은 떨어진다.
  • 존 네이글이 만든 알고리즘으로, 많은 양의 TCP 데이터를 한 개의 덩어리로 합쳐 전송한다.
  • 다른 모든 패킷이 확인 응답을 받았을 경우를 제외하고는 세그먼트가 최대크기가 되지 않으면 전송하지 않는다.
  • 확인 응답을 기다리던 패킷이 확인 응답을 받았거나 전송하기 충분한 만큼의 패킷이 쌓이면 버퍼에 있던 데이터가 전송된다.
  • 문제점
    • (1) 크기가 작은 HTTP메세지는 패킷을 채우기 못하기 때문에 생길지 모르는 데이터를 기다리며 지연된다.
    • (2) 확인응답 지연과 함께 쓰이면 형편없이 동작한다. 네이글 알고리즘은 확인응답을 기다리는데, 정작 확인응답은 확인응답 지연 알고리즘에 의해 지연된다.

4.3 HTTP 커넥션 관리

4.3.1 흔히 잘못 이해하는 Connection 헤더

  • 클라이언트와 서버사이에는 수많은 중개서버가 놓이는데, 어떤 경우에는 두 인접한 HTTP 애플리케이션이 맺고 있는 커넥션에만 적용될 옵션을 지정해야 할 때가 있다.
  • Connection 헤더에 전달될 수 있는 토큰
    • (1) HTTP 헤더 필드 명 : 이 커넥션에만 해당되는 헤더들을 나열
    • (2) 임시적인 토큰 값 : 커넥션에 대한 비표준 옵션
    • (3) close : 커넥션이 작업이 완려되면 종료되어야 함을 의미
  • 처음 전달받은 프록시는 요청에 대한 모든 옵션을 적용하고 Connection 헤더와 Connection에 기술된 모든 헤더를 삭제하고 보낸다.

4.3.2 순차적인 트랜잭션 처리에 의한 지연

  • 각 트랜잭션이 새로운 커넥션을 필요로 한다면 커넥션을 맺는데 발생하는 지연 및 느린 시작 지연이 발생한다.
  • 순차적으로 로드하는 방식은 객체를 화면에 배치하려면 객체의 크기를 알아야 하기 때문에 모든 객체를 받기 전까지 텅 빈 화면을 보여준다.
  • 이러한 점을 해결하기 위한 최신 기술들이 사용되고 있다.

4.4 병렬 커넥션

  • HTTP는 클라이언트가 여러 개의 커넥션을 맺음으로써 여러 개의 HTTP 트랜잭션을 병렬로 처리할 수 있게 한다.

4.4.2 병렬 커넥션이 항상 더 빠르지는 않다

  • 클라이언트의 네트워크의 대역폭이 좁을 때는 대부분의 시간을 데이터를 전송하는데에 쓰고, 결과적으로 병렬의 이점이 거의 없어진다.
  • 웹페이지는 수십에서 수백개의 객체를 포함하는데, 이를 모두 병렬로 처리한다면 많은 메모리를 필요로한다.
  • 현재는 대부분 6~8개의 병렬 커넥션을 지원한다.

4.5 지속 커넥션

  • HTTP 요청을 하기 시작한 애플리케이션은 웹 페이지 내의 다른 이미지 등을 가져오기 위해서 그 서버에 또 요청하는 일이 잦다. 이를 사이트 지역성이라 부른다.
  • HTTP/1.1부터는 TCP 커넥션을 유지하여 앞으로 있을 HTTP 요청에 재사용할 수 있다.
  • 커넥션을 맺기 위한 준비작업에 따르는 시간을 절약할 수 있다.

4.5.1 지속 커넥션 vs 병렬 커넥션

  • 병렬 커넥션에는 몇가지 단점이 있다.
    • (1) 각 트랜잭션마다 새로운 커넥션을 맺고 끊기 때문에 시간과 대역폭이 소요된다.
    • (2) 각각의 새로운 커넥션은 TCP 느린 시작 때문에 성능이 떨어진다.
    • (3) 실제로 연결할 수 있는 병렬 커넥션의 수에는 제한이 있다.
  • 지속커넥션은 위의 단점을 보완하지만 관리를 잘못할 경우 수많은 커넥션이 연결상태로 유지되어 불필요한 소모를 발생시킨다.
  • 지속 커넥션은 병렬 커넥션과 함께 사용하면 더욱 효과적이다.

4.5.8 HTTP/1.1의 지속 커넥션

  • HTTP/1.1의 지속 커넥션은 HTTP/1.0의 keep-alive 커넥션과 달리 기본으로 활성화되어 있다.
  • 커넥션을 끊으려면 Connection: close 헤더를 명시해야 한다.
  • 하지만 Connection: close를 보내지 않더라도 서버와 클라이언트는 언제든지 커넥션을 끊을 수 있다.

4.6 파이프라인 커넥션

  • HTTP/1.1은 지속 커넥션을 통해서 요청을 파이프라이닝할 수 있다.
  • 여러 개의 요청은 응답이 도착학히 전까지 큐에 쌓인다.
  • 제약사항
    • 클라이언트는 커넥션이 지속 커넥션인지 확인하기 전까지는 파이프라인을 이어서는 안 된다.
    • 응답은 요청 순서와 같게 와야 한다.
    • 클라이언트는 언제 커넥션이 끊어지더라도 완료되지 않은 요청이 파이프라인에 있으면 언제든지 다시 보낼 준비가 되어 있어야 한다.
    • POST와 같은 비멱등 요청을 재차 보내면 문제가 생길 수 있기 때문에 파이프라인을 통해 보내면 안된다.

4.7 커넥션 끊기

4.7.1 ‘마음대로’ 커넥션 끊기

  • 서버, 프록시, 클라이언트는 언제든 커넥션을 끊을 수 있다.

4.7.2 Content-Length와 Truncation

  • 각 HTTP 응답은 본문의 정확한 크기 값을 가지는 Content-Length 헤더를 가져야 한다.
  • 커넥션이 끊어졌다는 HTTP 응답을 받은 후, 실제 전달된 엔티티의 길이와 헤더값이 일치하지 않거나 존재하지 않으면 다시 서버에게 물어봐야 한다.
  • 수신자가 캐시 프록시라면 응답을 캐시해서는 안된다. 프록시는 Content-Length를 정정하려 하지 말고 그대로 전달해야 한다.

4.7.3 커넥션 끊기의 허용, 재시도, 멱등성

  • 예상치 못하게 커넥션이 끊어졌을 때에 적절히 대응할 준비가 되어있어야 한다.
  • 어떤 요청데이터가 전송되었지만, 응답이 오기 전에 커넥션이 끊기면 클라이언트는 실제로 서버에서 얼만큼 요청이 처리되었는지 알 수 없다.
  • GET, HEAD, PUT, DELETE, TRACE, OPTIONS 메서드와 같은 멱등 메서드만이 파이프라인을 통해 요청해야 한다.

4.7.4 우아한 커넥션 끊기

  • TCP 커넥션은 양방향이다.
  • 전체 끊기 : 입력채널과 출력채널을 모두 끊는다.
  • 절반 끊기 : 입력채널과 출력채널 중 하나만 끊을 수 있다.
  • 예상치 못한 에러를 예방하기 위해서는 절반 끊기를 사용해야 한다. (출력부터 끊는 것이 안전하다.)
  • 클라이언트가 더이상 데이터를 보내지 않는다는 확신이 없는 이상 커넥션의 입력 채널을 끊는 것은 위험하다.

Tags:

Categories:

Updated:

Leave a comment