CS/Network

What is HTTP?

on1ystar 2024. 7. 21. 04:53
728x90
반응형

HTTP가 무엇인가요

HTTPHyperText Transfer Protocol로 문자 그대로 HTML 문서를 주고받을 때 사용하는 프로토콜이다. 요즘은 웹에서 이루어지는 통신 대부분이 HTTP로 행해지며, HTML 뿐만 아니라 음성, 동영상, 메일 등의 다양한 데이터도 HTTP로 통신된다. 현재 전 세계 인터넷 구조의 절대적 위치를 차지하는 World Wide Web(W3)이 HTTP를 사용하기 때문에 웹 서비스 개발자에게 HTTP는 알아야 할 필수 프로토콜이다.

HTTP가 왜 이렇게 크게 성공하고, 현재까지 범용적으로 사용되고 있는지 이해하기 위해서는 먼저 HTTP가 가지고 있는 특성이자 장점들을 알아야 한다.

Client - Server 모델

HTTP는 클라이언트-서버 아키텍처를 기반으로 한다. 클라이언트에서 필요한 리소스들을 서버에 요청하면 서버는 요청받은 리소스를 찾고 조합해 클라이언트에 응답한다. 일반적으로 클라이언트는 브라우저나 모바일 어플리케이션 등이 될 수 있으며 서버는 대표적으로 웹 서버가 있다.

이 모델의 대표적인 장점은 클라이언트가 하는 일과 서버가 하는 일이 완벽하게 분리 됐기 때문에 각각 독립적으로 진화할 수 있게 됐다는 점이다.

예를 들어 클라이언트에서는 서버의 비즈니스 로직이나 데이터 가공에 신경쓰지 않고, 단지 브라우저가 어떻게 하면 응답 받은 HTML 등의 데이터들을 효울적으로, 빠르게 랜더링 하여 사용자의 화면에 보여줄 수 있을지를 고민할 수 있다.

서버의 경우에는 반대로 복잡한 비즈니스 로직과 대용량 데이터 처리 등에 더 집중해 기술, 아키텍처 등을 발전시킬 수 있게 됐다.

이 외에도 좋은 장점들이 많다.

  • 중요 데이터나 로직들을 서버에 중앙 집중화된 구조로 관리할 수 있으므로 보안이 용이
  • 필요에 따라 서버 성능을 향상시키거나, 더 많은 클라이언트를 추가하기 좋음
  • 서버에서 변경사항을 업데이트하면 모든 클라이언트에 반영되므로 유지보수에 용이

단, 대표적인 단점으로 처리해야할 비즈니스 로직이 복잡해지고 트래픽이 많아질수록, 서버 인프라를 구축하는데 드는 비용과 복잡성이 비약적으로 증가할 수 있다는 것이다. 그래서 요즘은 마이크로서비스 아키텍처 등을 혼합하여 서버가 처리해야할 로직이나 트래픽이 분산될 수 있도록 설계하고 있다.

무상태(Stateless)

HTTP는 클라이언트와 서버가 각각 한 번의 요청과 응답 후 연결이 끊기기 때문에 다음 요청 시 이전에 어떤 요청을 했는지 서버가 알 수 없는 무상태 프로토콜이다.

예를 들어,

  • 클라이언트: A와 B를 결제해주세요.
  • 서버A: A와 B 결제 됐습니다.
  • 클라이언트: 아까 산 것들 환불해주세요
  • 서버B: 아까 산 것들이 뭐죠?

위와 같이 서버는 클라이언트의 요청 상태를 따로 저장해 두지 않기 때문에 서버B는 클라이언트가 이전에 산 물건들의 정보를 알 수가 없어 환불 요청에 응답할 수 없다. 혹여 서버A가 요청을 받았어도 결과는 같다.

그럼 클라이언트는 어떻게 요청해야 할까?

  • 클라이언트: 아까 샀던 A와 B를 환불해주세요.
  • 서버: A와 B 환불 됐습니다.

위와 같이 이전의 상태들을 포함해 요청해야 한다. 클라이언트 입장에서는 좀 귀찮을 수 있겠지만 전체적으로 보면 엄청난 성능 향상을 기대할 수 있다.

서버 - 클라이언트 구조 특성상 클라이언트의 요청이 압도적으로 많을 수 밖에 없는데, 만약 Stateful 이라면 서버가 클라이언트의 상태를 일일이 기억해야 한다거나, 하나의 클라이언트당 하나의 서버가 담당해야 하는데, HTTP의 특성상 불가능하다.

또한 Stateless라 순간적인 대용량 요청에 대해 서버의 수를 순간적으로 증폭시켜 대응할 수 있다는 엄청난 장점이 생긴다.

