HTTP/2 - HyperText Transfer Protocol (Version 2) 을 자세히 알아보자
HTTP/2 는 HTTP/1.1 보다 성능을 개선한 프로토콜입니다. HTTP/2 는 성능 개선에 집중하여 개발되었으며, 성능을 개선시킬 수 있는 기능들이 추가되었습니다. 기능이 추가되었다 해서 HTTP/1.1 의 URL 이나 Method 와 Header 같은 의미와 연관된 부분은 달라지지 않았습니다. 기존에 사용하던 메서드 (GET, POST 등) 와 헤더 (Content-Type, Authorization 등) 는 HTTP/2 에서도 HTTP/1.1 과 동일하게 사용 가능합니다. HTTP/2 는 클라이언트와 서버 간에 데이터를 주고 받는 과정과 네트워크를 통해 전달할 데이터의 형태를 집중적으로 개선하였습니다.
HTTP/2 가 성능 개선에 집중한 이유는 최근 웹을 베이스로 하여 데이터를 전송하는 트래픽이 기하급수적으로 증가했기 때문입니다. 이에 대응하기 위해서 Google 은 선제적으로 SPDY 라는 프로토콜을 개발하여 사용했고, SPDY 는 Google 이 HTTP/2 설계에 참여함으로 HTTP/2 에 녹아들게 되었습니다.
이제 HTTP/1.1 과 달라진 HTTP/2 에 대해 하나씩 설명드리겠습니다.
Binary message framing 바이너리 메세지 프레임
HTTP/2 는 HTTP/1.1 과 다르게 메세지를 텍스트 포맷이 아닌 바이너리 포맷으로 인코딩합니다. 데이터의 포맷이 변경되었기 때문에 당연히 클라이언트와 서버가 포맷을 변경하는 코드를 구현해야 합니다. 하지만 클라이언트는 브라우저에서 이미 처리하기 때문에 신경쓰지 않아도 되고, 서버는 프레임워크가 이미 구현했기 때문에 신경쓰지 않아도 됩니다. 즉 내부적으로 포맷을 변경하기 때문에 개발자는 신경 쓰지 않아도 됩니다. HTTP 프로토콜을 사용할 TCP 소켓을 개발한다면 구현해야 합니다.
Multiplexing 멀티플랙싱
HTTP/1.1 의 경우, 동기로 동작하는 코드와 같이 요청 하나를 보내고 응답을 기다린 뒤 응답이 오면 다음 요청을 하는 방식으로 동작합니다. 즉 응답이 올 때까지 대기하게 됩니다. 만약 앞서 요청한 리소스의 응답이 오래 걸리면 오래 대기하게 됩니다. HTTP/1.1 은 대기가 길어지지 않도록 하기 위해 요청할 리소스가 많으면 여러 TCP 연결을 만들어 리소스를 요청하는 방식으로 해결했습니다.
HTTP/2 에서는 하나의 TCP 연결에 여러 리소스를 쪼개서 요청하고 응답도 나눠서 받을 수 있습니다. 이처럼 하나의 TCP 채널을 통해서 여러 데이터를 주고 받는걸 Multiplexing 멀티플렉싱 이라 합니다. 바이너리 메세지 프레임을 사용하면 메세지를 나누는게 가능해집니다. 즉 메세지를 프레임 단위로 나눠서 사용할 수 있습니다. 그러면 비동기 코드와 같이 통신이 가능해지기 때문에 HTTP/1.1 에서 발생하던 대기를 획기적으로 줄일 수 있습니다. HTTP/2 에서는 여러 리소스를 요청한 뒤, 메세지를 나눈 프레임이 모여 하나의 메세지를 만들 수 있게 되면 바로 사용할 수 있습니다. 만약 앞서 요청한 리소스의 응답이 오래 걸리더라도, HTTP/1.1 처럼 기다리는게 아니라 나중에 요청한 리소스의 응답을 계속 받아 대기하는 동안 다른 리소스를 활용할 수 있습니다. 즉 HTTP/2 는 HTTP/1.1 보다 대기가 줄어들게 되어 성능이 향상됩니다.
멀티플랙싱이 가능해져서 HTTP/1.1 처럼 여러 TCP 연결을 만들지 않아도 됩니다. 즉 HTTP/2 에서는 도메인 하나당 하나의 TCP 연결만 유지할 수 있습니다. TCP 는 신뢰성이 있는 데이터의 전송을 위한 프로토콜이기 때문에 연결을 만들고 해제하는데 오버헤드가 많습니다. 그런데 HTTP/1.1 에서는 TCP 를 마치 UDP 처럼 리소스 하나의 요청과 응답으로만 사용했었습니다. 심지어 여러 리소스를 병렬로 요청하기 위해 한번에 여러 TCP 연결을 만들기도 합니다. 따라서 필연적으로 서버는 여러 클라이언트로부터 TCP 연결 요청을 처리하고 유지하고 해제하는 등의 부하가 심각했습니다. 특히 보안을 위해 TLS 연결을 하게 되면 부하는 더욱 심각해집니다. 따라서 TCP 연결을 하나로 유지할 수 있다는건 중요합니다.
Stream prioritization 스트림 우선순위 부여
바이너리 메세지 프레임를 사용해 하나의 TCP 연결 내에서 멀티플랙싱이 가능해지자, 어느 리소스부터 전송할지가 중요해지게 됩니다. 예를 들어, 리소스 A 와 리소스 B 가 있을 때 만약 리소스 A 는 리소스 B 가 있어야 사용할 수 있다면, 리소스 A 를 먼저 전달받더라도 리소스 B 가 없어서 활용할 수가 없습니다. 그래서 HTTP/2 에서는 리소스를 전달하는 통로인 스트림에 우선순위를 부여할 수 있고, 스트림 간에 종속 관계를 설정할 수 있도록 설계되었습니다. 서버는 스트림의 우선순위와 종속 관계를 바탕으로 어느 리소스부터 응답할지를 결정합니다.
여기서 주의해야 할 사항은 클라이언트가 어느 리소스부터 응답받고 싶은지를 스트림의 우선순위와 종속 관계로 표현할 수는 있지만, 서버가 어떻게 반응할지는 서버 마음대로 라는 점입니다. 즉 클라이언트는 서버의 응답 순서를 강제할 수 없고, 어느 리소스부터 응답받을지는 보장할 수 없습니다. 왜냐하면 요청한 리소스를 처리하는데 얼마나 걸리는지를 판단할 수 있는건 클라이언트가 아니라 서버이기 때문에 우선순위가 높은 리소스를 처리하는데 시간이 오래걸린다면, 우선순위가 낮은 리소스라도 응답해야 성능상 유리하기 때문입니다.
Flow control 흐름 제어
흐름 제어는 네트워크 내에서 혼잡을 제어하기 위해 필수적인 기능입니다. 원래 TCP 프로토콜에 흐름 제어 기능이 들어가 있지만, HTTP/2 는 하나의 TCP 연결을 멀티플랙싱해서 사용하기 때문에 TCP 의 흐름 제어 기능만으로는 충분하지 않습니다. 그래서 HTTP/2 자체적으로 흐름 제어 기능이 추가되었습니다. TCP 흐름 제어 기능과 동일하게 HTTP/2 흐름 제어 기능도 슬라이딩 윈도우 기법을 사용하기 때문에 윈도우 크기로 흐름을 제어할 수 있습니다.
Server push 서버 푸시
서버 푸시는 HTTP/2 에 새롭게 추가된 강력한 기능입니다. 서버가 클라이언트의 요청 하나에 여러 응답을 할 수 있는 기능입니다. HTTP/1.1 에서는 서버가 클라이언트의 요청이 없는 리소스를 전송할 수가 없었습니다. 예를 들어, 클라이언트가 index.html 을 요청했다면 index.html 이 포함하고 있는 리소스도 요청할 거라는 걸 서버는 알고 있지만 클라이언트가 요청할 때까지 기다려야 합니다. 서버 푸시는 이를 개선한 기능으로 하나의 요청에 관련된 리소스를 함께 응답할 수 있도록 하는 기능입니다. 기능의 동작을 구체적으로 설명하자면, 서버는 클라이언트의 요청을 받고 응답할 때 함께 푸시해줄 리소스 목록을 같이 전달해서 클라이언트가 불필요한 요청을 하지 않도록 해 성능을 개선합니다. 그리고 서버 푸시는 강제가 아니기 때문에 클라이언트가 원하다면 서버의 제안을 거절하거나 무시할 수 있습니다.
Header compression 헤더 압축
헤더 압축 기능은 이름 그대로 HTTP 헤더를 압축하는 기능입니다. 먼저 각 HTTP 헤더 필드를 Huffman 코드로 인코딩하여 전송 크기를 줄입니다. 그리고 클라이언트와 서버 양쪽에서 HTTP 헤더에 대한 기록을 유지해서 이전에 전송한 프레임에서 동일하게 사용하는 헤더는 전송하지 않습니다. 즉 프레임 간 동일한 헤더를 중복해서 전송하지 않아 성능을 개선합니다. 헤더 압축은 HPACK 알고리즘으로 구현되었습니다.
참고자료
ietf.org RFC 7540
httpwg.org RFC 7540
Web Fundamentals Introduction to HTTP/2
D2 SPDY는 무엇인가?
'Develop > Frontend 가이드' 카테고리의 다른 글
[FE] Web API - Client-side storage : 쿠키 Cookie (0) | 2021.05.09 |
---|---|
[FE] Typescript - Type Guard 타입 가드 (0) | 2021.05.05 |
[FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (2/2) (0) | 2021.04.03 |
[FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (1/2) (0) | 2021.04.02 |
[FE] 브라우저 렌더링 Browser rendering - 5단계 변경 'change' (4) | 2021.03.31 |
꾸준히 노력하는 개발자 "김예건" 입니다.