HTTP/2는 무엇일까

pds·2023년 7월 30일
2
post-thumbnail

왜 Http2 프로토콜을 적용했는데 더 응답속도가 빨라진걸까?

lighthouse 경고를 보고 프론트엔드 서버에도 적용했고

백엔드 서버에도 적용을 요청드리고 서버사이드 렌더링 응답 시간 로그를 확인해보니 동시에 여러 api 요청을 하는 상황에 대한 응답시간이 튀는 상황이 거의 없어졌다.

왜 Http1.1을 Http2로 변경해서 사용해야하는지 궁금해서 간단하게 알아보았다.


HTTP, TCP

TCP는 서버와 클라이언트 간 신뢰성 있는 연결을 관리하기 위해 필요한 프로토콜로 전송 계층의 프로토콜이다.

HTTP는 웹 상에서 클라이언트와 서버가 통신을 하기 위해 필요한 애플리케이션 계층의 프토토콜(규칙)이며 TCP하에서 동작한다.

따라서 클라이언트가 서버에 HTTP로 요청(http/2 이하)하면 응답받기 전 전송 계층의 TCP를 반드시 거쳐야 한다고도 볼 수 있다.


TCP Handshake

클라이언트가 서버에 HTTP로 요청하면 TCP 계층을 거쳐야 한다고 했었다.

TCP는 신뢰성 있는 연결을 위해서 3-way-handshake라는 과정을 거친다.

tcp-3way-handshake

위와 같이 패킷을 주고받는 과정을 겨쳐서 연결이 수립된다면 데이터를 전송하게 된다.

심지어 연결을 종료할 때도 악수를 해야한다.

전송 순서 보장 등 신뢰성과 정확도 있는 데이터 송수신을 위해 필요한 과정이며 이로 인해 UDP 통신에 비해 속도가 느릴 수 있다.


Http 1.0

HTTP는 서버가 이전 요청의 상태를 저장하지 않기 때문에 클라이언트의 매 요청을 개별적인 것으로 보고 독립적으로 처리하여 응답한다.

즉 똑같은 클라이언트가 똑같은 요청을 계속 보내도 서버 입장에서는 같은지 알 수 없다는 것이다.

http 1.0 에서는 각각의 요청과 응답마다 별도의 TCP 연결을 생성하여 처리하기 때문에

잦은 요청에 응답속도가 저하될 수 있고 그만큼 서버 부하 비용도 발생하게 될 것이다.


Http 1.1

Http/1.1은 Http/1.0의 문제점을 개선하고 확장한 버전으로 다음과 같은 기능을 제공한다.

Keep-Alive Connection

지정한 타임아웃 시간동안은 TCP 연결을 닫지 않고 재사용할 수 있다.

연속적인 요청에 대해 연결을 유지햐 재사용하여서 새로운 TCP 핸드셰이크를 하는 비용을 아끼고
응답 성능 향상을 기대할 수 있다.

연결이 수립되어 keep-alive중인데 아무것도 하지 않으면 불필요하게 서버 리소스를 낭비하는 상황이 있을 수 있다.

nging-http1-1-keep-alive

nginx 1.18.0 버전 기준 기본으로 http1.1을 지원하고 keepalive-timeout이 65로 지정되어있다.

요청을 보내보면 Connection: keep-alive 라는 응답 헤더가 보인다!


Pipelining

하나의 커넥션에서 응답을 기다리지 않고 순차적인 여러 요청을 연속적으로 보낸 후
순서에 맞게 응답을 받는 방식으로 네트워크 지연을 줄일 수 있는 방식이다.


Head Of Line Blocking

HOL은 패킷 그룹이 라인의 첫 번째 패킷에 의해 대기열에 있을 때 발생하는 성능 문제 발생 현상이다.

결국 위의 Pipelining에서 요청한 순서에 맞게 응답을 해줘야 되기 때문에 앞선 순서의 요청의 응답 대기시간이 길어지게 된다면 이 HOL 문제가 발생할 수 있는 것이다.


Http/2

2015년에 출시된(HTTP/2 사양은 5월 14일에 RFC-7540) http/2 프로토콜은

다중화(multiplexing) 를 통해 하나의 TCP 연결 내에서 여러 요청과 응답을 동시에 처리할 수 있다.

이로써 여러 요청이 동시에 처리되면서 지연을 최소화시킬 수 있게 되었다고 한다.

가볍게 기존과 어떻게 다른지 알아보자

Binary Protocol

