TCP 기반 HTTP?

maketheworldwise·2022년 3월 13일
1


이 글의 목적?

쿠키와 세션에 대해 정리하면서 HTTP는 TCP 기반으로 구성되어있는데, 왜 비연결형이라고 하는지에 대해서 의문이 들었다. HTTP에 대해 정리해보자.

OSI 7 Layer

간략하게 OSI 7 Layer를 이미지로 살펴보자.

데이터에는 모든 계층을 지나면서 각 계층마다 패킷이 붙게 된다.

💡 서버에 보낼 데이터와 어떤 프로토콜 방식을 사용할지에 대해 헤더가 붙게 되고, 이를 패킷이라고 한다.

UDP? TCP?

TCP/IP의 전송계층에서 사용되는 프로토콜인 UDP와 TCP에 대해 간단하게 특징만 정리해보자.

TCP

  • 연결형 서비스로 가상 회선 방식을 제공 (전이중, 점대점 방식)
  • 3-way handshaking을 통해 연결을 설정하고 4-way handshaking을 통해 연결을 해제
  • 신뢰성 있는 데이터 전송을 보장
  • 흐름 제어 및 혼잡 제어를 수행
  • UDP보다 속도가 느림
  • 서버와 클라이언트는 1대 1로 연결
  • 스트림 전송으로 전송 데이터의 크기가 무제한

UDP

  • 데이터 방식으로 데이터를 처리하는 비연결형 프로토콜
  • 신뢰성이 낮음
  • TCP보다 속도가 빠름
  • 소켓 대신 IP를 기반으로 데이터를 전송
  • 서버와 클라이언트는 1대 1, 1대 N, N대 M 등으로 연결 가능
  • 데이터그램(메시지) 단위로 전송되며 그 크기는 65535바이트로 크기가 초과되면 잘려서 전송
  • 혼잡 제어와 흐름 제어를 수행하지 않음

💡 UDP에 비해 TCP가 느린 이유는 뭘까?

  • 물리적인 거리 문제
  • 주고 받는 패킷이 많음 (3-way-handshake, 4-way-handshake)

💡 Connection이 맺어졌다는 것은 무슨 의미일까?

