HTTP/2.0

HTTP/2.0

HTTP 완벽 가이드 10장 정리


개요


HTTP/2.0은 시간이 지날수록 늘어나는 네트워크 트래픽으로 인한 HTTP/1.1의 기술적 한계를 극복하기 위해 고안됐습니다.

2015년에 정식으로 승인된 최신기술로, 구글에서 HTTP/1.1의 한계를 극복하기 위해 제안한 스피디(SPDY) 에 기반하고 있다고 합니다.

HTTP/1.1은 요청을 한번 보내고 응답을 한번 받는다는 극강의 단순함으로 아주 견고한 프로토콜이지만, 이 단순한 구조로 인해 빠른 처리속도를 가지지는 못합니다.

웹 개발을 어느정도 해봤다면 다음과 같은 상황을 생각해 볼 수 있습니다.


  • 브라우저에 https://www.w3schools.com/ 를 입력합니다. (HTTP 커넥션 생성, HTTP 요청)
  • index.html 을 받습니다. (HTTP 응답, HTTP 커넥션 종료)
  • index.html 의 A 레이아웃에 필요한 여러 동적 데이터를 얻기 위해 자바스크립트로 오리진 서버에 데이터를 요청합니다. (HTTP 커넥션 생성, HTTP 요청)
  • 받아온 데이터를 index.html 의 A 레이아웃에 채워넣어 화면을 구성합니다. (HTTP 응답, HTTP 커넥션 종료)
  • index.html 의 B 레이아웃에 필요한 여러 동적 데이터를 얻기 위해 자바스크립트로 오리진 서버에 데이터를 요청합니다. (HTTP 커넥션 생성, HTTP 요청)
  • 받아온 데이터를 index.html 의 B 레이아웃에 채워넣어 화면을 구성합니다. (HTTP 응답, HTTP 커넥션 종료)



이렇게 단순히 웹 페이지 하나를 한번 로드하는데 값비싼 핸드셰이킹을 여러번 해야만 합니다.

왜? 한번의 요청을 보내면 한번의 응답을 받고 커넥션을 종료한다는 단순한 구조로인해서요.

이러한 문제들을 해결하기 위해 Keep-alive, Pipelining 등이 적용됐지만, 역시 각각 문제들이 있었습니다.

커넥션이 너무 많아져 서버에 부하가 많이 간다던가, 동기적인 처리로 인해 브라우저 렌더링에 지장이 생긴다든가 하는 문제(일명 HOL blocking 문제라고도 합니다.)들이요.


image

HTTP/1.1 Pipelining


그래서 HTTP/1.1로 통신할때 브라우저들은 한개의 커넥션만 사용하지 않고 여러개의 커넥션을 동시에 사용해 리소스를 받아옵니다.


image


HTTP/1.1로 이루어져 있는 우리나라 모 공공기관의 홈페이지에 접속해봤습니다.

단순히 메인 화면 하나를 로드하기 위해 많은 커넥션을 사용했고, 긴 시간동안 통신을 해야만 했습니다.

아래는 HTTP/2.0이 적용된 https://www.w3schools.com/에 접속했을 때의 결과입니다.

데이터의 밀도가 높아져 지연시간(Latency)이 대폭 감소된 것을 볼 수 있습니다.


image


HTTP/2.0


우선 이부분은 명확히 알고있어야 할 부분입니다.

HTTP/2.0에 대해 알아볼 때 가장 중요했던 부분은 기존 HTTP/1.1과의 하위호환성을 보장한다는 것이었습니다.

즉, HTTP/2.0을 적용 할 조건이 갖춰졌다는 가정하에 HTTP/1.1을 사용하고 있었다면 별 문제없이 업그레이드가 가능하다는 것입니다.

그럼 HTTP/2.0은 어떻게 이런 결과를 낼 수 있었을까요?


HTTP/2.0 역시 통신을 위한 커넥션을 맺습니다.

다만, 바이너리 프레이밍 계층이라는 것을 사용해 요청과 응답의 멀티플렉싱을 지원한다고합니다.


💡 멀티플렉싱이란? 하나의 통신 채널을 통해서 둘 이상의 데이터를 전송하는데 사용되는 기술이다. 기본적으로 멀티플렉싱이란 여러 개를 하나로 묶어 다중화 시킨다는 뜻이다.


99B5C5365B6460CD0D

프레이밍(Framing)


HTTP 메시지의 헤더와 바디를 바이너리 형태의 프레임(Frame)으로 나누고 이를 전송하고, 수신처에서 나눠 받은 프레임을 HTTP 메시지로 다시 조립합니다.

