우리는 웹에 있는 수많은 데이터들을 통해 정보를 얻습니다. 구글링을 통해 수많은 정보를 얻고, 유튜브에서 동영상을 통해 여러 사실들을 접하는 것처럼 말이죠. 우리에게 보여지는 이러한 정보들은 수많은 데이터로 이루어져 있습니다. 클라이언트(사용자)가 서버에 요청을 보내면 서버에서 응답으로 우리에게 필요한 데이터들을 보내줍니다. 브라우저에서는 이 데이터들을 조합하여 사용자가 볼 수 있는 화면으로 그려주게 됩니다 (렌더링). 우리는 브라우저가 렌더링해준 화면을 보고 정보를 얻게 되는 것이죠.
그렇다면 클라이언트와 서버에서는 어떻게 데이터를 주고 받을까요? 그것은 바로 이 게시물의 주제인 'HTTP' 입니다.
서버에서 데이터를 어떻게 받아오는지, 하나의 예시를 통해서 보여드리겠습니다. 아래의 캡쳐본은 네이버에 접속했을 때 서버로부터 데이터를 어떻게 받아오는지 크롬 개발자모드(F12)를 통해 확인한 모습입니다.
빨간색 네모 박스를 보시면 프로토콜에 'h2' 라고 되어있는 것을 확인하실 수 있습니다. h2는 HTTP 2.0 버전으로, HTTP 프로토콜을 통해 전송된 데이터라는 것을 의미합니다. 유형을 보시면 document (HTML)을 포함한 여러 script (JS) 파일, 이미지 파일 (png, jpeg ...) 등의 데이터가 모두 HTTP 프로토콜로 전송된다는 것을 알 수 있습니다.
HTTP 프로토콜은 웹상에서 정보를 주고 받을 수 있는 프로토콜이다.
💡 HTTP
HTTP란 Hyper Text Transfer Protocol 의 약자로써 W3 (WWW)상에서 정보를 주고 받을 수 있는 프로토콜입니다. 앞서 클라이언트에서 데이터를 요청하면 서버에서는 응답으로 데이터를 보내준다고 했었죠? 이렇게 동작하는 이유는 HTTP가 요청/응답 (request, response) 형태로 데이터를 전송하는 프로토콜이기 때문입니다. 데이터 요청을 보내고 (request), 수신한 요청에 대한 응답을 보내주는 (response) 방식으로 데이터를 전달하는 것이죠. 요청이 없다면 서버에서 먼저 데이터를 보내지 않는다는 것입니다.
HTTP는 HTML나 텍스트 데이터뿐만 아니라, image, 음성, 영상, 각종 파일, JSON, XML 등등 거의 모든 형태의 데이터를 전송 할 수 있습니다. 이러한 데이터들을 HTTP body에 담아서 보내면 됩니다. 심지어 서버간의 데이터들을 주고 받을 때도 대부분 HTTP 프로토콜을 사용한다고 하니, 지금은 대 HTTP 시대라고 볼 수 있습니다.
💦 HTTP 버전
HTTP의 버전은 다음과 같습니다.
- HTTP / 0.9 (1991) = HTTP가 문서화된 최초의 버전, GET 메서드만 지원하며 HTTP 헤더가 없었던 시절.
- HTTP / 1.0 (1996) = 다른 HTTP method와 헤더 추가.
- HTTP / 1.1 (1997) = 기능적으로 완성된 버전. 이후의 버전들은 성능 향상에 초점을 맞춤.
- HTTP / 2.0 (2015) = 기존 버전의 문제점과 성능 개선.
- HTTP / 3.0 (2022) = 구글에서 개발한 QUIC 프로토콜을 사용하여 데이터 전송.
- HTTP는 1991년 처음 문서화되어 등장하였으며 초기에는 GET 메서드만 있었고 응답 데이터 형태는 무조건 HTML 문서였습니다.
- 이후 점차 개선되어 1.1 버전에서 현재 사용하는 HTTP 의 형태를 갖추게 되었으며, 이후의 버전들은 요청/응답 데이터의 구조 개선보다는 성능 향상에 초점을 맞춘 버전입니다. 예전에는 HTTP/1.1 버전을 많이 사용하였지만 Head Of Line Blocking 과 같은 문제점들로 인해, 이를 개선한 HTTP/2 나 HTTP/3의 점유가 갈수록 커지고 있는 상황입니다.
- HTTP / 3.0에서의 가장 핵심적인 변화는 전송 프로토콜이 바뀌었다는 점입니다. 기존 HTTP/1.1 버전과 HTTP/2 버전은 TCP 프로토콜을 사용하였습니다. TCP는 신뢰성 있는 데이터 전송을 보장하지만, 3-way-handshake를 포함한 다양한 기능들의 제공으로 인해 UDP보다 상대적으로 헤더가 크고 전송 속도가 느리다는 단점이 있습니다.
따라서, 구글에서는 UDP를 기반으로한 QUIC 이라는 프로토콜을 개발하였고 이는 HTTP/3로 표준화 되었습니다. 기존 HTTP/2에 대비하여 Zero RTT, 패킷 손실에 대한 빠른 대응, 향상된 연결성 등의 장점을 가지게 되었고 전송 속도 또한 향상 되었습니다. HTTP/3를 지원하는 주요 웹 사이트로는 Google, Youtube, Facebook, instagram 등이 있습니다.
- HTTP/1.1 , HTTP/2 -> TCP 사용
- HTTP/3 -> UDP 기반의 QUIC 사용
📌 HTTP 특징
HTTP의 주요 특징을 간단하게 알아보겠습니다.
클라이언트 서버 구조
HTTP는 Request, Response 구조로 동작합니다. 클라이언트 (사용자)는 데이터를 요청하고 응답을 대기합니다. 서버는 요청에 대한 응답으로, 결과 (데이터)를 만들어서 클라이언트에게 보냅니다. HTTP는 요청/응답의 구조로 이루어져 있기때문에, 아래에서 살펴볼 HTTP 메시지의 형태도 요청과 응답이 조금씩 다릅니다. 예를 들어 HTTP 요청에서는 GET, POST 같은 HTTP method를 포함한 요청 정보들이 메시지에 포함되어있지만, 응답에서는 상태코드 (200, 404 ...) 를 포함한 응답 정보들이 담기는 것처럼 말이죠. 이 부분은 이후의 포스팅에서 알아보겠습니다.
무상태 프로토콜 (Stateless)
HTTP는 무상태 프로토콜입니다. 서버가 클라이언트의 상태를 보존하지 않는다는 의미입니다. 예를 들어, 쿠키나 세션, 토큰 같은 기능을 구현하지 않은 사이트에 로그인했다고 가정해보겠습니다. 로그인된 상태로 메일 서비스로 이동하면 로그인 된 상태를 보존하지 않기때문에 다시 로그인을 요청하는 페이지가 뜰 것입니다. HTTP는 클라이언트의 상태를 보존하지 않습니다. 따라서, 매 요청에 대해 첫 응답인 것처럼 동작합니다.
HTTP는 클라이언트의 상태를 보존하지 않기때문에 요청시마다 이전에 보냈던 데이터를 함께 보내주어야 합니다. 이러한 단점을 보완하기 위해 쿠키나 세션같은 기능들이 생겨났습니다. 쿠키는 서버에서 브라우저에게 보내주는 데이터로, 브라우저나 파일 형식으로 저장되며 요청시 매핑된 쿠키들을 자동으로 전송해주는 특징이 있습니다.
무상태 프로토콜의 장점은 스케일 아웃에 유리하다는 것입니다.
스케일 아웃(scale-out)이란 서버를 수평적으로 늘려 서버의 부하를 줄이는 방법입니다. 이에 최적의 성능을 내기 위해 서버의 부하(로드)를 고르게 분배(밸런싱)하는 로드밸런싱 기술을 적용하여 사용합니다. 스케일 업 (scale-up)은 서버 자체의 성능을 높이는 방법을 말합니다.
무상태 프로토콜의 특징으로 인해 클라이언트는 매 요청시 서버가 필요한 데이터를 보내줍니다. 따라서, 기존 요청을 처리하던 서버가 아닌, 다른 서버에게 요청이 가더라도 문제 없이 처리할 수 있습니다. 중간에 어떤 서버를 거치더라도 클라이언트의 요청을 동일하게 처리할 수 있기 때문에 스케일 아웃에 유리하다는 것입니다. 반대로 상태를 보존하는 프로토콜에서는 스케일 아웃에 불리하겠죠?
비연결성
HTTP 통신은 요청이 있을때만 연결을 유지하고, 이후 응답으로 데이터를 보내고 나면 연결을 종료하는 '비연결성'의 특징이 있습니다. 데이터 전송이 필요할 때에만 연결이 이루어지기 때문에, 실제 사용자가 수천명이여도 대비 서버에서 동시에 처리하는 요청은 수십개 이하로 매우 작아집니다. 따라서, 서버 자원을 매우 효율적으로 사용할 수 있습니다.
반대로 Socket 통신은 '연결성'의 특징을 가지고 있습니다. 클라이언트와 서버가 계속해서 연결을 유지하기 때문에 지속적으로 서버의 자원이 소모된다는 단점은 있지만 실시간으로 데이터를 주고받을 수 있다는 장점도 있습니다. 지속적인 연결을 유지하는 Socket 통신은 주로 실시간 스트리밍이나, 채팅, 온라인 게임 등에 주로 사용됩니다.
비연결성 특징의 한계와 극복
출처 - https://developer.mozilla.org/en-US/docs/Web/HTTP/Connection_management_in_HTTP_1.x
- 기존 HTTP 버전 1.0 이하에서는 함께 다운로드되는 수 많은 데이터들에 대한 각각의 TCP/IP 연결을 새로 맺었습니다. 따라서 아래 그림의 가장 왼쪽에 있는 것처럼 동작되어 매우 비효율적이었죠. 이러한 비 효율적 전송을 보완하기 위해 Persistent connection (지속 연결)이 도입되었습니다.
- Persistent connection은 요청이 있으면 클라이언트와 서버가 일정 시간동안 연결을 유지하도록 동작하는 것입니다. 따라서, 각 요청에 대한 연결을 설정하고 끊는 과정들이 사라져, 한 번의 연결로 여러 데이터를 보낼 수 있게 되었습니다.
- 이것에서 더욱 발전하여 HTTP Pipelining (파이프라이닝) 방식이 도입되었습니다. 기존에는 데이터 요청에 대해 순차적으로 응답을 받던 방식이였습니다. Pipelining은 요청에 대한 응답을 기다리지 않고 순차적인 여러 요청을 연속적으로 보내, 그 순서에 맞춰 응답을 받는 방식으로 동작합니다. 이에 따라, 데이터 요청/응답에 대한 지연 시간이 줄어들게 되었습니다.
🎯 HTTP 구조
HTTP 구조에 대해서는 해당 글을 참고하시면 됩니다.
2022.09.06 - [Web/HTTP] - HTTP의 구조
참고
https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard
- https://ko.wikipedia.org/wiki/QUIC
https://velog.io/@tkddn2075/%EB%A1%9C%EB%93%9C-%EB%B0%B8%EB%9F%B0%EC%8B%B1Load-Balancing