이전 포스팅에 HTTP에 관한 전반적인 개요를 공부하고 정리하였으나, HTTP의 발전 중 큰 변화가 있었던 HTTP/2가 이전 버전과 어떻게 다른지에 대하여선 공부하지 않았었다. 그래서 이번 포스팅엔 HTTP/2가 HTTP/1.1과 비교해서 어떤 점들이 다른지 돌아보고 정리한 내용을 담으려고 한다.
이전글:
2021.10.01 - [Learn to Code] - HTTP란?
개요
HTTP/1.1은 90년대에 나온 버전으로, 20년도 더 된 아주 오래된 버전이다. 시간이 흐르면서 웹사이트들은 발전했고, 이에 맞춰 HTTP에 요구되는 개선 필요 사항들도 여럿 생겨났다. 이에따라 더 현대화된 웹에 맞춰 HTTP를 개선하고자 하는 수요가 생겼고, 이에 대한 결과물로 2015년에 HTTP/2가 공식적으로 표준화되어 나오게 된 것이다.
사람들이 원했던 HTTP/1.1에서 개선했으면 좋을 사항들은 아래와 같았다. 이 사항들은 자연스럽게 HTTP/2가 해결하고자 하는 목표가 되었다:
- Latency 감소
- 네트워크 통신에 필요한 데이터량 감소
- 서버에서 클라이언트로 먼저 데이터를 보낼 수 있는 방법
HTTP/2는 이러한 문제 사항들을 아래와 같은 솔루션으로 해결했다:
- Latency 감소 => 멀티플렉싱(Multiplexing)
- 네트워크 통신에 필요한 데이터량 감소 => 헤더 압축 (header compression)
- 서버에서 클라이언트로 먼저 데이터를 보낼 수 있는 방법 => 서버 푸시(server push)
멀티플랙싱 (Multiplexing)
HTTP/1.1에서 웹의 성능 향상을 위해 다중 병렬 요청을 하고 싶은 경우엔, 여러 개의 TCP 연결을 사용해야만 했다. HTTP/1.x의 delivery model에 따라 하나의 연결 당 한 개의 응답만 보낼 수 있도록 설계되어 있었기 때문이다. 이는 연결 지향 프로토콜인 TCP를 효율적으로 사용하는 방법이 아니었으며, head-of-line blocking 이슈를 야기했다. head-of-line(HOL) 블로킹은 앞서 보내진 패킷의 처리가 지연됨에 따라 뒤에 전달되어야 할 패킷들에 대한 처리가 지연되는 현상을 뜻한다.
HTTP/2에선 이러한 문제를 해결하고자 binary framing layer(바이너리 프레이밍 계층)를 추가했다. 이 새로운 바이너리 프레이밍 계층은 http 메시지가 클라이언트와 서버 사이에서 어떻게 캡슐화되고 전송되는지에 관여한다. 더 구체적으론, 이를 통해 HTTP/2는 http 메시지를 독립적인 개별 프레임(frame) 단위로 나누고, 이들을 상호배치(interleave)하여 전송한 뒤 목적지에 도착하였을 때 재조립하는 방식을 사용한다.
이에 따라, HTTP/1.1엔 없었지만 HTTP/2에 추가된 새로운 용어들이 생겨났다:
- 스트림(stream): 생성된 하나의 커넥션 내 데이터의 양방향 흐름. 하나의 스트림은 한개 또는 그 이상의 메시지(message)를 가지고 있을 수 있다.
- 메시지(message): 논리적 요청 또는 응답 메시지에 매칭되는 프레임(frame)의 완전한 시퀀스.
- 프레임(frame): HTTP/2에서 사용되는 커뮤니케이션 단위 중 가장 작은 단위(unit). 각 프레임은 각자의 프레임이 어떤 스트림에 속하는지 나타내는 정보를 가진 프레임 헤더(frame header)를 지니고 있음.
정리하자면, HTTP/2는 HTTP 메시지들을 프레임이라는 단위로 잘라서 전송하는 방식을 택하며, 이 각 프레임들은 특정 스트림에 속하는 메시지와 연결된다. 이 모든 프로세스는 한 개의 TCP 커낵션 상에서 발생하는데, 그래서 이를 multiplexing이라고 칭하는 것이다. 이러한 멀티플렉싱 방법을 도입함으로서 HTTP/2는 이전 버전보다 월등히 높은 성능을 자랑할 수 있었다.
헤더 압축 (Header compression)
HTTP/1.1에선 헤더가 플레인 텍스트였다. 즉, 사람이 그냥 눈으로 읽을 수 있는 글자들이었다. 이 헤더의 용량은 매 요청마다 약 500 - 800 바이트 정도가 된다고 하는데, 여기에 만약 쿠키가 좀 더 있다면 KB 단위로까지 증가할 정도로 사이즈카 컸다(왕대가리). 웹이 점점 발전할수록, 서버에 요청하는 건수는 점점 늘어났다. 그렇기 때문에 이 무거운 헤더들이 점점 더 큰 부담으로 다가오게 될 수 밖에 없었다.
HTTP/2는 이러한 왕대가리 문제를 해결하기 위해 헤더를 압축(compress)하는 방식을 도입했다. HTTP/2에선 HPACK이라는 압축 형식을 사용해서 요청 및 응답 헤더의 메타 데이터를 압축한다. 이를 통해, 개별 http 메시지의 용량이 크게 줄어들 수 있었다.
서버 푸시(Server push)
서버 푸시(Server push)란 클라이언트의 요청이 한 개 였음에도 불구하고 여러개의 응답을 보낼 수 있는 서버의 기능을 뜻한다.
이런 기능은 왜 필요할까? 효율성 때문이다. 예를 들어, 유저가 웹사이트에 접속해서 html 파일을 받고, 그 파일을 읽어감에 따라 그 웹앱을 방문하는데 필요한 추가 CSS 파일이나 JS 파일이 있다는 것을 인지하면 그 추가 리소스들을 위한 요청을 또 보내게 된다.
한편, 서버는 "아 얘가 지금 이 html 파일을 요청했으니 이제 이러이러한 파일을 또 달라고 하겠네~?"하는 정보를 갖고 있을 것이다. 그래서, 서버 푸시 기능이 있는 HTTP/2에선 서버가 "이게 추가로 더 필요할 걸 아는데 괜히 요청 더 보내지 말고, 내가 그냥 먼저 줄게~~"해서 불필요한 통신량을 미리 예방할 수 있게 되어 효율성이 증가하게 된다.
Reference
https://developers.google.com/web/fundamentals/performance/http2
https://developer.mozilla.org/en-US/docs/Glossary/HTTP_2
'Learn to Code' 카테고리의 다른 글
레이지로딩(lazy loading)이란? (0) | 2023.07.27 |
---|---|
[JS] 이벤트룹 (Event loop), 힙(Heap), 콜 스텍(Call stack) (2) | 2021.11.18 |
[JS] apply, call, bind (0) | 2021.10.21 |
[JS] 클래스(class): 정적 메소드(static method)와 프로토타입 메소드(prototype method)의 차이 (1) | 2021.10.04 |
[TIL] 갑자기 달력이 만들고 싶어졌다 (바닐라JS) (0) | 2021.10.03 |
댓글