HTTP 완벽 가이드 요약
옮긴이의 글
HTTP/1.1 명세는 1999년 RFC 2616이었으나, 2014년 6월에 RFC 7230~7235로 대체되었다.
서문
책 전반에 걸쳐서, "HTTP를 어떻게 사용하는가"에 대한 내용뿐만 아니라 "HTTP를 사용하는 이유"에 대해서도 자세히 설명한다.
1부 - HTTP: 웹의 기초
1장 - HTTP 개관
미디어 타입
- 인터넷에서는 여러 가지 타입을 다루는데, 이 타입에 대한 정보를 MIME 타입이라고 한다.
Content-type: image/jpeg
- 주 타입/ 부 타입으로 이루어진 라벨
URI
- 리소스의 고유 식별자이다. URL과 URN으로 구분된다.
- URL
- 경로를 통해 리소스를 식별하는 것
- URN
- 리소스 고유의 이름을 통해 리소스를 식별하는 것이다. URL과 다르게 리소스의 경로가 수정되어도 동일한 값을 가진다.
telnet이란
- 텔넷 유틸리티가 HTTP 요청을 수행하기 전 TCP 연결을 해주는 역할을 한다.
HTTP는 여러 버전을 통해 발전해왔다.
- HTTP/0.9: 프로토타입용
- HTTP/1.0: keep-alive 커넥션, 가상 호스팅 지원, 프락시 연결 지원
- HTTP/1.1: 1.0 결함 교정, 성능 최적화, 잘못된 기능 제거
- HTTP/2.0: 1.1 성능 개선을 위해 SPDY 프로토콜 기반으로 설계
웹은 다양한 구성 요소들을 가지고 있다.
- 프록시
- 주로 보안 향상을 위해 중재자 역할을 한다.
- 캐시
- 웹 캐시, 프록시 캐시 등이 성능 향상을 위해 사용한다.
- 게이트웨이
- 다른 서버들의 중개자로 동작하며, 주로 프로토콜 변환 시에 사용한다. (e.g. http -> ftp)
- 터널
- 두 커넥션 사이 데이터를 열어보지 않고 그대로 전달해준다.
- 프록시는 클라이언트의 패킷을 분석 후 다시 재조립하여 서버에 보내주지만, 터널은 패킷을 조작하지 않는다.
- 에이전트
- 자동화된 HTTP 요청을 만드는 클라이언트
2장 - URL과 리소스
URL을 사용하면 리소스를 일관된 방식으로 지칭할 수 있다. 대부분의 URL은 스킴://서버위치/경로
로 구성된다.
http://www.joes-hardware.com/seasonal/index-fail.html
-
http
: 스킴- 웹 클라이언트가 리소스에 어떻게 접근하는지 (어떤 프로토콜을 사용할 것인지)
-
www.joes-hardware.com
: 서버의 위치- 리소스가 어디에 호스팅되어 있는지
-
/seasonal/index-fail.html
: 리소스의 경로- 서버에 존재하는 로컬 리소스 중 요청받은 리소스가 무엇인지
- URL 문법을 더 자세하게 나누면 다음과 같은 형태가 된다. 1
<스킴>://<사용자 이름>:<비밀번호>@<호스트>:<포트>/<경로>;<파라미터>?<질의>#<프래그먼트>
안전한 URL
- 상대 URL(
./hammers.html
)이 주어지면 기존의 절대 URL(http://example.com
)의 정보를 상속받아 절대 URL(https://example.com/hammers.html
)로 다시 변환한다. - 이스케이프 문자열은 US-ASCII에서 사용이 금지된다. 특정 문자나 데이터를 인코딩할 수 있게 한다.
- 안전하지 않은 문자 집합을 사용하는 경우
%
기호로 시작해, ASCII 코드로 표현되는 두 개의 16진수 숫자로 이루어진이스케이프
문자로 바꾼다. - URL 내에 특별한 의미로 예약되어 있는 경우 인코딩해서 사용해야 한다. (
%
,/
외 등등) - 안전하지 않거나 제한된 문자는 인코딩하거나 변환하는 것이 좋다.
스킴
- 유명한 스킴으로는
http
,https
,mailto
,ftp
,rtsp, rtspu
,file
,news
,telnet
등이 있다. - URL은 강력한 도구이지만 수조이지 실제 이름은 아니다. URN의 경우 URL과 다르게 경로가 변경되어도 같은 리소스를 찾을 수 있다.
3. HTTP 메시지
메시지는 원 서버 방향을 인바운드로 하여 송신된다
- 다운스트림으로 흐르는 메시지
- 모든 메시지는 요청/응답에 관계없이 다운스트림으로 흐른다
메시지는 시작줄
, 헤더 블록
, 본문
세 부분으로 이루어진다. 각 줄은 캐리지 리턴(ASCII 13)과 개행 문자(ASCII 10)로 구성된 두 글자의 줄바꿈 문자열으로 끝난다. 2
4. 커넥션 관리
4장은 중요한 내용이라 판단하여 좀 상세하게 정리하였다.
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 우아한 커넥션 끊기
- 일반적으로는 자신의 출력 채널을 먼저 끊고 (절반 끊기) 다른 쪽에 있는 기기의 출력 채널이 끊기는 것을 기다리는 것
2부 - HTTP 아키텍처
5. 웹 서버
웹 서버
- HTTP 요청을 처리하고 클라이언트에게 응답을 돌려주는 것을 의미한다.
IETF ident 프로토콜 5
- 클라이언트의 식별자를 얻기 위한 프로토콜이다. 클라이언트가 이 프로토콜을 지원한다면 서버와 클라이언트가 HTTP 커넥션을 맺을 시 클라이언트 측에서 113번 포트를 열고 서버가 요청 시 이 클라이언트의 사용자에 대한 식별자를 리턴하게 된다.
6. 프락시
프락시는 요청을 가로채는 중개인으로써 보안, 캐시, 성능 개선 등 다양한 용도로 활용된다.
프락시와 게이트웨이의 차이
- 프락시는 클라이언트와 서버가 동일한 프로토콜을 사용한다.
- 게이트웨이는 보통 다른 프로토콜을 변환하기 위해 사용한다.
Via
헤더와 Server
헤더
-
Via
헤더는 어떤 경유지들을 지나가는지 나타내는 정보이다. 쉼표로 구분되어 나타난다.Via: 1.1 proxy1.com, 1.1 proxy2.com
-
Server
헤더는 원 서버가 사용하는 소프트웨어를 알려준다. 프록시는 이 값을 수정해서는 안된다.Server: Apache/1.3.14 (Unix) PHP/4.0.4
TRACE 메서드
HTTP/1.1의 TRACE 메서드는 요청 메시지를 프락시의 연쇄를 따라가면서 어떤 프락시를 지나가고 어떻게 각 프락시가 요청 메시지를 수정하는지 관찰/추적할 수 있도록 해준다. TRACE는 프락시 흐름을 디버깅하는데 매우 유용하다.
- TRACE가 무한으로 빠지는 것을 방지하기 위해
Max-Forwards
헤더를 사용해 거쳐갈 프락시 개수를 제한할 수 있다. 이 값은 다음 프락시로 넘어갈때 마다 한개씩 감소한다.
OPTIONS 메서드
- 웹 서버나 웹 서버의 특정 리소스가 어떤 기능을 지원하는지 볼 수 있다. 경로 지정시에는 해당 경로에 대한 기능을 볼 수 있고, 별표(
*
) 지정시 모두 확인이 가능하다.
7. 캐시
웹 캐시는 자주 쓰이는 문서의 사본을 자동으로 저장하는 HTTP 장치다. 원 서버의 요청을 줄이고 네트워크 비용, 병목을 줄여준다.
신선도 검사 (HTTP 재검사)
- 가지고 있는 캐시 데이터가 원 서버의 데이터와 일치하는지 확인하는 과정이다. 주로
If-Modified-Since
와If-None-Match
헤더를 많이 사용한다.-
If-Modified-Since <캐시된 마지막 수정일>
- 변경되지 않았을 경우
304 Not Modified
와 함께Expires
헤더에 만료일 응답
- 변경되지 않았을 경우
-
If-None-Match <Tag명>
- 서버가 가지고 있는 것이 동일할 경우
304 Not Modified
와 함께ETag
헤더로 태그명을 같이 응답
- 서버가 가지고 있는 것이 동일할 경우
-
캐시 제어
-
Cache-Control
헤더 값에 따라서 캐시를 어떻게 제어하는지를 정의한다.-
no-store
: 캐시 금지 -
no-cache
: 서버와 재검사 반드시 필요, 단 로컬에는 데이터 저장- HTTP/1.0+ 에 대응하기 위해서는
Pragma: no-cache
도 추가해야 함
- HTTP/1.0+ 에 대응하기 위해서는
-
must-revalidate
: 신선하지 않을 경우 원 서버와 최초 검사 진행 -
max-age
: 캐시를 몇초동안 사용할 것인지 지정
-
10. HTTP/2.0
HTTP/2.0은 구글에서 개발하던 SPDY 프로토콜을 모티브로 개발되었다.
하나의 커넥션에서 여러 요청을 주고 받을 수 있게 되며, 헤더 압축으로 인한 대역폭 절약, 서버가 리소스를 능동적으로 푸시하는 등의 기능을 갖추고 있다.
이 모든 기술들은 기존 HTTP/1.1의 회전 지연을 줄이기 위한 것이다.
3부 - 식별, 인가, 보안
11. 클라이언트 식별과 쿠키
쿠키
는 사용자를 식별하기 위해 지금까지 가장 많이 사용하는 방식이다. 6
- 쿠키는 브라우저를 닫을 시 바로 삭제되는 세션 쿠키와 디스크에 계속 저장되는 지속 쿠키로 나뉜다.
- 쿠키는 모든 사이트에 정보를 보내지 않는다. Domain, Path등의 속성을 일치할시에만 저장한 쿠키를 해당 사이트에 전송한다.
12. 기본 인증
HTTP는 사용자 인증을 하기 위한 자체 인증요구/응답 프레임워크를 제공한다. 과정은 다음과 같다.
- 클라이언트가 리소스를 요청한다.
- 서버는 인증이 되지 않았을 경우 401 응답 코드와 함께
WWW-Authenticate
헤더에 어떤 인증 정보를 사용하는지 기술한다. - 클라이언트는 이름, 비밀번호 등 필요한 정보를 브라우저 상에 입력한다.
- 인증 정보는 Base64로 인코딩된 정보로
Authorization
헤더에 담긴다. - 인증 정보가 유효할 경우 200과 함께 리소스를 응답하며, 올바르지 않을 경우 401을 응답한다.
하지만 기본 인증은 다음과 같은 취약점이 있다. 그래서 SSL과 같이 사용하는 것이 권장된다.
- 평문으로 인증 정보가 저장된다.
- 프록시가 존재할 경우 내용이 변질될 가능성이 있다.
- 가짜 서버의 위장에 취약하다.
14. HTTPS
https는 기존 http에서 SSL 계층을 추가한 프로토콜이다. (a.k.a. HTTP over SSL) 7
TCP 연결을 맺은 후에도 SSL 핸드셰이크 과정을 수행하게 된다.
기존 HTTP의 문제점
HTTP는 평문으로 데이터를 주고받는다. 이로 인해 비밀번호, 카드 번호 등 민감한 정보를 다른 사용자가 가로채는 문제가 발생할 수 있다.
HTTPS는 클라이언트와 서버가 주고받는 데이터를 암호화8함으로써 제 3자가 데이터를 가로채더라도 해당 내용을 보지 못하도록 하는 것이 목적이다.
대칭키와 공개키(비대칭키)
대칭키는 어떤 메시지 a
가 있을 때 e
라는 해시값을 통해 암호화/복호화를 동시에 진행하는 것을 의미한다.
이로 인해 해시값이 탈취당할 경우, 암호화된 메시지 역시 복호화를 통해 어떠한 내용인지 알아낼 수 있는 단점이 있다.
공개키(=비대칭키)는 암호화는 공개된 키를 통해 암호화를 하되, 복호화는 각자 개인이 가진 개인키를 통해 하는 방식을 의미한다. 9
디지털 인증서
디지털 인증서는 인증 기관이 서버가 안전한지 확인한 과정을 거친 후 서명된 정보가 담긴 것이다.
인증서에 포함되는 정보들은 다음과 같다.
- 대상의
이름
(사람, 서버, 조직) 유효 기간
- 인증서
발급자
- 인증서 발급자의
디지털 서명
- 사이트의 공개키 10
HTTPS 클라이언트
SSL은 복잡한 바이너리 프로토콜이므로, 암호학 전문가가 아닌 이상은 OpenSSL등의 SSL 오픈소스 구현체를 쓰는 것이 바람직하다.
4장 - 엔터티, 인코딩, 국제화
15. 엔터티와 인코딩
Content-Length 헤더와 지속 연결
Content-Length는 지속 연결을 사용 시 어디까지가 응답 메시지인지 구별하기 위해서 사용되므로 굉장히 중요한 요소라고 할 수 있다.
GET /foo HTTP/1.1
Connection: Keep-Alive // 지속 연결
Content-Type: text/plain
Content-Length: 4 // 본문의 길이
bar1
---
GET /foo HTTP/1.1
Connection: Keep-Alive // 지속 연결
Content-Type: text/plain
Content-Length: 4 // 본문의 길이
bar2
17. 내용 협상과 트랜스코딩
콘텐츠 협상 (content negotitation)
콘텐츠 협상은 클라이언트가 서버에게 내가 선호하는 형식이 있는데, 이것을 최대한 맞춰달라고 요청하는 것이다.
주로 응답 미디어 타입
, 언어
, 압축 방식
등이 내용 협상에 해당한다.
콘텐츠 협상 헤더는 요청 시에만 사용 가능하며, Accept
로 주로 시작한다.
헤더 | 뜻 |
---|---|
Accept | 원하는 미디어 타입 |
~Accept-CharSet~ | ~원하는 문자 인코딩~ |
Accept-Language | 원하는 데이터의 언어 |
Accept-Encoding | 원하는 데이터의 압축 방식 |
- 현재 MDN문서에서는
Accept-CharSet
헤더를 사용하지 않을 것을 권고한다. 11
우선순위를 q값으로 설정할 수 있다. 0~1의 값으로 설정할 수 있으며, 생략 시 1로 설정된다.
GET /foo
Accept-Language: ko-kr, en;q=0.9 fr;q=0.8
부록
base64 인코딩
- base64 인코딩은 사용자의 입력을 HTTP 파서가 망가뜨릴 수 있는 문자(
:
,\n
, 이진값) 등을 안전하게 헤더 필드 값으로 보낼 수 있게 해준다. - 문자열을 8비트로 쪼갬 -> 24비트의 이진값 생성 -> 6비트 수열로 조각냄 -> 64개의 문자열 중 하나로 치완 과정을 통해 이루어진다.
-
Ow!
->0x4F
,0x77
,0x21
->010011110111011100100001
->010011
,110111
,01110
,100001
->T3ch
- 문자열이 고르게 나뉘지 않았다면 0으로 치완한다. 어떤 비트도 포함되지 않을 경우
=
의 특수한 값을 사용한다. (base64의 패딩)
-
추가 내용
OCSP stapling
아래는 인증서가 브라우저에 어떻게 들어오고 대칭키를 주고받는지에 대한 내용이다. (책에 포함된 내용은 아님)
- 인증기관들의 공개키는 브라우저에 내장되어 있다. 이를 통해 브라우저는 인증 기관에서 개인키로 암호화한 인증서를 복호화한다.
추가 참고자료
해당 책 외에도 다양한 자료와 같이 공부하였다.
- 그림으로 배우는 HTTP & Network Basic
- HTTPS
각주
-
p31 이렇게 모든 형태를 가지는 URL은 잘 없다. 가장 중요한건 스킴, 호스트, 경로이다. ↩
-
p51 줄바꿈 문자열은 'CRLF'라고 쓴다. (
\r\n
) ↩ -
p97 크기가 작은 HTTP 메시지는 패킷을 채우지 못함 / 확인응답 지연과 함께 쓰일 경우, 확인 응답이 도착할 때까지 데이터를 전송을 멈춘다. ↩
-
p101 병렬, 지속, 파이프라인, 다중 등 뒤에 더 자세히 다룬다. ↩
-
쿠키 외에 사용자를 식별할 수 있는 수단으로는 IP, URL, 헤더 등이 있다. ↩
-
TLS는 SSL의 업그레이드 버전이며, SSL과 TLS가 거의 비슷한 의미로 사용된다. ↩
-
주고받는 데이터는 request/response body와 헤더가 모두 포함된다. ↩
-
그 반대인 개인키로 암호화하고 공개키로 복호화 하는 것도 가능하다. ↩
-
이는 추후 인증기관이 브라우저로 인증서를 전달하고 인증서를 복호화 후, 자신의 대칭키를 암호화 하는 용도로 사용된다. ↩
-
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Accept-Charset ↩