- HTTP: 서버가 클라이언트의 상태를 보존하지 않는다. => 무상태 (Stateless)
🤔 클라이언트의 상태? 클라이언트의 상태란, 클라이언트의 식별 정보를 의미한다. ex) 로그인한 후, 클라이언트가 상태를 유지해야 서버는 어떤 클라이언트가 요청을 보냈는지 식별할 수 있다.
🤔 무상태이면 서버는 어떻게 식별하나? 1) 쿠키 - 클라이언트가 서버로부터 쿠키를 받아, 이를 요청에 포함시킨 후 서버는 요청에 포함된 쿠키를 읽고 클라이언트를 식별한다. 2) URL 파라미터 - 클라이언트가 요청할 때 URL에 식별번호를 포함시킬 수 있다. ex) https://example.com/profile?userId=12345 3) HTTP 헤더 - HTTP 요청 헤더에 인증 토큰을 포함할 수 있다. 4) 세션 ID - 세션ID(고유한 식별자)를 발급하고 클라이언트는 세션ID를 요청에 포함하여 서버에 보낸다.
HTTP 구조
HTTP의 request와 response 는 크게 Start Line , Headers , Body 세 가지로 나눌 수 있다. (- HTTP 1.1 기준)
< HTTP request >
# Start Line
GET /index.html HTTP/1.1
# Headers
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
# Body
username=user1&password=1234
1) Start Line : HTTP 메서드, Request-URI, HTTP 버전
2) Headers
- Host : 요청할 서버의 호스트 이름
- User-Agent : 클라이언트 프로그램(브라우저)의 정보
- Accept : 클라이언트가 받을 수 있는 데이터 형식
- Accept-Language : 클라이언트가 선호하는 언어
- Connection : 요청 후 연결을 유지 ( 지속적 연결 )
❗️ Host : 요청할 서버의 도메인 이름-> 요청할 서버의 호스트 이름
🤔 호스트와 도메인 무슨 차이일까? 1) 호스트 - 네트워크에서 서버 (또는 컴퓨터)를 식별하는 이름 ex) www.example.com 에서 www는 호스트 이름이다.
2) 도메인 - 인터넷에서 웹사이트 등을 식별하는 이름 ex) www.example.com 에서 example.com 은 도메인 이름
3) Body
- 서버로 보내는 실제 데이터를 포함
<HTTP response >
# Status Line
HTTP/1.1 200 OK
# Headers
Date: Thu, 09 Jan 2025 12:34:56 GMT
Server: Apache/2.4.41
Content-Type: text/html; charset=UTF-8
Content-Length: 138
Connection: keep-alive
# Body
<!DOCTYPE html>
<html>
<head><title>Example</title></head>
<body><h1>Hello, World!</h1></body>
</html>
1) Start Line:HTTP 버전 , Status Code (상태 코드), Reason Phrase (상태 메시지)
2) Headers
-Date: 응답이 생성된 날짜와 시간
- Server: 소프트웨어 정보
- Content-Type: 본문 데이터 형식
- Content-Length: 응답 본문의 길이를 바이트 단위로 나타냄
-Connection: 연결의 상태를 지정함 ( 지속적 연결 )
3) Body
-서버가 클라이언트에게 반환하는 데이터
HTTP 버전
HTTP 0.9
1) 초기 버전으로 매우 단순하다.
2) get 메서드만 지원한다.
3) 응답은 HTML 문서만 전송한다.
/*요청*/ GET /index.html
/*응답*/ <HTML> A very simple HTML page </HTML>
HTTP 1.0
특징
1) 추가 메서드 도입
- GET, POST
2) 버전 정보 포함
- 어떤 버전의 HTTP를 사용하는지 명확히 파악 가능하다.
3) 헤더 개념 도입 - 이전에는 요청과 응답이 매우 간단했기 때문에, 서버가 보내는 데이터 형식을 명확히 지정할 수 없었다.
- 헤더를 도입함으로써 필요한 데이터 형식을 요청하고, 사용한 데이터 형식을 응답할 수 있다.
4) 상태코드 라인 추가
- 요청 실패, 성공 파악 가능하다.
# 요청
GET /mypage.json HTTP/1.0
Accept: application/json
# 응답
HTTP/1.0 200 OK
Content-Type: application/json
{
"message": "This is a JSON response."
}
한계
1) 비지속적 연결
- 하나의 TCP 연결로 하나의 요청과 응답만 처리할 수 있다.
즉, 여러개의 자원에 대한 요청을 처리할 때마다 새로운 연결이 필요하다.
ex) 여러 자원 ( 이미지, 자바스크립트, css 등) 각각의 자원에 대해 새로운 TCP 연결을 열어야 한다.
비지속적 연결
HTTP 1.1
특징
1) 지속적연결
- HTTP 1.0 : 각 요청마다 새로운 연결을 만들어야 했다. (비지속 연결)
- HTTP 1.1 : 모든 자원에 대한 응답이 돌아온 후에 연결을 종료한다. (지속 연결)
지속 연결
2) 파이프라이닝 도입
- HTTP 1.0 : 요청을 보내고 응답을 받은 뒤 서버가 끊어지는 문제를 (비지속적 연결) 지속적 연결로 해결했다.
그러나 하나의 요청을 보내고 응답이 와야, 새로운 요청을 보낼 수 있다.
- HTTP 1.1 : 요청을 동시에 서버로 보낼 수 있기때문에 대기 시간을 줄일 수 있다. ( 파이프라이닝 )
비지속적연결, 지속적 연결, 파이프라이닝
3) 호스트헤더 명시
- HTTP 1.0 : host 헤더가 반드시 명시되지 않아도 됐다.
- HTTP 1.1 : 필수로 명시해줘야 함 -> 가상 호스트 환경을 지원하기 위해 도입된 규칙이다.
4) 추가 메서드 도입
- GET, POST, PUT, DELETE, OPTIONS, HEAD
한계
1) HOL Blocking
- 파이프라이닝을 도입하여 요청을 동시에 보낼 수 있지만 응답은 순차적이다.
따라서 첫 번째 요청이 지연되면, 뒤에 있는 모든 요청도 기다려야 한다.
=> 이런 문제를 해결하기 위해 여러 TCP 연결을 동시에 열어, 각 요청을 다른 연결로 보냈다.
=> 네트워크 리소스 낭비
HTTP 2
특징
1) 멀티플렉싱
- HTTP 1.1 : 처리는 순차적이기 때문에 여러 연결(TCP 연결) 을 해야했다. -> 속도저하, 네트워크 낭비
-HTTP 2 : 하나의 연결에서 여러개의 스트림을 사용하여 동시에 요청과 응답을 처리한다. -> HOL Blocking 일부 해결
🤔 스트림? 여러 요청을 동시에 처리하려면, 각 요청을 구분할 수 있어야한다. 이때 각 요청을 스트림이라 부른다. (독립적인 데이터 흐름)
2) 헤더 압축
-HTTP 1.1 : 요청과 응답마다 같은 헤더 정보를 반복해서 보낸다.
-HTTP 2 : 헤더 정보를 압축해서 보낸다.
3) 바이너리 기반
-HTTP 1.1 : 사람이 읽을 수 있는 텍스트 포맷이다. -> 속도 저하
-HTTP 2: 컴퓨터가 읽기 쉬운 바이너리(0과 1) 포맷이다.
/*HTTP 1.1*/ GET /index.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0
/*HTTP 2*/ 0000 1001 0110 0011 1110 1010 ...
TCP의 한계
1) 느린 연결 설정
- TCP는 3-way handshake을 사용한다.
해당 과정은 오래걸리고 네트워크가 잠깐 끊기면 TCP 연결을 다시 설정해야한다. -> 연결 지연
🤔 3-way handshake 란? TCP는 데이터 전송 전에 유저와 서버를 미리 연결하는데 이 과정을 3-way handshake이라 한다. (연결 설정)
미리 연결하는 이유는? 1) 신뢰성 보장 - 클라이언트와 서버가 서로 확인하고, 연결 준비 상태를 확인하기 위함 2) 재전송 가능 - 해당 과정이 없으면, 초기 시퀀스 번호가 설정되지 않아 패킷 손실 발생시 이를 추적하고 재전송할 방법이 없다
1) SYN : 연결 준비됐어? 2) SYN + ACK : 응 준비됐어 3) ACK : 연결할게~
2) HOL Blocking
- HTTP/2는 여러 요청을 한 TCP에서 멀티플렉싱하여 처리하였지만
한 스트림에서 패킷손실이 나면, 그 스트림의 나머지 데이터가 순서대로 전송될 때까지 다른 스트림의 데이터도 모두 지연된다.
HTTP 3
TCP의 한계를 극복하고자 HTTP 3가 등장했다.
HTTP 3는 Google의 QUIC 프로토콜을 기반으로 개발했다.
🤔 QUIC 프로토콜이란? UDP를 기반으로 만들어진 프로토콜이다. UDP는 TCP와 다르게 3-way handshake(연결 설정)가 없다.
장점 - 3-way handshake가 없어, 간단하고 빠른 프로토콜이다. 단점 - 3-way handshake가 없어, 신뢰성이 부족하다. ( 데이터가 손실/ 순서가 바뀌어도 자동으로 감지, 복구 기능이 없다)
즉, UDP를 사용하여 속도를 높이고자 했지만, 신뢰성 문제가 발생하여 구글은 UDP 기반의 QUIC 프로토콜을 개발했다.
특징
1) 연결 설정 속도 향상
- QUIC는 초기 연결시 0-RTT를 지원한다. 이는 연결설정을 하지않고, 이전 연결 정보를 재사용한다.
-> 이전 정보가 없으면? : 1-RTT를 사용한다. 이는 클라이언트가 요청을 보내고 서버가 응답하는 과정을 말한다.
2) HOL Blocking 개선
- HTTP 2: 한 스트림에서 데이터가 손실되면 다른 스트림의 데이터도 모두 지연됐다.
- HTTP 3: UDP는 TCP와 달리 연결 지향적이지 않기 때문에, 각 스트림을 독립적으로 처리하여 지연되는것을 막을 수 있다.
3) 신뢰성 부족 개선
- TCP는 3-way handshake 가 있어, 초기 시퀀스 번호가 설정되어 패킷을 감지하고 재전송하는 방식으로 신뢰성을 보장한다.
- QUIC는 3-way handshake를 사용하지 않고 자체적으로 각 패킷에 고유한 시퀀스 번호를 할당하여,