📌 HTTP
서버/클라이언트 모델을 따라 데이터를 주고받기 위한 프로토콜이다.
일반적으로 프로토콜을 이용하여 HTML 파일을 주고받을 수 있는 공간을 의미한다.
- 텍스트 교환으로 보안에 취약하다.
역사
초기 웹 페이지는 단순한 서버-클라이언트의 구조를 따랐다. 처음부터 TCP / IP 위에서 구현되도록 설계되었다. 지금의 TCP는 무겁고 느리다고 까이지만, 이 당시에는 연결 지향적 특성 때문에 안정적이고 신뢰성있는 통신을 제공하여 평이 좋았다.
초기 HTTP 구조는 매우 간단했다. 요청 메서드도 GET 한가지였고, 헤더나 상태 코드도 없었고 응답은 무조건 HTML 파일 그 자체였다.
하지만 웹이 인기를 끌다 보니 기존 HTTP 사양만으로는 사용자들의 요구사항을 충족시킬 수 없었고 명시적으로 약속된 사양이 없어 여러 브라우저들 간의 혼란이 있어서 HTTP 기본 구조를 그대로 유지하면서 HTTP를 표준화하기 위해 HTTP WG 조직이 탄생하고 이 때 HTTP/1.0이 탄생하게되었다.
📌 HTTP/1.0
- HTTP Header에 버전정보 명시되어있다.
- 요청 메서드 GET, POST, HEAD 3가지
- 상태 코드 추가 되어 클라이언트 측에서 요청 결과에 따라 동작하도록 설계 가능
- Content-type의 도움으로 HTML 이외의 파일도 전송할 수 있게되었다.
1 | <!-- 요청 --> |
- HTTP/1.0의 간단한 요청과 응답 예시이다.
📌 HTTP/1.1
❓ HTTP/1.0의 문제
- HTTP/1.0에서는 요청에 따른 응답이 수신되면 TCP 연결 바로 종료
- 웹 페이지가 복잡해짐에 따라 이러한 TCP 핸드쉐이크 과정을 새로 거쳐야 하여 속도가 느려지는 문제가 있었다.
- 1개의 요청을 보내면 1개의 응답을 받고 1번의 연결이 종료된다. 만약 10번의 요청을 보내면 TCP 연결을 10번 해야하므로 서버에 부담이 된다.
❗️ 문제 해결책
- 연결 상태 유지(Persistent connection) : 기본적으로 한번 수립한 연결을 재사용 할 수 있도록 설정
- 지정한 시간동안 연결을 끊지 않는 방식
- 연결 유지 시간 길어지면 서버 부하 🔺
- Pipelining(파이프라이닝) : 클라이언트가 여러 요청 연달아 보내야할 때, 먼저 보낸 요청의 응답을 기다리는 것이 아니라 발생한 요청은 일단 전송하는 방식
- 클라이언트에서 여러 요청을 순차적으로 보내면 서버는 받은 순서에 따라 응답을 제공한다.
📌 HTTP/2
❓ HTTP/1.1의 문제
- 매 요청마다 헤더를 중복해서 전송해야만 하는데 이것이 굉장한 낭비였다.
- 서버가 항상 요청받은 순서대로 응답해야하므로 HOLB(Head-of-Line Blocking) 방식이었다.
- 하나의 연결 내에서 응답 다중화(multiplexing)을 할 수 없어 요청이 순차적으로 처리되어야 했는데, 서버가 응답 작성 중간에 문제가 생기면 후속 요청들이 전송되지 못하고 지연되는 문제가 있었다.
❗️ 문제 해결책
- SPDY 프로토콜 기반으로 동작 ⇒
웹 페이지 로드 시간 단축 - 이진 프로토콜 : 단순 텍스트를 전송하는 것보다 컴퓨터 입장에서 훨씬 더 효율적으로 데이터 전송 가능
- 응답 다중화 지원 : 하나의 TCP 연결에서 여러 요청을 동시에 처리할 수 있다. 바이너리 프레이밍으로 TCP 연결을 스트림, 메시지, 프레임으로 세분화하였다.
이는 요청 별 순서를 반드시 지켜야 했던 HTTP/1.1과 대조적이다. - 스트림 : 요청과 응답이 양방향으로 오가는 연결 단위
- 메시지 : 하나의 요청과 응답을 구성하는 단위
- 프레임 : 메시지를 구성하는 최소 단위
- 위 사진에서 하나의 TCP 연결에서 3개의 스트림이 존재한다.
- 5번 스트림은 클라이언트 측에서 서버로 데이터 전송하고, 1,3번 스트림은 서버 측에서 클라이언트로 데이터를 전송중이다.
- 1번 프레임 사이에 3번 스트림의 프레임이 끼워져있다.
이로써 HTTP/1.1에서 발생한 HOLB 문제 해결할 수 있었다.
- 헤더 필드 압축 지원 : 달라진 부분만 다시 전송하는 코딩 기법 사용
📌 HTTP/3
❗️ TCP로 인한 문제점
앞서 헤더 필드 압축을 통해 HTTP/1.1에서 발생한 HOLB 문제를 해결했다고 하였지만 이와 별개로
- 신뢰성 지향하기에 데이터 손실 발생 시 데이터를 재전송하는데 순서대로 처리해야하기 때문에 HOLB 문제를 해결할 수 없다.
- 혼잡제어를 수행하기 때문에 전송 속도를 낮은 상태에서 높이는 방식으로 속도 제어를 하는데 이는 네트워크 상황이 좋을 때 불필요한 지연을 발생시킨다.
문제를 해결하기 위해 TCP/IP기반이 아닌
⇒ UDP는 신뢰성을 보장하지 않는데 QUIC 신뢰성 기능을 직접 구현하여 신뢰성 기능이 제공되는 UDP 기반의 프로토콜이다.
👍 HTTP/3 장점
- 0-RTT 기능 : 연결 정보를 캐싱하여 재사용하여 다음 연결때는 바로 연결이 가능
- 연결 다중화 지원 : 각 스트림이 독립적으로 동작한다.
- HTTP/2 방식의 경우 TCP 특성상 데이터 손실이 발생할 경우 데이터 복구를 우선 처리하여 HOLB가 발생한다.
- HTTP/3는 데이터 손실이 발생해도 연결 내 스트림이 독립적으로 동작하기 때문에
다른 스트림에 영향을 주지 않는다.
- 연결 별 고유 UUID 지원
- TCP 기반의 통신은 wifi 환경에서 셀룰러 환경으로 이동하는경우 IP주소가 변경되어 연결 재수립 과정을 거쳐야하지만, QUIC는 UUID(Connection ID) 연결 ID 기반으로 식별하여 연결을 유지할 수 있다.
📌 HTTP Message
HTTP 메시지는 서버와 클라이언트 간에 데이터가 교환되는 방식이다. 메시지 타입에는 요청(Request), 응답(Response)이 있다.
요청과 응답의 구조는 유사하다.
실행 되어야 할 요청 또는 요청의 성공, 실패가 기록된 한줄
요청에 대한 설명, 메시지 본문에 대한 설명이 포함된 HTTP Header 세트(optional)
요청에 대한 모든 메타 정보가 전송되었음을 알리는 빈 줄(blank line)
요청과 관련된 내용이 옵션으로 들어가거나, 응답과 관련된 문서가 들어간다. 본문의 존재 유무는 첫 줄과 HTTP Header에 명시된다.
✏️ HTTP Request
요청은 클라이언트가 서버로 전달해서 서버의 액션이 일어나게끔 하는 메시지이다.
1. Start Line
- HTTP 메서드
GET,POST 등의 서버가 수행해야 할 동작을 나타낸다.
- 요청 타겟 : URL 또는 (프로토콜,포트, 도메인)
요청 타겟 포맷은 HTTP 메서드에 따라 달라진다.
- Origin 형식 : 끝에 ‘?’와 쿼리 문자열이 붙는 절대경로이다. 가장 일반적인 형식으로 GET, POST, HEAD, OPTIONS 메서드와 함께 사용한다.
1 | POST / HTTP 1.1 |
- absolute 형식 : 완전한 URL 형식으로, 프록시에 연결하는 경우 대부분 GET과 사용한다.
1 | GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1 |
- 마지막으로 HTTP 버전이 들어간다.
2. Header
대소문자 구분없는 문자열 다음에 콜론(:)이 붙고 그 뒤에 오는 값은 Header에 따라 달라진다.
- HTTP Method
- HTTP Version
- Host
- Content-Type
3. Body(본문)
모든 요청에 본문이 들어가지 않는다. GET, HEAD, DELETE, OPTIONS 처럼 리소스를 가져오는 요청은 본문이 필요 없다.
보통 POST 요청으로 서버에 데이터를 업데이트 하기 위해 본문이 필요하다.
본문은 두가지 종류로 나뉜다.
- 단일-리소스 본문(single-resource bodies) : Header 2개(Content-Type, Content-Length)로 정의된 단일 파일
- 다중-리소스 본문(muliple-resource bodies) : 파트마다 다른 정보를 지닌다.
✏️ HTTP Response
응답은 요청에 대한 서버의 답변이다.
1. Start Line
프로토콜 버전 (보통 HTTP/1.1)
상태 코드 : 요청의 성공 여부를 나타낸다. 200, 404 또는 302
상태 텍스트 : 상태 코드에 대한 설명글
1 | HTTP/1.1 404 Not Found. |
2. Header
요청 Header와 동일한 구조이다.
- HTTP Version
- Status
- Content-Type
- Set-Cookie
3. Body
모든 응답에 Body가 들어가지는 않는다. 201, 204 상태 코드를 가진 응답은 Body가 없다.
📌 HTTPS
기존 프로토콜에서 데이터가 쉽게 도난당하는 것을 방지하기 위해 SSL(Secure Socket Layer) 또는 TLS(Transport Layer Security) 프로토콜 을 사용하여 브라우저와 서버를 암호화하여 연결해준다.
또한 데이터가 전송중에 손상되거나 수정되는 것을 방지한다.
- 구글같은 포털에서 SEO 가산점을 준다.
✏️ SSL(Secure Socket Layer) 프로토콜
HTTPS 프로토콜이 텍스트를 암호화 할 수 있도록 도와주는 프로토콜이다. 암호화 원리는 공개키 암호화 방식이다.
SSL 프로토콜 통제권을 IETF로 넘기면서 TLS로 바뀐 상태인데 현재는 두가지를 혼용해서 사용하고 있다.
공개키 암호화 방식
공개키 암호화 방식은 공개키와 개인키를 사용하는 방식이다.
- 공개키는 모두에게 공개해서 사용하는 키이다.
- 개인키는 서버에서만 가지고 있는 키이다.
예시
- A 서버가 HTTPS 적용하기 위해 공개키와 개인키를 만든다.
- CA 기업을 선택하고 해당 CA 기업에게 공개키 관리를 부탁하며 계약한다.
- CA 기업은 기업명, A 서버 공개키, 공개키 암호화 방법을 담은 인증서를 만들고 해당 인증서를 CA 기업의 개인키로 암호화해서 A 서버에게 제공한다.
- A 서버는 CA 기업의 개인키로 암호화된 인증서를 가지고서 클라이언트로부터 HTTPS이 아닌 요청이 오면 암호화된 인증서를 건네준다.
- 클라이언트는 예를 들어
main.html
을 서버에 요청했다고 하자. HTTPS 요청이 아니기 때문에 CA기업의 개인키로 암호화된 인증서를 받게된다.- CA 기업의 공개키는 모두에게 공개되므로 클라이언트는 인증서를 공개키로 복호화하여 A 서버 공개키를 얻었다.
- 클라이언트가 A 서버에 요청을 보낼 때 텍스트를 공개키로 암호화하며 HTTPS 요청을 보낸다.
- 서버는 개인키로 암호화된 텍스트를 복호화하여 데이터를 해석하고 응답을 개인키로 암호화하여 클라이언트에게 보낸다.
- 클라이언트는 다시 공개키로 응답을 해석하여 해당 서버가 인증된 서버임을 알 수 있다.