물론 클라이언트의 상태를 기억해야하는 상황도 있다. 예를 들어, 로그인 정보를 기억해야 한다거나, 장바구니 서비스를 지원할 때 등이 있다. HTTP는 이런 경우를 쿠키와 세션 정보를 활용해 클라이언트의 상태 정보를 유지한다.

이런식으로 무상태를 극복하는 여러가지 방법이 있다.

  • 쿠키(Cookie)
  • 세션(Session)
  • 토큰 기반 인증(Token-based Authentication)
  • URL 매개변수(URL Parameters)

웹 서비스 설계 시 어쩔 수 없는 상황들을 제외하고는 위 방법들을 이용해 최대한 Stateless하게 설계하는 것이 추후 유지보수 측면이나 안정성에서 상당히 중요하다.

간단하면서 확장성 높은 HTTP Message 구조

HTTP는 통신 시 2개의 간단한 메세지를 서버와 클라이언트가 서로 요청하고 응답한다. HTTP/1.1(rfc9112) 표준 문서를 보면 메세지 포맷이 아래와 같이 기술되어 있다.

RFC9112(HTTP/1.1) 표준 문서 발췌

언뜻 보기에도 상당히 간단한 구조인데, 자세히 살펴봐도 사람이 쉽게 읽을 수 있도록 설계되어 있다.

  • start-line: 이 HTTP 메세지가 요청인지 응답인지를 구문할 수 있는 라인이다. 요청과 응답메세지 모두 3개의 요소로 이루어져 있다.
  • CRLF: Enter 키를 의미한다.
  • field-line: HTTP의 헤더 정보들이 담기는 라인으로 각각의 헤더는 Enter 키로 구분한다.
  • message-body: 실제 주고받아야 할 데이터들을 의미한다. 위 데이터들은 좀 더 명확하게 보자면 메타 데이터들이다.

요청과 응답 메세지 각각을 예시와 함께 조금만 더 자세히 분석해 보겠다.

HTTP Request Message

HTTP Request Message 구조

위 메세지에서 start-line은 아래 request-line의 구조를 따른다.

RFC9112(HTTP/1.1)

  • method: HTTP Method가 오며, 위 예시에서는 GET 요청을 했다.
  • SP: 한 칸 띄어쓰기를 의미한다.
  • request-target: 브라우저에 입력한 URI에서 요청한 데이터(위치)다. (도메인 이후 ~ 쿼리 스트링 이전)
  • HTTP-version: HTTP 버전을 나타내며, 위에서는 HTTP/1.1 버전이다.

그 아래부터는 HTTP Header다. 구조는 아래와 같다.

RFC9112(HTTP/1.1)

  • field-name: HTTP Header의 이름이 오고, 대소문자를 구분하지 않는다. 사용자가 직접 만들어 사용할 수 있다.
  • OWS: 띄어쓰기를 해도 되고 안 해도 된다는 의미다.
  • field-value: HTTP Header 값이 들어간다.

그 이후 빈 라인이 필수로 들어간 뒤 데이터가 이어진다.

HTTP Response Message

HTTP Response Message 구조

응답 메세지는 요청 메세지와 start-line만 다르며 status-line 이라고 한다.

RFC9112(HTTP/1.1)

  • HTTP-version: 응답 메세지는 HTTP 버전이 먼저 온다.
  • status-code: HTTP 상태 코드로 위에서 200은 요청이 성공했다는 의미다.
  • reason-phrase: 상태 코드를 간단히 설명하는 구간이라고 보면 된다. 필수가 아니며 생략해도 되지만 이 전의 SP(스페이스바 1번)는 꼭 넣어줘야 한다.

현재 인터넷 통신의 대부분을 담당하는 프로토콜인 것에 비해 메세지 내용은 상당히 간단해 보인다. 심지어 header에 필요한 메타 데이터들을 충분히 추가해 줄 수 있으며 이 또한 매우 쉽다. 이렇게 간단하면서도 확장성 있는 특성이 HTTP가 지금까지 사랑받는 이유다.

비연결성

HTTP는 TCP 표준에 의존하기 때문에 통신을 하기 전 클라이언트와 서버는 3-ways-handshaking을 통해 가상으로 연결되야 한다. 이는 실제로 연결된 상태가 아니며, 실제로는 데이터를 주고 받을 때마다 연결이 끊기게 된다. 이로 인해 서버는 무수히 많은 클라이언트들과 ‘연결’ 상태를 유지할 필요가 없어 불필요한 자원을 절약할 수 있다.

