옮긴이의 글

HTTP/1.1 명세는 1999년 RFC 2616이었으나, 2014년 6월에 RFC 7230~7235로 대체되었다.

서문

책 전반에 걸쳐서, "HTTP를 어떻게 사용하는가"에 대한 내용뿐만 아니라 "HTTP를 사용하는 이유"에 대해서도 자세히 설명한다.

1부 - HTTP: 웹의 기초

1장 - HTTP 개관

내가 궁금했던 내용

  • HTTP가 무엇인가?
  • HTTP가 왜 탄생했는가?
  • HTTP가 웹 트래픽을 어떻게 전송하는가?
  • 웹 서버는 어떤 역할을 하는가?
  • MIME 타입이란 무엇인가?

책에서 다룰 내용 - 3p

  • 얼마나 많은 클라이언트와 서버가 통신하는지
  • 리소스(웹 콘텐츠)가 어디서 오는지
  • 웹 트랜잭션이 어떻게 동작하는지
  • HTTP 통신을 위해 사용하는 메시지의 형식
  • HTTP 기저의 TCP 네트워크 전송
  • 여러 종류의 HTTP 프로토콜
  • 인터넷 곳곳에 설치된 다양한 HTTP 구성요소

1.3 리소스

웹 서버는 웹 리소스(웹 콘텐츠)를 관리하고 제공한다. 이는 정적 파일, 텍스트, 동영상 등 외에 모든 종류의 파일을 포함한다.

미디어 타입

  • 인터넷에서는 여러 가지 타입을 다루는데, 이 타입에 대한 정보를 MIME 타입이라고 한다.
    Content-type: image/jpeg
    
    • 주 타입/ 부 타입으로 이루어진 라벨
  • URI
    • 리소스의 고유 식별자이다. URL과 URN으로 구분된다.
    • URL
      • 경로를 통해 리소스를 식별하는 것
    • URN
      • 리소스 고유의 이름을 통해 리소스를 식별하는 것이다. URL과 다르게 리소스의 경로가 수정되어도 동일한 값을 가진다.

1.4 트랜잭션

1.4.1 메서드

  • 서버에게 어떤 동작이 취해져야 하는지를 말해준다.

1.4.2 상태 코드

  • 응답과 함께 반환되며, 요청 성공, 실패, 추가 조치가 필요한지 알려주는 세 자리 숫자이다.

1.4.3 웹페이지는 여러 객체로 이루어질 수 있다

  • 웹브라우저는 풍부한 웹페이지를 가져올 때 대량의 HTTP 트랜잭션을 수행한다.

1.5 메시지

요청은 다음과 같은 형식의 메시지가 주어진다.