HTTP1.x는 요청에 대한 응답을 완료하기 위해 텍스트 형식의 메시지를 사용했다면
HTTP/2는 동일한 작업을 실행하기 위해 바이너리 명령(1과 0)을 사용한다.

바이너리 프레이밍 계층은 요청-응답을 바이너리로 변환하고 더 작은 청크로 나눠 양방향 통신 스트림을 형성한다.

각 스트림은 요청/응답 형태로 구성된 여러 메시지를 포함하며, 이 메시지들은 작은 단위인 프레임으로 분할된다.

컴퓨터 친화적으로 데이터 구문 분석의 오버헤드가 낮아지고 오류율이 적어지며 전송속도가 빨라질 가능성이 높아진다.


Multiplexing

HTTP/2 uses new technologies to take away one of the web’s biggest bottlenecks by introducing full multiplexing connections. Servers can now open a single connection with a browser and keep sending all a website’s files until everything is done. After that, the connection closes and the browser can render the site.

HTTP/2는 하나의 TCP 연결을 통해 데이터에 대한 여러 요청을 병렬로 보낼 수 있다.

HTTP/2는 하나의 연결에서 동시에 다양한 스트림을 열 수 있고, 연결 내에서 다른 스트림의 프레임을 할당할 수 있다.

여기서 프레임은 특정 유형의 데이터를 포함하는 통신의 최소 단위를 말한다.(HTTP Header, 메시지 등)

프레임은 서로 다른 스트림에서 교차(interleaved)되어 재조립되며, 각 프레임의 헤더에 포함된 내장된 스트림 식별자를 통해 구분된다.
교차되는 요청과 응답은 서로 뒤를 막지 않고 병렬로 실행되며, 한 메시지가 다른 메시지의 완료를 기다릴 필요가 없도록 보장하며, 이 방법론은 Multiplexing이라고 한다.

말이 어려운데 아무튼 중요한 것은 병렬처리를 통해 더 빠르게 데이터를 요청하고 전송하고 수신할 수 있다는 것이다.

웹 페이지의 리소스들이 병렬로 다운로드되며, 브라우저는 필요한 리소스를 비동기적으로 처리하여 로드 속도를 크게 향상시킬 가능성이 있다고 볼 수 있다.


Header Compression

HTTP/1.1 까지는 중복되는 헤더에 대한 문제가 있을 수 있었다.

헤더는 요청에 꽤 많은 양이 항상 포함되기 때문에 메시지 크기에 대해 많은 부분을 차지하고 이는 속도에도 영향을 줄 수 있다.

HTTP/1.1에서는 gzip과 같은 압축 소프트웨어를 통해 css, js등의 리소스 파일의 크기를 압축하여 전송량을 줄이는 것은 가능하지만

일반 헤더의 경우는 항상 일반 텍스트 형식으로 전송된다는 점이 문제였다고 한다.

계속되는 중복 요청에 대한 중복되는 헤더 정보로 인해 메시지 크기로 인한 네트워크 지연이나 대역폭 낭비에 영향을 줄 수 있는 것이다.

HTTP/2에서는 HPACK이라는 명세를 사용해 중복 헤더 프레임을 압축한다.
각 헤더의 개별값을 압축하고 서버로 전송한 다음 이전 전송 헤더 값 목록에서 헤더 정보를 조회해와 전체 헤더 정보를 재구성한다.

역시 말이 어려운데 요약하면 알아서 중복되는 헤더에 대한 처리나 최적화에 대한 작업을 수행하여 비용과 속도를 개선한다는 것이라고 볼 수 있다.


Stream Prioritization

리소스 간 우선순위를 지정할 수 있다.

애플리케이션 성능을 최적화하고 동일한 리소스에 대한 잠재적인 경쟁상태 발생 등을 고려하기 위해 가중치를 커스텀할 수 있는 기술이다.


Server Push

Server Push는 요청이 오지 않았지만 앞으로 요청에서 예상되는 캐시 가능한 추가정보를 클라이언트에 미리 보낼 수 있는 기능을 말한다.

ref-github-helospark/learning-http2-push-filter


결론

HTTP/2HTTP/1.1에서 발생할 수 있었던 성능 문제를 개선하기 위해 나온 버전이다.

기본적으로 해당 프로토콜을 적용할 경우 이득이 많으며 여러 커스텀 가능한 기능들(서버푸시, 우선순위 설정)을 활용해 더 최적화 할 수 있는 여지가 있다.

그러니 적용할 수 있으면 적용해야할 것 같다.

References

profile
강해지고 싶은 주니어 프론트엔드 개발자

0개의 댓글

관련 채용 정보