Dev.YoungKyu
YoungKyu's Devlog
전체 방문자
오늘
어제
  • 분류 전체보기
    • 부스트캠프
    • iOS
    • visionOS
    • Backend
    • 알고리즘
    • CS
    • Git
    • Python
    • 끄적끄적

블로그 메뉴

  • 홈
  • 🌝 티스토리 홈
  • ⭐️ 깃허브
  • 태그

공지사항

인기 글

최근 댓글

최근 글

태그

  • guard
  • jekyll
  • ios
  • CS
  • boj
  • 소프트웨어 테스트
  • Swift5.7
  • 소프트웨어공학
  • Git
  • 소프트웨어 공학
  • 부스트캠프
  • 백준
  • swift
  • AVAudioSession
  • SwiftUI
  • 오블완
  • MVC
  • 모듈화
  • Python
  • 티스토리챌린지
  • if let
  • image
  • AutoLayout
  • ImageResource
  • Concurrency
  • authenticationinterceptor
  • alamofire
  • Optional
  • 알고리즘
  • constraint

티스토리

hELLO · Designed By 정상우.
Dev.YoungKyu
HTTP 개요 및 HTTP 버전별 차이
CS

HTTP 개요 및 HTTP 버전별 차이

2025. 6. 3. 17:30

HTTP란?

HTTP(HyperText Transfer Protocol)는 클라이언트와 서버 간에 의미 있는 요청과 응답을 주고받기 위한 텍스트 기반 통신 프로토콜입니다.

'의미 있는' 이란?

HTTP는 단순히 데이터를 주고받는 수준을 넘어서, 요청과 응답의 목적과 맥락을 헤더(Header)를 통해 설명할 수 있습니다.

예를 들어, GET, POST와 같이 요청의 종류를 설명하고, User-Agent를 통해 누가 보냈는지를 설명하며 Content-Type을 통해 데이터의 형식이 무엇인지를 설명할 수 있습니다.

전송 방식

HTTP는 어플리케이션 계층의 프로토콜로 신뢰가능한 전송 계층 프로토콜(TCP) 위에서 동작합니다. 보안이 강화된 버전인 HTTPS(HTTP over TLS)는 TLS(SSL)를 통해 데이터를 암호화하여 전송합니다.

HTTP 메시지 구조

HTTP에서 클라이언트와 서버들은 두가지 형태의 메시지 교환을 통해 통신합니다.
수신 측인 클라이언트가 전송하는 메시지를 요청(request)라고 부르며, 발신 측인 서버가 전송하는 메시지를 응답(response)라고 부릅니다.

요청 메시지 구조는 아래와 같습니다.

요청 정보 (Method, Path, Protocol Version)
헤더 (Headers)

본문 (Body, 선택적)

ex)
POST /login HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 34

{"username":"test", "password":"1234"}

응답 메시지 구조는 아래와 같습니다.

응답 정보 (Protocol Version, StatueCode, StatusMessage)
헤더 (Headers)

본문 (Body, 선택적)

ex)
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 19

{"result":"success"}

주요 HTTP 메소드

클라이언트가 수행하고자 하는 동작을 정의하는 것으로, 주요 메소드는 GET, POST 등이 있고 많은 내용은 HTTP 메소드-MDN Web Docs여기서 확인할 수 있습니다.
클라이언트와 서버간의 합의를 통해 사용자 정의 메소드를 추가할 수도 있습니다.

주요 상태 코드

상태 코드는 요청에 대한 응답의 상태를 의미하며, 자주 사용되는 상태 코드로는 200(OK), 302(Temporarily Moved), 404(Not Found), 500(Internal Server Error) 등이 있으며 많은 내용은 HTTP 상태 코드-MDN Web Docs에서 확인할 수 있습니다.
클라이언트와 서버간의 합의를 통해 사용자 정의 상태 코드를 추가할 수도 있습니다.

HTTP 버전 별 차이

HTTP/1.0

HTTP/1.0은 최초의 표준으로, 버전 정보 명시, 요청 메소드 추가, 상태 코드 추가, 헤더 필드 추가 등 다양한 요구사항을 만족하기 위한 개선이 이루어졌습니다.

HTTP/1.0을 구별하기 위해 이전 버전은 HTTP/0.9라는 이름을 붙였으며 자세한 배경은 다음 글 웹 개발자라면 알고 있어야 할 HTTP의 진화 과정-요즘 IT에서 확인할 수 있습니다.

HTTP/1.1

