8. HTTP 진화 과정
WWW(World Wide Web)
: HTTP라는 프로토콜을 이용해 HTML 파일을 주고 받을 수 있는 공간
- HTTP : World Wide Web에 내재된 프로토콜
HTTP / 0.9
: 원-라인 프로토콜
- 단순한 서버 - 클라이언트 구조를 따름
- 요청 : 단일 라인으로 구성
- 리소스 경로 : GET 메소드만 가능
- 특징 )
- HTTP 헤더 없음 -> 즉, HTML 파일만 전송 가능
- 상태 혹은 오류 코드 없음
HTTP / 1.0
: 확장성 만들기 -> 기존 HTTP 기능을 확장함
- 특징 )
- 버전 정보가 각 요청에 포함됨
- 요청 메소드가 GET, HEAD, POST 세 가지로 확장됨
- 상태 코드가 각 응답의 시작 부분에 포함되어, 브라우저가 해당 요청에 대한 성공, 실패를 알 수 있었고 동작할 수 있었음
- HTTP 헤더 개념 등장 -> 이는 서버, 브라우저의 메타 데이터 전송을 허용하면서 프로토콜을 유연, 확장 가능하게 만듦
- 새로운 HTTP 헤더의 등장(Context-Type)으로 HTML 파일이외의 다른 파일도 전송할 수 있게 됨
HTTP / 1.1
: 표준화된 HTTP(표준 프로토콜)
- 모호함을 명확하게 하고 많은 개선 사항들을 도임
- 특징 )
1. 연결 재사용
- HTTP / 1.0에서는 기본적으로 한 연결 당 하나의 요청을 처리하고 요청에 따른 응답이 수신되면 TCP연결을 바로 종료함
- 웹 페이지가 복잡해지면서 한 페이지에서 여러 번 HTTP 요청이 발생했을 때, 매번 새로운 TCP handshake 과정을 거쳐야 해서 속도가 느려짐 -> RTT 증가
cf) RTT
: 패킷이 목적지에 도달하고 나서 다시 출발지로 돌아오기까지 걸리는 시간
-> 패킷 왕복 시간
- TCP 가상 회선 방식은 신뢰성을 보장하지만 속도가 느림
-> 기본적으로 한 번 수립한 연결을 재사용하게 설정
cf) Keep-Alive Header
: 연결을 유지하는 시간이 길어지면 서버에 부하가 생기기 때문에 연결을 유지하는 시간을 제한
- HTTP / 1.0에서도 있었지만 표준화가 되어 있지 않았고, HTTP / 1.1부터 표준화가 되어 기본 옵션으로 설정됨
2. 파이프라이닝(Pipelining)
: 첫 번째 요청에 대한 응답이 완전히 전송되기 이전에 두 번째 요청 전송을 보낼 수 있도록 함
-> 커뮤니케이션 레이턴시를 낮춤
- 기존에는 여러 요청을 보낼 때 한 요청과 응답을 끝내고 다음 요청을 보냄
- 여러 요청을 한 번에 보낼 수 있어서 지연을 개선시킴
3. 캐시 제어 매커니즘 도입
: 요청과 응답에 대한 메타 정보를 담음
- HTTP로 통신을 할 때 Client는 네트워크를 거치는 시간을 소비, Server는 요청을 처리하는 데 걸리는 시간 혹은 부하를 소비
- 이 과정에서 Client가 이전에 받은 데이터와 새로 요청한 데이터가 같다면 이전과 같이 한 번 더 과정을 거치는 것은 낭비임
- 이러한 낭비를 줄이기 위한 해결책으로 사용할 수 있는 방법이 HTTP Cache-Control
-> 적절하게 Cache-Control을 사용함으로써, 상황에 따라 Server는 부하를 줄일 수 있고, Client는 네트워크를 거치는 시간을 아낄 수 있음
- 때에 따라 서버나 클라이언트에게 HTTP 캐시를 위해 명시된 지시자를 제공할 필요가 있음
-> Cache-Control 헤더를 이 목적으로 사용
4. 청크 전송 인코딩
: HTML을 분할해 전송하는 방법
5. 호스트 헤더(Host Header)
: 동일 IP에 여러 도메인을 호스트할 수 있게 해줌
- HTTP / 1.1은 가상 호스팅(Virtual Hosting)이 가능해졌기 때문에 하나의 IP 주소에 여러 개의 도메인을 적용시킬 수 있음
HTTP / 2
: 더 나은 성능을 위한 프로토콜
1. HTTP HOL(Head Of Line) Blocking
cf) HOL(Head Of Line) Blocking
: 컴퓨터 네트워킹에서 패킷 대기열이 존재할 때, 앞선(Head) 패킷이 지연될 때 발생하는 성능 저하 현상
- HTTP / 1.1이 굉장히 유연하고 확장성이 좋지만, TCP / IP 프로토콜을 기반으로 하면서 하나의 연결 내에서 하나의 요청을 처리하도록 설계되었기 때문에 순차적으로 처리되어야 함
- 이를 해결하기 위해 파이프라이닝 기법이 도입됨
-> 응답은 FIFO로 전송되어야 하기 때문에 서버로 먼저 온 요청의 응답이 지연되면, 뒤이은 다음 요청들의 응답도 덩잘아 지연됨
1. SPDY
: 이와 같은 지연들로 인해 구글에서 2010년 전반기에 SPDY(Speedy의 약자) 프로토콜을 구현하여 공개
- 목표 : 웹 페이지 로드 대기 시간을 줄이자
- 특징 )
- HTTP / 2는 SPDY라는 프로토콜 기반으로 동작
- SPDY는 항상 TLS(Transport Layer Security) 위에서 동작 -> 즉, HTTPS 필수
2. 이진(Binary) 프로토콜
- HTTP / 1.1는 텍스트 기반 프로토콜로 아스키코드로 작성, 읽기는 편하지만 데이터가 커짐
- HTTP / 2는 데이터를 바이너리로 변환해서 전송하기 때문에 파싱이 더 빠르고, 오류 발생 가능성이 낮아짐
3. 응답 다중화(Multiplexing)
- HTTP / 1.1은 TCP 하나의 연결 내에서 하나의 요청을 처리할 수 있었고 요청에 대한 응답이 순차적으로 처리되어야 햄
-> HOLB와 같은 문제점이 발생
- HTTP / 2는 Multiplexing으로 위의 문제를 해결함
- HTTP / 2는 하나의 TCP 연결에 여러 개의 요청을 처리할 수 있는데 이것은 스트림(Stream), 메세지(Message), 프레임(Frame)이라는 단위로 세분화했기 때문
- Stream : 구성된 연결 내에서 전달되는 바이트의 양방향 흐름, TCP 연결에서 여러 개 스트림 존재 가능
- Message : 논리적 요청 또는 응답 메세지에 매핑되는 프레임의 전체 시퀀스
- Frame : HTTP / 2에서 통신의 최소 단위, 각 최소 단위에는 하나의 프레임 헤더가 포함됨, 이 프레임 헤더는 최소한으로 프레임이 속하는 스트림을 식별, HEADERS Type Frame, DATA Type Frame이 존재
- 하나의 TCP 커넥션에서 여러 병렬 스트림(3개)이 존재할 수 있음
- Stream이 뒤섞여서 전송될 경우, Stream Number를 이용해 수신 측에서 재조합됨
4. HTTP 헤더 데이터 압축(HTTP Header Data Compression)
- 이전 Header의 내용과 중복되는 필드를 재전송하지 않도록 함
-> 불필요한 오버헤드를 제거하면서, 연속된 요청 사이의 매우 유사한 내용으로 존재하는 헤더들을 압축시킴
- 변경된 부분만 다시 보내는 허프만(Huffman Coding)기법을 사용하는 HPACK이라는 Header 압축 방식을 이용
cf) Huffman Coding 방식
: 데이터 문자의 빈도에 따라서 다른 길이의 부호를 사용하는 알고리즘
5. Server Push
: 클라이언트의 요청을 예상하여 클라이언트 캐쉬에 클라이언트가 요청할 거 같은 데이터(리소스)를 미리 넣어두는 기술
HTTP / 3
: HTTP / 2까지 여전히 데이터 전송 계층을 TCP 위에서 동작하기 때문에 그로 인한 문제가 계속 진행되기 때문
- TCP는 연결 지향형 프로토콜로 신뢰성을 지향
-> 데이터 손실이 발생하면 재전송을 수행
-> 패킷을 순서대로 처리해야 하기 때문에 재전송 과정에서 병목 현상 발생
-> TCP 자체에서 흐름제어 및 혼잡제어를 제공
- 흐름제어 )
- 데이터를 송신하는 곳과 수신하는 곳의 데이터 처리 속도를 조절하여 수신자의 버퍼 오버플로우를 방지
- 송신하는 곳에서 감당이 안되게 많은 데이터를 빠르게 보내 수신하는 곳에서 문제가 일어나는 것을 방지
- 혼잡제어 )
- 네트워크 내의 패킷 수가 넘치게 증가하지 않도록 방지하는 것
- 정보의 소통량이 과다하면 패킷을 조금만 전송하여 혼잡 붕괴 현상이 일어나는 것을 막음 -> 속도를 제어, 천천히 속도를 올림
QUIC
: UDP를 기반으로 구현
-> 성능을 개선한 프로토콜
- UDP 자체는 신뢰성을 보장하지는 않지만, 추가적인 정의를 통해 신뢰성을 보장받을 수 있게 됨
- UDP + 패킷 재전송, 혼잡 제어, 흐름 제어 기능 등(직접 구현) = QUIC
- 최초 연결(1-RTT) : 연결에 필요한 정보를 한 번에 보냄
- 다음 연결(0-RTT) : 한 번 성공한 연결을 캐싱하고 다음 연결 때 캐싱된 정보를 사용함
- 연결 내 스트림이 완전히 독립적으로 동작 -> 하나가 실패해도 다른 스트림에 영향X
- IP 기반이 아니라 연결 별 고유 UUID(Connection ID)를 이용해 각 연결들을식별
-> TCP 기반에선 Wi-Fi에서 셀룰러 환경으로 이동하면 IP 주소가 변경되어 연결을 재수립해야 함
-> QUIC에서는 ID 기반이기 때문에 연결이 그대로 유지됨