다만, 점점 인터넷의 크기가 커지고 트래픽이 많아지면서 클라이언트의 모든 요청마다 또 다시 3-ways-handshaking을 하는 것에 대한 오버헤드 부담이 심해졌다.

예를 들어, 하나의 웹 페이지를 띄우기 위해서는 생각보다 많은 요청과 응답을 주고받아야 한다.

www.naver.com  페이지를 띄우기 위해서는 최소 100개 이상의 HTTP request가 필요

이를 개선하기 위해 HTTP/1.1에서는 지속 연결을 지원하고, HTTP/2는 다중 메세지 전송을, HTTP/3는 더 나아가 전송 계층에서 UDP 표준을 채택하고 있다.

HTTP/1.1 vs HTTP/2 vs HTTP/3

각 버전들이 어떤 문제들을 해결하며 진화해 왔는지 몇몇 주요 특징들과 한계들을 확인해 보겠다.

(여기서 기술하는 특징들은 결코 쉬운 내용들이 아니며, 실제로 더 많은 내용들을 알아야 ‘제대로 ‘이해할 수 있지만 여기서는 간단히만 알아봄)

HTTP/1.1

현재 우리가 아는 HTTP 대부분의 근간이 정의된 버전으로 이후 버전부터는 성능 향상의 초점이 맞춰져 있다. HTTP/1.0과 가장 큰 차이는 지속 연결을 지원한다는 것이다.

주요 특징

  • 지속 연결 (Persistent Connection): 기본적으로 연결을 유지하여 클라이언트가 서버의 응답을 기다리지 않고 여러 요청을 한 연결에서 처리할 수 있다.
  • 파이프라이닝 (Pipelining): 클라이언트가 여러 요청을 한 번에 보내고, 서버가 순서대로 응답을 보낼 수 있다. 그러나 구현이 어려워 실제로는 많이 사용되지 않는다.
  • 캐싱 메커니즘: 개선된 캐싱 메커니즘으로, Cache-Control, ETag, Last-Modified 등의 헤더를 통해 캐시를 효율적으로 관리할 수 있다.
  • 호스트 헤더 (Host Header): 하나의 서버에서 여러 도메인을 호스팅할 수 있게 해주는 호스트 헤더를 도입했다.

한계

  • 단일 연결에서의 순차 처리: 요청이 순차적으로 처리되므로 하나의 요청이 지연되면 다음 요청도 지연되는 Head-of-line blocking 문제가 발생한다.
  • 비효율적인 헤더: 각 요청마다 반복되는 헤더가 전송되어 네트워크 대역폭이 낭비된다.

HTTP/2

HTTP/2는 HTTP/1.1의 요청 병목 문제를 바이너리 프레이밍을 통한 멀티플렉싱으로 해결했다.

멀티플렉싱(Multiplexing)에는 2가지 주요 개념이 있다.

  • 스트림 (Stream): 하나의 연결 내에서 독립적으로 주고받는 논리적인 데이터 흐름으로 각각 고유의 ID를 가지고 있다. 하나의 TCP 연결에서 여러 개의 스트림을 생성할 수 있으며, 각 스트림은 독립적으로 동작한다.
  • 프레임 (Frame): HTTP/2는 모든 데이터를 프레임이라는 작은 단위로 나누어 전송한다. 각 프레임은 특정 스트림에 속하며, 프레임 유형에 따라 다양한 역할(데이터 프레임, 헤더 프레임, 설정 프레임 등)을 수행한다.

하나의 TCP 연결에서 여러 스트림을 통해 프레임을 동시 전송할 수 있으며 서로 다른 프레임이 클라이언트 - 서버 간에 교차 전송되고, 각각의 스트림이 고유의 ID를 가지고 순서에 상관없이 처리될 수 있다.

주요 특징

  • 멀티플렉싱 (Multiplexing): 단일 연결에서 여러 요청과 응답을 동시에 주고받을 수 있어 Head-of-line blocking 문제를 해결했다.
  • 헤더 압축 (Header Compression): HTTP/2는 HTTP 헤더 패킷에서 중복 정보를 제거하는 HPACK이라는 방식으로 헤더를 압축하여 전송 효율성을 높인다.
  • 서버 푸시 (Server Push): 서버가 클라이언트 요청에 대한 응답을 보내기 전에 필요한 리소스를 미리 클라이언트에 전송할 수 있다.
  • 이진 프레이밍 (Binary Framing): 텍스트 기반이 아닌 이진 데이터로 프레임을 나누어 전송하므로, 더 효율적이고 빠른 통신이 가능하다.

한계

  • 복잡성 증가: 멀티플렉싱과 헤더 압축 등의 기능으로 인해 구현이 복잡해졌다.