GET /index.html
---
Accept: text/*

  • 요청 메서드
  • 요청 헤더

응답은 다음과 같은 형식으로 응답한다.

HTTP/1.1 200 OK
---
Content-type: text/html

---
<html>
...
</html>

  • HTTP 상태 코드 / 상태 코드에 대한 메시지
  • 응답 헤더
  • 응답 본문

1.6 TCP 커넥션

telnet

  • 텔넷 유틸리티가 HTTP 요청을 수행하기 전 TCP 연결을 해주는 역할을 한다.

1.7 여러 종류의 HTTP 프로토콜

  • HTTP/0.9: 프로토타입용
  • HTTP/1.0: keep-alive 커넥션, 가상 호스팅 지원, 프락시 연결 지원
  • HTTP/1.1: 1.0 결함 교정, 성능 최적화, 잘못된 기능 제거
  • HTTP/2.0: 1.1 성능 개선을 위해 SPDY 프로토콜 기반으로 설계

1.8 웹의 구성 요소

  • 프록시
    • 주로 보안 향상을 위해 중재자 역할을 한다.
  • 캐시
    • 웹 캐시, 프록시 캐시 등이 성능 향상을 위해 사용한다.
  • 게이트웨이
    • 다른 서버들의 중개자로 동작하며, 주로 프로토콜 변환 시에 사용한다. (e.g. http -> ftp)
  • 터널
    • 두 커넥션 사이 데이터를 열어보지 않고 그대로 전달해준다.
    • 프록시는 클라이언트의 패킷을 분석 후 다시 재조립하여 서버에 보내주지만, 터널은 패킷을 조작하지 않는다.
  • 에이전트
    • 자동화된 HTTP 요청을 만드는 클라이언트

2장 - URL과 리소스

  • URL 문법, 여러 URL 컴포넌트가 어떤 의미를 가지며 수행하는지.
  • 여러 웹 클라이언트가 지원하는 상대 URL과 확장 URL같은 단축 URL에 대해서.
  • URL의 인코딩과 문자 규칙
  • 여러 인터넷 정보 시스템에 적용되는 공통 URL 스킴
  • 기존 이름은 유지하면서 객체들을 다른 장소로 옮기는 것을 가능하게 해주는 URN을 포함한 URL의 미래

2.1 인터넷의 리소스 탐색하기

URL을 사용하면 리소스를 일관된 방식으로 지칭할 수 있다. 대부분의 URL은 스킴://서버위치/경로로 구성된다.

http://www.joes-hardware.com/seasonal/index-fail.html
  • http: 스킴
    • 웹 클라이언트가 리소스에 어떻게 접근하는지 (어떤 프로토콜을 사용할 것인지)
  • www.joes-hardware.com: 서버의 위치
    • 리소스가 어디에 호스팅되어 있는지
  • /seasonal/index-fail.html: 리소스의 경로
    • 서버에 존재하는 로컬 리소스 중 요청받은 리소스가 무엇인지

2.2 URL 문법

URL 문법을 더 자세하게 나누면 다음과 같은 형태가 된다. 1

<스킴>://<사용자 이름>:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터>?<질의>#<프래그먼트>

(자세한 내용은 중략…)

2.3 단축 URL

상대 URL(./hammers.html)이 주어지면 기존의 절대 URL(http://example.com)의 정보를 상속받아 절대 URL(https://example.com/hammers.html)로 다시 변환한다.

2.4 안전하지 않은 문자

2.4.1 URL 문자 집합

이스케이프 문자열은 US-ASCII에서 사용이 금지된다. 특정 문자나 데이터를 인코딩할 수 있게 한다.

2.4.2 인코딩 체계

안전하지 않은 문자 집합을 사용하는 경우 %기호로 시작해, ASCII 코드로 표현되는 두 개의 16진수 숫자로 이루어진 이스케이프문자로 바꾼다.

2.4.3 문자 제한

URL 내에 특별한 의미로 예약되어 있는 경우 인코딩해서 사용해야 한다. (%, / 외 등등)

2.4.4 좀 더 알아보기

안전하지 않거나 제한된 문자는 인코딩하거나 변환하는 것이 좋다.

2.5 스킴의 바다

유명한 스킴으로는 http, https, mailto, ftp, rtsp, rtspu, file, news, telnet 등이 있다.

2.6 미래

URL은 강력한 도구이지만 수조이지 실제 이름은 아니다. URN의 경우 URL과 다르게 경로가 변경되어도 같은 리소스를 찾을 수 있다.

3. HTTP 메시지

  • 메시지가 어떻게 흘러가는가
  • HTTP 메시지의 세 부분(시작줄, 헤더, 개체 본문)
  • 요청과 응답 메시지의 차이
  • 요청 메시지가 지원하는 여러 기능(메서드)들
  • 응답 메시지가 반환하는 여러 상태 코드들
  • 여러 HTTP 헤더들은 무슨 일을 하는가

3.1 메시지의 흐름

3.1.1 메시지는 원 서버 방향을 인바운드로 하여 송신된다

3.1.2 다운스트림으로 흐르는 메시지

  • 모든 메시지는 요청/응답에 관계없이 다운스트림으로 흐른다

3.2 메시지의 각 부분

메시지는 시작줄, 헤더 블록, 본문 세 부분으로 이루어진다. 각 줄은 캐리지 리턴(ASCII 13)과 개행 문자(ASCII 10)로 구성된 두 글자의 줄바꿈 문자열으로 끝난다. 2

4. 커넥션 관리

  • HTTP는 어떻게 TCP 커넥션을 사용하는가
  • TCP 커넥션의 지연, 병목, 막힘
  • 병렬 커넥션, keep-alive 커넥션, 커넥션 파이프라인을 활용한 HTTP의 최적화
  • 커넥션 관리를 위해 따라야 할 규칙들

4.1 TCP 커넥션

HTTP 요청을 하기 전 TCP 커넥션을 맺고, 요청과 응답을 주고받은 뒤 TCP 연결이 종료된다.

  • 4.1.2 TCP 스트림은 세그먼트로 나뉘어 IP 패킷을 전송된다
    • 세그먼트라는 단위로 데이터 스트림을 잘게 나누고, IP 패킷라고 불리는 봉투에 담아서 인터넷을 통해 데이터를 전달한다.
    • IP 패킷들을 각각 IP 패킷 헤더, TCP 세그먼트 헤더, TCP 데이터 조각을 포함한다.
  • 4.1.3 TCP 커넥션 유지하기
    • TCP는 포트 번호를 통해서 여러 개의 커넥션을 유지한다.
    • TCP 커넥션은 <발신지 IP 주소, 발신지 포트, 수신지 IP 주소, 수신지 포트> 네 가지 값으로 식별한다.
  • 4.1.4 TCP 소켓 프로그래밍
    • 운영체제는 TCP 커넥션의 생성과 관련된 여러 기능과 인터페이스 제공

4.2 TCP의 성능에 대한 고려

HTTP는 TCP 바로 위에 있는 계층이기에 TCP 성능에 영향을 받는다.

4.2.2 성능 관련 중요 요소

  • TCP 커넥션 핸드셰이크 설정
  • 인터넷 혼잡을 제어하기 위한 TCP의 느린 시작 (slow-start)
  • 데이터를 한데 모아 한번에 전송하기 위한 네이글 알고리즘
  • TCP의 편승(piggyback) 확인응답(acknowledgment)을 위한 확인응답 지연 알고리즘
  • TIME_WAIT 지연과 포트 고갈

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

  • HTTP 트랜잭션이 아주 큰 데이터를 주고받지 않는 평범한 경우에는, SYN/SYN+ACK 핸드셰이크가 눈에 띄는 지연을 발생시킨다.
    • TCP의 ACK 패킷은 HTTP 요청 메시지 전체를 전달할 수 있을 만큼 큰 경우가 많고, 많은 HTTP 서버 응답 메시지는 하나의 IP 패킷에도 담길 수 있다.

4.2.4 확인응답 지연

  • 각 TCP 세그먼트는 순번과 데이터 무결성 체크섬을 가진다.
  • 확인응답은 그 크기가 작기 때문에, TCP는 같은 방향으로 송출되는 데이터 패킷에 확인응답을 편승(piggyback) 시킨다. 많은 TCP 스택은 확인응답 지연 알고리즘을 구현한다.

4.2.5 TCP 느린 시작 (slow start)

  • TCP 커넥션은 시간이 지나면서 자체적으로 '튜닝'되어서, 처음에는 커넥션의 최대 속도를 제한하고 데이터가 성공적으로 전송됨에 따라서 속도 제한을 높여간다.
  • TCP의 느린 시작은 TCP가 한 번에 전송할 수 있는 패킷의 수를 제한한다.

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

  • 패킷을 전송하기 전에 많은 양의 TCP 데이터를 한 개의 덩어리로 합치는 과정이다. 네이글 알고리즘은 세그먼트가 최대 크기가 되지 않으면 전송하지 않는다.
  • HTTP 성능 관련 여러 문제를 일으킨다고 한다. 3 HTTP 어플리케이션에서 TCP_NODELAY 파라미터 값을 설정하여 비활성화하기도 한다.

4.2.7 TIME_WAIT의 누적과 포트 고갈

  • TCP 커넥션을 맺으면 커넥션의 IP 주소와 포트 번호를 메모리의 작은 제어영역(control block)에 저장한다.
  • 같은 IP 주소와 포트가 커넥션이 2분 이내에 생기는 것을 방지해준다.

4.3 HTTP 커넥션 관리

커넥션을 생성하고 최적화하는 HTTP 기술에 대해 알아본다.

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

  • Connection 헤더는 옵션과 토큰들을 쉼표로 구분해 나열한다.
    • close 값은 커넥션이 작업이 완료되면 종료되어야 함을 의미한다.
    • 커넥션에 기술된 모든 헤더 필드는 메시지를 다른 곳으로 전달하는 시점에 삭제되어야 한다.

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

  • 페이지 노출을 위해 여러 개의 커넥션이 필요하다면 그만큼 커넥션 지연과 느린 시작 지연이 발생한다. 이를 위해 HTTP 커넥션의 성능을 향상시키는 여러 기술이 존재한다. 4

4.4 병렬 커넥션

여러 개의 HTTP 커넥션을 병렬로 처리하는 방식으로 응답속도를 개선한다.

  • 네트워크 대역폭이 좁은 경우 오히려 더 느릴 수도 있다.
  • 너무 많은 커넥션은 서버에도 부담이 갈 수 있고, 이로 인해 브라우저는 대부분 4개의 병렬 커넥션을 허용한다.

4.5 지속 커넥션

4.5.3 Keep-Alive 동작

  • HTTP 1.0 keep-alive 커넥션은 요청에 Connection: Keep-Alive를 포함하고, 서버가 지속 커넥션을 지원할 경우 응답에도 해당 헤더를 응답한다.

4.5.4 Keep-Alive 옵션

  • Keep-Alive 헤더에 옵션을 key-value 형태로 쉼표로 구분해 지정한다. 커넥션 유지 시간인 timeout과 최대 트랜잭션 처리 개수인 max 외 임의 속성을 지원한다.

4.5.8 HTTP/1.1의 지속 커넥션

  • HTTP/1.1에서는 별도 설정을 하지 않는 한, 모든 커넥션을 지속 커넥션으로 취급한다. 커넥션을 종료하려면 Connection: close 헤더를 명시한다.

4.6 파이프라인 커넥션

HTTP/1.1은 지속 커넥션을 통해서 요청을 파이프라이닝할 수 있고, 이는 keep-alive 성능을 더 높여준다.

4.7 커넥션 끊기에 대한 미스터리

4.7.4 우아한 커넥션 끊기

  • 일반적으로는 자신의 출력 채널을 먼저 끊고 (절반 끊기) 다른 쪽에 있는 기기의 출력 채널이 끊기는 것을 기다리는 것

5. 웹 서버

웹 서버

  • HTTP 요청을 처리하고 클라이언트에게 응답을 돌려주는 것을 의미한다.

IETF ident 프로토콜 5

  • 클라이언트의 식별자를 얻기 위한 프로토콜이다. 클라이언트가 이 프로토콜을 지원한다면 서버와 클라이언트가 HTTP 커넥션을 맺을 시 클라이언트 측에서 113번 포트를 열고 서버가 요청 시 이 클라이언트의 사용자에 대한 식별자를 리턴하게 된다.

각주

  1. p31 이렇게 모든 형태를 가지는 URL은 잘 없다. 가장 중요한건 스킴, 호스트, 경로이다. 

  2. p51 줄바꿈 문자열은 'CRLF'라고 쓴다. (\r\n

  3. p97 크기가 작은 HTTP 메시지는 패킷을 채우지 못함 / 확인응답 지연과 함께 쓰일 경우, 확인 응답이 도착할 때까지 데이터를 전송을 멈춘다. 

  4. p101 병렬, 지속, 파이프라인, 다중 등 뒤에 더 자세히 다룬다. 

  5. https://www.ietf.org/rfc/rfc1413.txt