HTTP/1.1은 HTTP/1.0 출시 후 얼마 지나지 않아 발표되었습니다.
HTTP/1.1의 제안 배경을 보면 다음과 같은 문제점들을 해결하기 위해 발표된 것을 알 수 있습니다.

  1. HTTP/1.0은 계층형 프록시, 캐싱, 지속 연결, 가상 호스팅과 같은 기능들을 충분히 고려 X
  2. HTTP/1.0을 명시했지만, 사양을 지키지 않은 경우가 많아 불편했음

따라서 HTTP/1.1에서는 아래와 같은 기능들이 추가되었습니다.

연결 상태 유지

HTTP/1.0에서는 요청에 따른 응답이 수신되면 TCP 연결을 바로 종료했습니다. 다수의 HTTP 요청이 발생하는 경우 매번 TCP 핸드셰이크 과정을 거쳐야 했기에 오버헤드가 발생했습니다.

그래서 HTTP/1.1에서는 Keep-Alive 라는 헤더를 추가하여 기본적으로 한 번 수립한 연결을 재사용할 수 있게 설정되었습니다. 물론 연결을 유지하는 시간이 길어질수록 서버에 부하가 생기기 때문에 timeout 과 연결이 닫히기 전 전송할 수 있는 최대 요청 수를 제한하는 max 파라미터 또한 존재합니다.

파이프라이닝

1번째 그림은 HTTP/1.0 에서 요청마다 TCP 핸드셰이크를 하는 예시이고,
2번째 그림은 HTTP/1.1 에서 Keep-Alive가 추가된 예시이며,
3번째 그림은 파이프라이닝이 적용된 예시입니다.

 

Keep-Alive를 통해 TCP 핸드셰이크 과정을 줄였다 하더라도, 여러 요청을 보낼 경우 기존 요청의 응답을 받아야 다음 요청을 전송할 수 있어 지연이 발생할 수 밖에 없었습니다.

 

그래서 등장한 기법이 파이프라이닝(Pipelining)입니다.

클라이언트가 여러 요청을 순차적으로 보내면 서버가 이를 순서대로 처리하여 응답을 전송하게 됩니다.

 

하지만 이 방식에도 한계는 존재했습니다.
서버는 여전히 요청을 순서대로 처리해야 하기 때문에, 가장 앞의 요청의 처리가 느리면 그 뒤에 있는 응답이 지연되는 문제가 발생합니다.
이 현상을 HOL Blocking(Head-of-Line Blocking) 이라고 합니다.

캐시 제어(Cache-Control)

HTTP/1.0에서는 클라이언트와 서버간의 불필요한 데이터 재요청을 줄이기 위해 Expires, Last-Modified 와 같은 날짜 기반의 캐시 제어 방식을 제공했습니다. 하지만 이 방식은 절대적인 시간 기준을 사용했고, 요청이 서버에 닿기까지 걸리는 네트워크 지연 시간으로 인해 정확성이 떨어지는 문제와 실제로는 변경되지 않은 리소스를 새로 받아오는 불필요한 트래픽이 발생할 수 있다는 한계가 존재했습니다.

이러한 한계를 해결하기 위해 HTTP/1.1에서는 ETag와 Cache-Control을 제공했습니다.

ETag는 서버가 리소스의 고유 해시값이나 버전 문자열을 생성하여 응답에 포함시키는 방식입니다.

// Response 서버 -> 클라이언트
ETag: "v1.0.1"

클라이언트는 이후 요청 시 이전에 받은 ETag 값을 If-None-Match 헤더에 담아 전송합니다.

// Request 클라이언트 -> 서버
If-None-Match: "v1.0.1"

서버는 전달받은 ETag를 비교하여 리소스가 변경되지 않았다면, 304 Not Modified로 응답합니다.

날짜와 시간을 통해 캐시 여부를 결정하는 것이 아닌 실제 내용의 달라짐 여부를 통해 캐시 유효성을 판단할 수 있어 캐시 정확도가 향상되었습니다.

또한 Cache-Cotnrol 헤더를 통해 캐싱 정책을 지원합니다. Cache-Cotnrol 헤더는 상대적인 시간 기준(max-age)를 사용하며, no-cache, no-store 등 다양한 정책들을 지원합니다.

아래와 같이 서버는 응답에 Cache-Control 헤더를 추가하여 클라이언트에게 더 유연한 캐시 제어를 지시할 수 있습니다.

// Response 서버 -> 클라이언트
Cache-Control: max-age=3600, public

HTTP/2

이진(Binary) 프로토콜

HTTP/2는 이진(Binary) 프로토콜입니다. HTTP/1.1은 텍스트 기반 프로토콜이기 때문에 아스키코드로 작성되었습니다. 덕분에 사람이 읽기엔 편하지만 데이터가 크다는 단점이 있었습니다.

HTTP/2에서는 보내야 할 데이터를 바이너리로 변환하는 계층이 있어 텍스트 형태로 전송하는 것보다 데이터의 크기를 줄여 전송할 수 있게 되었습니다.