이렇게 요청과 응답이 동시다발적으로 이루어지니 하나의 커넥션에 여러 요청과 응답이 뒤섞여 있습니다.

하지만 프레이밍 작업은 기본적으로 서버와 클라이언트(=브라우저)에서 모두 해주기 때문에 큰 걱정을 하지않아도 됩니다.

즉, 바이너리 프레이밍멀티플렉싱을 이용해 여러 개의 커넥션 연결 없이 단 하나의 커넥션으로, 한쌍의 요청과 응답이 아닌 여러쌍의 요청과 응답을 동시다발적으로 처리할 수 있게됨과 동시에 기존 파이프라이닝의 HOL문제도 해결한 것입니다.


image

출처: 구글 개발자 페이지 - 바이너리 프레이밍 계층


한쌍의 요청과 응답은 하나의 스트림위에서 처리되며, 이 스트림은 커넥션에 여러개 존재할 수 있습니다. (병렬 스트림)

비유를 들자면, HTTP/1.1은 구리선이 하나만 들어있는 케이블이라고 볼 수 있고, HTTP/2.0은 구리선이 여러개 들어있는 케이블이라고 볼 수 있습니다.


또한 HTTP 헤더는 모두 압축되어 처리됩니다.


추가적으로 서버 푸시라는 것이 가능해지는데, 서버에서 임의의 요청에 대해 여러 리소스를 능동적으로 한꺼번에 응답해주는 것을 말합니다.

이 기능은 제가 사용하는 Spring Framework 5에서 도입됐으며(PushBuilder), 매우 당연하게도 HTTP2.0을 필요로 합니다.



크롬 시크릿 브라우저 세션에서 성능측정 페이지에 접속해 HTTP/1.1과 HTTP/2.0의 성능을 수차례 비교해보니 최대 100%까지도 차이가 나는것을 확인할 수 있었습니다.


image


HTTP/2.0 적용


HTTP/2.0을 적용하기 위해서는 HTTPS 적용 필수적이라고 하는데, 이미 HTTPS는 적용돼있었습니다.

저는 Nginx를 사용하고 있었는데, 관련 문서를 읽어보니 제가 사용하고있는 최신 버전의 Nginx에서는 HTTPS가 적용돼있다는 가정하에 키워드 하나만 추가하고 Nginx를 리로드 하는 정도에서 끝날정도로 아주 손쉬웠습니다.


image


image

HTTP/2.0 적용된 모습


문제점 ?


우선 제가 생각해본 문제점은 두개였습니다.


  1. 컴퓨팅 리소스를 지나치게 많이 사용하지는 않을지
  2. 커넥션 내의 스트림간 간섭문제는 없는지


1번에 대한 부분은 컴퓨팅 리소스를 더 사용해서라도 월등한 성능을 얻을 수 있다면 생각보다 큰 문제가 될 것 같다고 생각되진 않았습니다.


2번에 대한 부분은 별도의 내용을 찾지 못했는데, 개발사가 구글이니 아마 어떤 처리가 돼있지 않을까 조심스레 추측만 해보고 있는 상태입니다.

다만, 이 간섭으로 인한 데이터의 유출문제는 HTTP/2.0 적용을 위한 필수조건에 HTTPS 구축이 포함돼있어 별 문제가 되지 않을 것 같습니다.


HTTP/2.0의 목표


  • 클라이언트와 서버가 HTTP/1.1, HTTP/2.0 혹은 다른 비 HTTP 프로토콜 사용을 협상할 수 있는 메커니즘 구현
  • HTTP/1.1과 호환성 유지
  • 다음과 같은 방법들을 이용하여 지연 시간을 감소시켜 웹 브라우저의 페이지 로드 속도 개선
    • HTTP 헤더 데이터 압축
    • 서버 푸시 기술
    • 요청을 HTTP 파이프라인으로 처리
    • HTTP/1.x의 HOL blocking 문제 해결
    • TCP 연결 하나로 여러 요청을 다중화 처리
  • 데스크탑 브라우저, 모바일 웹 브라우저, 웹 API, 웹 서버, 프록시 서버, 리버스 프록시 서버, 방화벽, 콘텐츠 전송 네트워크 등 자주 쓰이는 것들을 지원


출처: 위키백과 HTTP2.0


참고


제가 사용하는 Spring Framework는 5부터 HTTP/2.0을 안정적으로 지원하며, 이 때 Tomcat은 8.5+ 이상이어야 합니다. 그외 Netty, Apache, Nginx 등도 모두 HTTP/2.0을 구현하여 지원하고 있음을 알 수 있습니다.




© 2022. All rights reserved.