(참고 : https://docs.oracle.com/javase/tutorial/networking/sockets/definition.html)

Connection이 맺어졌다는 것은 우리가 가지고 있는 장비의 포트까지 연결이 된 상태를 의미한다. 즉, 서버측의 포트 정의와 클라이언트의 포트 정의가 된 것을 뜻한다. (자바에서는 Connection을 Socket이라고 하는데, Connection이 맺어졌다는 것은 Socket이 맺어졌다는 의미와 같다.)

TCP와 HTTP의 관계

그래서 TCP는 연결지향인데 HTTP는 왜 비연결성일까? 🤔

기본적으로 HTTP는 TCP 기반으로 만들어졌다. 하지만 OSI 7 Layer에서 확인해보면, TCP는 4계층, HTTP는 7계층에 속해있는 것을 알 수 있다.

TCP는 기본적으로 연결을 유지한다. 연결을 유지하는 모델에서는 클라이언트가 요청을 보내지 않더라도 계속 연결을 유지해야한다. 이러한 경우 연결을 유지하는 서버의 자원이 계속 소모된다.

반면, 비연결성을 가지는 HTTP에서는 실제로 요청을 주고 받을 때만 유지하고 응답을 주고나면 연결을 끊는다. 이를 통해 최소한의 자원으로 서버 유지를 가능하게 한다.

적절한 비유라고 생각하지 않지만, 나는 이것을 듀얼 모니터 🖥 - TCP는 HDMI 케이블, HTTP는 모니터로 비유했다. 듀얼 모니터를 이용하려면 반드시 HDMI 케이블이 연결되어있어야한다. (연결지향) 하지만 모니터의 경우 상황에 따라 전원을 킬 수도 있고 끌 수도 있다. (비연결성)

즉, TCP는 말 그대로 수단일 뿐이고 이를 조작하는 것을 HTTP라고 보면 될 것 같다.

💡 Stateless 상태가 인기가있는 이유는 스케일링에서의 장점 때문?

(참고: https://develogu.tistory.com/m/5))

트래픽이 늘어나 스케일 아웃을 해야하는 경우 - Stateful한 구조였다면 클라이언트 정보를 다른 서버에서 가지고 있지 않기 때문에 클라이언트 정보를 추가된 서버로 넘겨줘야하는 추가적인 작업이 필요해진다.

반면, Stateless 하다면 클라이언트 정보를 클라이언트가 직접하거나 DB에서 하기 때문에 스케일 아웃을 추가적인 작업없이 할 수 있다.

HTTP의 역사

많은 내용이 있으나, 대략적인 흐름만 살펴보자.

HTTP 0.9

  • GET 메소드 지원
  • HTTP 헤더 지원 안함
  • Status Code 지원 안함
  • HTML 문서만 전송 가능

HTTP 1.0

  • 메소드 및 헤더 추가
  • HTTP 버전 정보 추가 (HTTP/1.0)
  • Status Code 지원
  • HTML 문서 외에 다양한 컨텐츠 지원 (Content-Type)

HTTP 1.1

  • 현재 가장 많이 사용하는 버전
  • keep-alive 연결 (Connection 재사용)
  • 청크된 인코딩 전송
  • 바이트 범위 요청
  • 추가적인 캐싱 메커니즘
  • 전송 인코딩
  • 요청 파이프라이닝

💡 Keep-alive란 뭘까?

(참고: https://velog.io/@kyle-log/HTTP-keep-alive)

Keep-alive는 이미 연결되어있는 TCP 연결을 재사용하는 기술이다. 즉, 서버와 클라이언트가 맺은 연결을 유지하는 방식이다. 연결을 얼마나 유지할지에 대한 Keep-alive 속성은 운영체제 커널에서 관리되는 TCP Keep-alive와 웹 서버에서 관리되는 웹 서버 Keep-alive가 있다. HTTP와 같은 일반적인 웹 서버 통신은 웹 서버의 Keep-alive의 속성을 따른다. (RabbitMQ, ActiveMQ, Thrift RPC 등은 TCP Keep-alive를 따름) 이 기능을 이용하면 handshake 과정을 생략할 수 있어 성능 향상을 기대할 수 있다.

HTTP 2.0

  • 전송 성능 향상
  • 지연 시간 및 처리량 개선

HTTP 3.0

이전 버전에 비해 성능은 개선되었지만, 가장 큰 특징은 TCP가 아닌 UDP를 사용한다는 것이다.

왜 TCP가 아닌 UDP를 선택했을까?

이유는 간단하다. TCP 자체의 프로토콜을 개선할 수 없기 때문이다. 쉽게 비유를 하자면, 우리가 한국에서 사용하는 220v를 110v로 바꾸는 것이다. (생각만해도 끔찍하다. 😰)

그 동안 우리가 사용해온 TCP 기반의 HTTP는 서로 신뢰성 있는 통신을 보장하기 위해 여러 방법들을 사용한다. 이러한 방법들은 TCP 프로토콜이 생기기 전부터 정의된 표준 규격이기 때문에 무시할 수 없다. 따라서 TCP에서 정의한 기능 외에 다른 부분을 건드려야하는데 건드리기에는 많은 제약 사항이 존재한다.

반면, UDP는 필요한 기능만 들어있는 가벼운 라이브러리로, 하얀색 도화지 같은 프로토콜로 볼 수 있다. 따라서 TCP보다 비교적으로 손쉽게 확장할 수 있다고 판단하여 UDP를 이용한다고 한다.

HTTP 3.0은 UDP 기반으로 만들어진 QUIC(Quick UDP Internet Connection)라는 프로토콜 위에서 돌아간다. UDP 기반으로 만들어졌기 때문에 TCP의 3-way-handshake 과정을 거치지 않아 연결 설정 시 레이턴시가 감소된다. 그 외에도 패킷 손실 감지에 대해 걸리는 시간 단축 및 멀티 플렉싱을 지원한다고 한다.

이 글의 레퍼런스

profile
세상을 현명하게 이끌어갈 나의 성장 일기 📓

0개의 댓글