멀티플렉싱(Multiplexing)

HTTP/1.1은 파이프라이닝을 통해 요청의 비동기화를 구현했지만, 서버 측에선 할상 요청받은 순서대로 응답해야 했기에 응답 작성 중 문제가 생기면 후속 응답들이 전송되지 못하고 지연되는 HOL Blocking(Head-of-Line Blocking) 문제가 여전히 남아있었습니다.

클라이언트 요청 순서:
1. 요청 A (오래 걸리는 요청)
2. 요청 B (가벼운 요청)

서버 처리:
- 요청 B는 먼저 처리 완료되었지만,
- 클라이언트는 A에 대한 응답을 먼저 받아야 하므로
- B의 응답도 기다리게 됨 (Block)

응답 순서:
1. 응답 A
2. 응답 B

HTTP/2는 이 문제를 해결하기 위해 멀티플렉싱(Multiplexing) 을 지원합니다. 요청과 응답에 스트림 ID를 부여하고, 하나의 TCP 연결에서 여러 요청과 응답을 동시에 처리할 수 있게 되었습니다.

하나의 TCP 연결을 스트림(Stream), 메시지(Message), 프레임(Frame)이란 단위로 세분화합니다.

스트림(Stream): 요청과 응답이 양방향으로 오가는 논리적 연결 단위, 하나의 TCP 연결에서 여러 개의 스트림이 동시에 존재할 수 있음
메시지(Message): 하나의 요청과 응답을 구성하는 단위
프레임(Frame): 메시지를 구성하는 최소 단위, 잘게 쪼개어 전송되고 수신 측에서 다시 조립하여 사용

HTTP/3

HTTP/2는 결국 TCP 위에서 동작하기 때문에, TCP가 갖는 문제에서 벗어날 수 없었습니다. TCP는 신뢰성있는 데이터 전송을 보장하기 때문에 데이터 손실이 발생하면 재전송을 수행합니다. 그런데 TCP는 패킷을 정확한 순서대로 처리해야 하기 때문에 재전송 과정에서 병목현상이 발생할 수 밖에 없는 구조였습니다.

또한 TCP는 혼잡 제어를 수행하기 때문에 전송 속도를 낮은 상태에서 천천히 높이는 방식으로 속도 제어를 취합니다. 이는 네트워크 상황이 좋을 때는 불필요한 지연이 발생합니다.

이러한 문제들을 해결하기 위해 HTTP/3 는 QUIC 프로토콜 위에서 동작합니다. QUIC은 2013년 구글이 공개한 프로토콜로, TCP의 신뢰성 보장을 위해 제공되는 기능들을 UDP 기반으로 직접 구현하여 성능을 개선한 프로토콜입니다.

HTTP/3는 TCP의 3-way handshake 과정에서 발생하는 지연시간을 줄여 1-RTT(One Round Trip Time), 0-RTT(Zero Round Trip Time) 를 도입했습니다.

QUIC는 자체적으로 TLS 1.3 암호화 통신을 내장하고 있으며, 연결 수립과 동시에 TLS 핸드셰이크를 처리합니다.

Handshake with QUIC with only one RTT for a secure connection QUIC Handshake 0-RTT

참고

https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Methods
https://developer.mozilla.org/ko/docs/Web/HTTP/Reference/Status
https://datatracker.ietf.org/doc/html/rfc2068#section-1.1
https://12bme.tistory.com/579
https://velog.io/@jhl221123/HTTP3-%EC%A7%84%ED%99%94%EC%97%90-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EB%B3%80%ED%99%94
https://blog.cloudflare.com/ko-kr/even-faster-connection-establishment-with-quic-0-rtt-resumption/

저작자표시 (새창열림)

'CS' 카테고리의 다른 글

Socket vs WebSocket  (0) 2025.06.03
Audio 기본 지식 이해하기(Sample, Frame, Sampling Rate, Channel, Bit Depth)  (0) 2025.03.31
SQL 기본 쿼리문 정리  (0) 2024.08.05
Heap이 Stack에 비해 느릴 수 밖에 없는 이유  (0) 2024.07.21
객체 지향 프로그래밍을 설계할 때는 SOLID 원칙을 지켜야 한다.  (0) 2024.04.12
    'CS' 카테고리의 다른 글
    • Socket vs WebSocket
    • Audio 기본 지식 이해하기(Sample, Frame, Sampling Rate, Channel, Bit Depth)
    • SQL 기본 쿼리문 정리
    • Heap이 Stack에 비해 느릴 수 밖에 없는 이유
    Dev.YoungKyu
    Dev.YoungKyu
    iOS를 공부하고 있습니다

    티스토리툴바