HTTP/3

이전 버전들과 가장 큰 특징은 TCP가 아닌 UDP를 기반한다는 것이다. TCP는 연결 설정 과정에서의 지연과 패킷 손실 시 재전송 문제를 가지고 있어 성능 향상에 대한 한계를 가지고 있었다. 이를 극복하기 위해 TCP에서 탈피해 전송 계층에 새로운 프로토콜을 채택했다.

QUIC(Quick UDP Internet Connections)는 구글이 개발한 프로토콜로, TCP와 TLS를 통합하고 UDP 위에서 동작하는 새로운 전송 계층 프로토콜이다.

주요 특징

  • QUIC 프로토콜: TCP 대신 UDP 기반의 QUIC(Quick UDP Internet Connections) 프로토콜을 사용하여 더 빠르고 안정적인 연결을 제공한다.
  • 내장된 암호화: QUIC는 기본적으로 TLS 1.3을 사용하여 보안을 강화한다.
  • 향상된 멀티플렉싱: HTTP/2의 멀티플렉싱 기능을 개선하여 패킷 손실 시 특정 스트림만 재전송하면 된다.
  • 연결 설정 속도 향상: QUIC는 0-RTT(Zero Round Trip Time)-hands-shaking 통해 연결 설정 속도를 크게 줄인다.

한계

  • 새로운 프로토콜: QUIC는 UDP 기반으로 새롭게 설계된 프로토콜이기 때문에 네트워크 장비와의 호환성 문제가 있을 수 있다.
  • 복잡성 증가: QUIC와 HTTP/3의 복잡한 메커니즘으로 인해 구현이 어렵다.

일반적인 사이트의 경우 아직까지 HTTP/1.1을 많이 사용하지만, 대형 포털사이트는 성능 향상을 위해 HTTP/2를 주로 채택하여 사용하고 있다. HTTP/3은 별도의 설정 등의 호환성 문제로 아직 많이 사용되고 있진 않지만, 구글의 크롬 등 주요 브라우저는 이미 지원하고 있다.

크롬의 경우 이미 HTTP/2 및 대부분이 HTTP/3로 통신

 

HTTP와 HTTPS의 차이는?

HTTPS(HyperText Transfer Protocol Secure)란 HTTP에 보안을 추가한 버전이다. HTTPS는 기본적으로 전송하는 내용을 SSL(Secure Sockets Layer) 및 TLS(Transport Layer Security) 프로토콜을 사용하여 암호화한다.

기존의 HTTP는 클라이언트와 서버가 서로를 믿고 통신하는 형태였지만, HTTPS에서는 제 3자인 신뢰할 수 있는 인증 기관(CA)이 끼어들어 통신의 보안성을 보증하게 된다. SSL 인증서도 위 기관으로부터 발급받아 사용해야 하며, 클라이언트는 이 인증서를 확인하여 서버가 신뢰할 수 있는지 판단한다.

💡 TLS는 SSL의 후속 버전으로 더 강력한 암호화 알고리즘을 사용하는 등 보안성을 강화했다.

SSL/TLS Handshake

SSL/TLS 핸드셰이크는 HTTPS 통신 기술의 구성 요소 중 하나로, HTTP와 SSL/TLS의 조합이다. 클라이언트와 서버가 서로 인사를 나누며 암호화 방법을 협상하고 세션 키를 교환하게 된다.

절차는 다음과 같다.

  1. 브라우저(클라이언트)가 SSL/TLS 보안 웹 사이트를 열고 웹 서버에 연결
  2. 브라우저는 식별 가능한 정보를 요청하여 웹 서버의 진위 여부를 확인하려고 시도
  3. 웹 서버는 공개 키가 포함된 SSL/TLS 인증서를 응답
  4. 브라우저는 SSL/TLS 인증서가 유효하고 웹 사이트 도메인과 일치하는지 확인. 브라우저가 SSL/TLS 인증서에 만족하면 공개 키를 사용하여 비밀 세션 키가 포함된 메시지를 암호화하고 전송.
  5. 웹 서버는 개인 키를 사용하여 메시지를 해독하고 세션 키를 검색. 그런 다음 세션 키를 사용하여 암호화하고 브라우저에 승인 메시지를 보.
  6. 이제 브라우저와 웹 서버 모두 동일한 세션 키를 사용하여 메시지를 안전하게 교환하도록 전환.
💡 세션 키는 대칭 암호화를 위한 암호 키로 초기 SSL/TLS 인증이 완료된 후 브라우저와 웹 서버 간의 암호화된 통신을 유지한다. 굳이 대칭키를 사용하는 이유는 성능 때문이다.

참고

728x90
반응형