Http에 대해서
What is HTTP
웹상에서 클라이언트와 웹서버간 통신을 위한 프로토콜중 하나
HTTP/0.9
초기에는 버전 번호가 존재하지 않았지만, 이후 다른 버전들과 구분하기위해 0.9를 붙이게 되었다.
가장 초기버전 스펙이며 주요 기능으로는 아래와 같다
- method는 GET만 가능
- client - server 구조
- request - response 구조
HTTP/1.0
최초의 인기 브라우저 Mosaic가 탄생하고, 1994년 Netscape Navigator 1.0이 출시되면서 인터넷의 성장은 날이 갈수록 거대해졌다. 같은 해 W3C가 만들어지며 HTML의 발전을 도모하게 되었고, 이와 비슷하게 HTTP 프로토콜 개선에 초점을 맞추기 위해 HTTP-WG가 설립되었다. 마지막으로 1994~1995 기간에 전화 접속 인터넷 엑세스가 제공되기 시작하며 인터넷의 붐이 도래했다.
두번째 스펙인 1.0의 주요 기능은
- 버전 정보가 각 요청 사이내로 전송되기 시작 (HTTP/1.0 이 GET 라인에 붙은 형태로)
- 상태 코드 라인 또한 응답의 시작 부분에 붙어 전송, 브라우저가 요청에 대한 성공과 실패를 알 수 있고 그 결과에 대한 동작을 할 수 있게 되었다.
- HTTP 헤더 개념은 요청과 응답 모두를 위해 도입되어, 메타데이터 전송을 허용하고 프로토콜을 극도로 유연하고 확장 가능하도록 만들어주었다.
- 새로운 HTTP 헤더의 도움으로, 평이한 HTML 파일들 외에 다른 문서들을 전송하는 기능이 추가되었다. (Content-Type)
HTTP/1.1
HTTP / 1.1 표준은 이전 버전에서 발견 된 많은 프로토콜 모호성을 해결하고 keep-alive 연결, chunk encoding 전송, 바이트 범위 요청, 추가 캐싱 메커니즘, 전송 인코딩 및 요청 파이프 라이닝과 같은 여러 중요한 성능 최적화를 도입했다. 좀더 보완된 특징은 다음과 같다.
- 커넥션이 재사용될 수 있게 하여, 탐색된 단일 원본 문서 내로 임베드된 리소스들을 디스플레이하기 위해 사용된 커넥션을 다시 열어 시간을 절약하게 하였다.
- 파이프라이닝을 추가하여, 첫번째 요청에 대한 응답이 완전히 전송되기 이전에 두번째 요청 전송을 가능케 하여, 커뮤니케이션 레이턴시를 낮췄다.
- 청크된 응답 또한 지원된다.
- 추가적인 캐시 제어 메커니즘이 도입되었다.
- 언어, 인코딩 혹은 타입을 포함한 컨텐츠 협상이 도입되어, 클라이언트와 서버로 하여금 교환하려는 가장 적합한 컨텐츠에 대한 동의를 가능케 했다.
- Host 헤더 덕분에, 동일 IP 주소에 다른 도메인을 호스트하는 기능이 서버 코로케이션을 가능케한다.
기본적으로 Http 1.1은 하나의 커넥션에 하나의 요청을 처리하도록 설계되었다. 때문에 동시에 여러개의 리소스를 주고받는 것이 불가능하고 요청과 응답이 위 그림처럼 순차적으로 이루어진다. 이런 설계 방식 때문에 HTTP 문서 내에 포함된 다수의 리소스 (image, css, script)를 처리하려면 요청할 리소스 개수에 비례하여 Latency(대기시간)이 길어진다.
단점으로는 크게 3가지가 있다.
- HOL(Head Of Line) Blocking - 특정 응답의 지연
HTTP/1.1의 경우 HOL Blocking이 발생할 수 있다. HOL (Head-Of-Line) 블로킹이란 네트워크에서 같은 큐에 있는 패킷이 첫 번째 패킷에 의해 지연될 때 발생하는 성능 저하 현상을 말한다. 웹 환경에서의 HOL 블로킹은 패킷 처리 속도 지연 뿐만 아니라 최악의 경우 패킷 드랍까지 발생할 수 있다.
웹 환경에서의 HOLB는 두 가지 종류가 있다. 첫 번째는 HTTP의 HOLB, 두 번째는 TCP의 HOLB이다. 먼저 HTTP 프로토콜에서 발생할 수 있는 HOLB에 대해 살펴보자.
- HTTP에서의 Head-Of-Line Blocking HTTP/1.1의 ‘Connection 하나 당 하나의 요청을 처리하는’ 방식을 개선할 수 있는 개선 방법 중 pipelining이라는 것이 존재한다. 이것은 하나의 connection을 통해 여러 개의 파일을 요청/응답할 수 있는 기법을 말하는데 이 기법을 통해 어느 정도의 성능 향상을 꾀할 수 있지만 한 가지 문제점이 있다. 아래 예시처럼 하나의 TCP 연결에서 3개의 이미지를 얻으려고 하는 경우 HTTP 요청 순서는 다음 그림과 같다.
| --- a.png --- |
| --- b.png --- |
| --- c.png --- |
순서대로 첫 번째 이미지를 요청하고 응답받고 두 번째, 세 번째도 마찬가지로 처리하는데 첫 번째 이미지의 응답 처리가 완료하기 전까지 b.png, c.png에 대한 요청은 대기하게 된다. 이와 같은 현상을 HTTP/1.1의 Head of Line Blocking이라 부르며 파이프 라이닝의 가장 큰 문제점 중 하나이다.
- TCP에서의 Head-Of-Line Blocking TCP에서의 HOLB는 HTML/2에서도 나타나는 단점으로서 TCP의 고질적인 문제이다. TCP의 경우 패킷 LOSS가 발생하면 패킷을 재전송하게 되는데 패킷 전송 후 상대방으로부터 ACK 신호를 받지 못하면 전송한 다음 번에 패킷들을 전송하지 않고 모두 대기 상태로 두고 이전에 보냈던 패킷을 재전송한다. 이러한 특성 때문에 TCP를 사용하게 될 경우 어쩔 수 없이 Head-Of-Line Blocking 문제가 발생하게 된다.
-
RTT(Round Trip Time) 증가 HTTP/1.1의 경우 일반적으로 Connection 하나에 요청 한 개를 처리한다. 이렇다보니 매번 요청 별로 Connection을 만들게 되고 TCP 상에서 동작하는 HTTP의 특성상 3-way Handshake가 반복적으로 일어나며, 불필요한 RTT증가와 네트워크 지연을 초래하여 성능을 지연시킨다.
-
무거운 Header 구조 HTTP/1.1의 헤더에는 많은 메타 정보들이 저장되어 있다. 클라이언트가 서버로 보내는 HTTP 요청은 매 요청 때마다 중복된 헤더 값을 전송하게 되며 서버 도메인에 관련된 쿠키 정보도 헤더에 함께 포함되어 전송된다. 이러한 반복적인 헤더 전송, 쿠키 정보로 인한 헤더 크기 증가가 HTTP/1.1의 단점이다.
이러한 단점들을 개선하기 위한 많은 노력들이 있다.
-
Image Spriting 웹 페이지를 구성하는 다양한 아이콘 이미지 파일의 요청 횟수를 줄이기 위해 아이콘을 하나의 큰 이미지로 만든 다음 CSS에서 해당 이미지의 좌표 값을 지정하여 표시한다.
-
Domain Sharding 요즘 브라우저들은 HTTP/1.1의 단점을 극복하기 위해 여러 개의 Connection을 생성해서 병렬로 요청을 보내기도 한다. 하지만 브라우저 별로 도메인당 Connection의 개수 제한이 존재하기 때문에 근본적인 해결책은 아니다.
-
Minified CSS/Javascript HTTP를 통해 전송되는 데이터의 용량을 줄이기 위해서 CSS, Javascript를 축소하여 적용한다. name.min.js, name.min.css 등이 그 예이다.
-
Data URI Scheme 이 방법은 HTML 문서 내에 이미지 리소스를 Base64로 인코딩된 이미지 데이터로 직접 기술하는 방법으로 이를 이용하여 서버로의 요청을 줄이는 방식이다.
HTTP/2.0
이러한 개선 방법들로도 근본적인 문제를 해결하기 어려웠기에 대안으로 구글에서 SPDY라는 새로운 프로토콜을 만들었다.
이 새로운 프로토콜은 HTTP/2.0의 시작이되었다.
HTTP/2는 HTTP/1.1을 완전하게 재작성한 것이 아니라 프로토콜의 성능에 초점을 맞추어 수정한 버전이라 생각하면 된다. 특히 End-user가 느끼는 latency나 네트워크, 서버 리소스 사용량 등과 같은 성능 위주로 개선했다. 아래는 HTTP/2의 주요 특징들이다.
- Stream, message and frame 클라이언트와 서버간에 데이터 교환 방법이 변경되었다. 설명하기 전에 용어를 정리해보자면
- 스트림
- 구성된 연결 내에서 전달되는 바이트의 양방향 흐름이며, 하나 이상의 메세지가 전달 가능함
- 메세지
- 요청 / 응답에 해당하는 프레임의 전체 시퀸스
- 프레임
- HTTP/2 통신에서의 최소 단위이며, 각 프레임에는 하나의 프레임 헤더가 포함된다.
간단하게 요약하자면
- 스트림은 하나 이상의 메세지를 전송한다
- 하나의 HTTP Request / Respone 는 하나의 메세지에 해당한다
- 메세지는 한 개 또는 여러 개의 프레임으로 구성될 수 있다
- 각 프레임은 프레임 헤더를 가지고 있으며, 프레임 헤더를 이용하여 어느 스트림에 속하는 지를 알아낸다
따라서 아래와 같은 특징들을 갖게 된다.
- 모든 통신은 단일 TCP 연결을 통해 이뤄질 수 있고, 스트림의 개수는 제한이 없다
- 각 스트림은 고유 식별자와 우선순위 정보(선택사항) 이 있다
- 프레임은 통신의 최소 단위이다. TCP가 데이터를 쪼개서 보낸 다음 헤더를 보고 재조립 하는것과 비슷하다.
기존 HTTP 는 Body가 문자열로 이루어져 있지만, HTTP 2.0 부터는 binary framing layer 라고 하는 공간에 이진 데이터로 전송된다.
HTTP Req Method, 헤더 등은 여전히 문자열로 전송되지만, 밑 바디 부분이 변경되는 것이 가장 큰 변경점 중 하나다.
- Multiplexed Streams HTTP/2는 Multiplexed Streams를 이용하여 Connection 한 개로 동시에 여러 개의 메시지를 주고 받을 수 있으며 응답은 순서에 상관없이 Stream으로 주고 받는다. HTTP/1.1의 Connection Keep-Alive, Pipelining의 개선 버전이라 보면 된다.
1.0 에서 1.1으로 넘어오며 pipelining 기술을 도입하였지만, 여전히 HOL(Head-of-line) Blocking 문제가 있다. HOL blocking 은 패킷이 순서대로 도착해야 하므로, 패킷이 도착할 때 까지, 그 이후의 패킷은 전송되지 못하는 것을 의미한다.
이 특징으로 개선된 효과는 아래와 같다
- 여러 요청/응답을 병렬로 처리 (하나의 TCP 연결에 여러 스트림 사용)
- TCP 연결이 1개이므로 3-way-handshake 오버헤드가 없음
- 네트워크 가용성 증가로 속도 상승 및 이미지 스프라이트 등을 사용하지 않아도 됨
- Stream Prioritization 문서 내에 CSS 파일 1개와 이미지 파일 2개가 존재하고 이를 클라이언트가 요청하는 상황에서, 이미지 파일보다 CSS 파일의 수신이 늦어진다면 브라우저 렌더링에 문제가 생기게 된다. HTTP/2에서는 이러한 상황을 고려하여 리소스 간의 의존관계에 따른 우선순위를 설정하여 리소스 로드 문제를 해결한다.
- Server Push 서버는 클라이언트가 요청하지 않은 리소스를 사전에 푸쉬를 통해 전송할 수 있다. 이렇게 리소스 푸쉬가 가능해지면 클라이언트가 추후에 HTML 문서를 요청할 때 해당 문서 내의 리소스를 사전에 클라이언트에서 다운로드할 수 있도록 하여 클라이언트의 요청을 최소화할 수 있다.
- Header Compression 클라이언트가 요청을 두 번 보낸다고 가정할 때 HTTP/1.x의 경우 헤더 중복이 발생해도 중복 전송한다. 하지만 HTTP/2에서는 헤더에 중복이 있는 경우 Static/Dynamic Header Table 개념을 이용하여 중복을 검출해내고 해당 테이블에서의 index값 + 중복되지 않은 Header 정보를 Huffman Encoding 방식으로 인코딩한 데이터를 전송한다.
참고
- https://developers.google.com/web/fundamentals/performance/http2?hl=ko
- https://seokbeomkim.github.io/posts/http1-http2/
- https://velog.io/@zzzz465/HTTP1.1-2-3-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90
- https://www.whatap.io/ko/blog/38/