0w0

Http/1.1를 조사했다.

개요

RFC2616를 읽고 HTTP/1.1에 대해 알아보자.

동기

우리는 컴퓨터를 키고 당연히 웹브라우저를 킨다.

컴퓨터를 킨다는 소리는 어쩌면 웹브라우저를 킨다는 소리와 사실상 동의어가 되어버렸다.

그리고 웹브라우저에 돌아갈 서비스를 만들기 위해 개발자는

React, Vue, Svelte, Angular, Preact, Remix, SolidJS, Next.js, Nuxt.js, Blitz.js, Aleph.js, vno...

Node.js, Deno, Express, Koa, Nest.js, fastify, Socket.io, Django, flask, Sinatra, Ruby on rails, Laravel...

PostgreSQL, MariaDB, MySQL, MongoDB, DynamoDB, Graphql, Redis...

Docker, Kubernetes, Vargant, Apache, nginx, AWS...

헤아릴 수 없는 환경, 라이브러리, 프레임워크, 언어가 있지만 우리 모두 한 줄의 메세지를 보기 위해 프로그래밍 한다.

HTTP/1.1 200 OK

HTTP/1.1 정의한 RFC2616를 알자

RFC....

RFC2616에 대해 조사하다보니 이 RFC는 폐기되었고, 2014년에 RFC7230, RFC7231, RFC7232, RFC7233, RFC7234, RFC7235 로 정의한 HTTP1.1를 사용한다는 사실을 알게되었다.

우선 각 문서가 무슨 역할을 하는가 정리해보면,

그 외

무엇이 변했을까?

RFC(7230-7235) 부록에 RFC2616 변경점 표기됨

주요 변경점

RFC7230: HTTP1.1 메시지 문법 및 라우팅

RFC7231: HTTP의 의미론과 내용

Referer: 사람들이 어디로부터 와서 방문 중인지 인식할 수 있도록 해주는 것

RFC7232: HTTP 조건 Request

RFC7233: HTTP Range Request

RFC7234: HTTP 캐시처리

RFC7235: HTTP 인증

그 외

RFC7236: HTTP 인증 스킴 등록
RFC7237: HTTP 메서드 등록
RFC7238: HTTP 308 상태 코드 (리다이렉트에 관한)
영속적 일시적
POST => GET 메서드 변경 허용 301 302
POST => GET 변경 허용 안함 308 307
RFC7239: HTTP 확장

:::note 부록: Forwarded 헤더

Forwarded: for="_gazonk"
Forwarded: for=192.0.0.1;proto=http;by=203.0.0.1
Forwarded: for=192.0.0.1, for=198.0.0.1

:::

HTTP를 알자

사실상 여기가 본론...

HTTP 이름을 알아보자

HTTP는 이름에 이것이 무엇인가 가장 간략하게 설명되어 있다.

Hyper Text Transfer Protocol

여기서 Hyper Text독자가 문서에서 다른 문서로 접근할 수 있는 텍스트를 의미하며 Hyper Media 또한 같은 맥락이다. 이러한 다른 것으로의 접근을 기반으로 거미줄처럼 얽혀있어 우리는 Web이라 한다.

나머지 Transfer Protocol은 말그대로 전송 규약으로 무엇인가 전송하기 위한 약속을 의미한다. HTTP 위치를 그림으로 표현하면 이하와 같다.

where is HTTP

Protocol 만 따로 떼어내 언급하면, 컴퓨터 내부에서, 또는 컴퓨터 사이에서 데이터의 교환 방식을 정의하는 규칙 체계. 기기 간 통신은 교환되는 데이터의 형식에 대해 상호 합의가 필요하며, 이런 형식을 정의하는 규칙의 집합을 프로토콜이라고 한다.

여담으로 우리는 흔히 HTTP 프로토콜이라하지만 HTTP는 그 자체에 프로토콜이라는 말이 들어가므로 HTTP 프로토콜이라함은 역전앞 같이 동의어를 두 번 말하는 격이다...

수 많은 프로토콜을 보고 싶다면 여기

규약

버전표기

HTTP + / + 숫자 + . + 숫자

예시 HTTP/1.1

호환

프록시/게이트웨이는 실제 자신의 버전보다 높은 표시를 사용해서 메세지를 발송하면 절대 안 됨

상위 버전 요구가 수신되었으면 프록시 / 게이트웨이는

  1. 요구 버전을 내리거나
  2. 에러를 발송하거나
  3. 터널로 전환해야 한다

프록시 / 게이트웨이 버전보다 낮은 요구는 상위 버전으로 올릴 수 있으나 요구 받은 버전의 주요 버전은 반드시 동일해야 한다.

URI

URI는 www부터 URL, URN 등등 식별해주는 정형화된 문자열

스킴://호스트[:포트] [절대경로]
http://호스트[:포트] [절대경로]

http://abc.com === http://ABC.com === http://ABC.COM/

역사를 알아보자

  1. HTTP/0.9

    • 팀 버너스리가 1990년에 발명한 프로토콜을 HTTP/0.9라 함
    • 헤더가 없음
    • 메서드는 GET만 존재
  2. HTTP/1.0

    • IETF에서 표준화된 최초의 버전
    • 버전 명시
    • 헤더 도입
    • GET 메서드 외의 메서드 도입(확장성)
  3. HTTP/1.1

    • HTTP의 완성
    • Connection 재사용 가능
    • 파이프라이닝
    • chunk response
    • Accept 헤더를 통한 content 협상으로 클라이언트-서버 교환에서 적합한 컨텐츠 제안가능
    • 복잡한 캐시 컨트롤
    • 지속적 접속
    • Host 헤더
    • URL === URI === URN 으로 봐도 무방
    • MIME 차용
    • Web의 거의 대부분이 이 프로토콜
  4. HTTP/2

    • 텍스트 프로토콜 => 이진 프로토콜
    • 다중화 프로토콜, 순서 제거
    • 중복, 오버헤드 제거, 헤더 압축
    • 서버에서 클라이언트 캐시를 서버 푸시 메커니즘으로 데이터를 넣도록 허용
  5. HTTP/3(QUIC)

:::note

부록: Request - Response 체인

단순한 상황
request chain -------- response chain
UA------------V-----------O
복잡한 상황
request chain -------- response chain
UA----V----A----V----B----V----C----V----O
복잡한 상황2

터널이 아니라면 내부 캐시 사용할 수 있다

캐시된 응답이 있으면 체인은 간결해짐

O가 B 사본을 가지고 있을 때이다.

request chain -------- response chain
UA----V----A----V----B----C---------O

이 외에도 여러 프록시, 게이트웨이, 터널 등의 상황에 따라 체인은 변한다

:::

왜 HTTP/1.1은 중요한가

  1. 가장 많이 사용된다.
  2. REST의 중요한 특징인 통일 인터페이스, 무상태성, cache 등이 구현되어 있다

TCP/IP

HTTP/1.1는 네트워크 프로토콜인 TCP/IP를 기반으로 한다.

표로 표현하면

계층형 프로토콜
애플이케이션층(HTTP)
트랜스포트층(TCP)
인터넷층(IP)
네트워크 인터페이스층

전체상을 알아보자

HTTP의 구체적인 구조를 표로 정리하면 이렇다

클라이언트 서버
request response
UA(RFC2616 정의상)

UA: User Agent

request와 response

HTTP/1.1는 request-Response Style 프로토콜이다.

서버에서 처리가 길어지면 클라이언트는 대기한다. (동기형 프로토콜)

실제로 특정 사이트에 접속해보면

여담으로 github를 비롯한 유명한 사이트 대부분이 HTTP2였다...

request
GET /index.laf HTTP/1.1
Host: www.kyobobook.co.kr
User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
DNT: 1
Upgrade-Insecure-Requests: 1
Connection: keep-alive
Cookie: WMONID=m8FSu3GwIhy; KYOBOSESSIONID=vXnNPhspRDdCdWLcHvHcPmQ0QRQh4TQFshqmmzpXnGJ1mRVtsQk5!1790412269!-2124087675!7200!-1!944508172!-2124087674!7200!-1; NSC_wjs_lzpcp_Dppljf=ffffffffd0b53b3045525d5f4f58455e445a4a42378b; PCID=16540732644003240091946
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-site
response
HTTP/1.1 200 OK
Date: Wed, 01 Jun 2022 08:48:07 GMT
Server: Apache
Content-Language: ko-KR
Keep-Alive: timeout=5, max=84
Connection: Keep-Alive
Content-Type: text/html; charset=EUC-KR
Set-Cookie: NSC_wjs_lzpcp_Dppljf=ffffffffd0b53b3045525d5f4f58455e445a4a42378b;expires=Wed, 01-Jun-2022 08:50:08 GMT;path=/;httponly
Cache-Control: private
Content-Encoding: gzip
Transfer-Encoding: chunked

클라이언트에서는 무슨 일이 일어났는가?

  1. Request 메세지 구축
  2. Request 메세지 송신
  3. (Response 대기)
  4. Response 메세지 수신
  5. Response 메세지 해석
  6. 클라이언트 목적 달성하기 위한 처리
    • 일반적으로는 렌더링...

서버에서는 무슨 일이 일어났는가?

  1. (Request 대기)
  2. Request 메세지 수신
  3. Request 메세지 해석
  4. 적절한 애플리케이션 프로그램에 처리 위탁
  5. 애플리케이션 프로그램 결과 획득
  6. Response 메세지 구축
  7. Response 메세지 송신

메세지를 알아보자

Request와 Response 메세지를 하나모아 HTTP 메세지라 한다.

Request 메세지

GET / HTTP/1.1
Host:kyobobook.co.kr

Response 메세지

HTTP/1.1 200 OK
Content-Type: text/html; charset=EUC-KR

:::note

HTTP/1.1 200 OK
Date: Sun, 10 Oct 2010 23:26:07 GMT
Server: Apache/2.2.8 (Ubuntu) mod_ssl/2.2.8 OpenSSL/0.9.8g
Last-Modified: Sun, 26 Sep 2010 22:04:35 GMT
ETag: "45b6-834-49130cc1182c0"
Accept-Ranges: bytes
Content-Length: 12
Connection: close
Content-Type: text/html

Hello world!

Hello World!가 바디이다. :::

메세지 정리

이하 같은 표로 구성된다.

HTTP 메세지
스타트라인(Request Line / Status Line)
헤더
빈줄
바디

HTTP의 무상태성

서버가 클라이언트의 애플리케이션 상태를 저장하지 않는 제약

이것만으로는 설명이 부족하다!

유명한 햄버거 가게 예시를 보자.

Stateful
Stateless
정리
stateful stateless
장점 일상적 처리에 모든 정보가 담겨져있다
간결 Self Descriptive Message로 클라이언트가 자신의 상태를 기억한다
이에 서버 시스템 관리는 단순해진다(Request 메세지에 모든 정보가 담겨있으므로)
단점 불특정 다수의 클라이언트를 처리하기에는 비용이 크다 길다
데이터 동기화할 때 오버헤드 위협이 크다 매회 새 주문 반복
스케일아웃이 어렵다 송신할 데이터가 많아짐에 따른 퍼포먼스 저하
인증 등 서버에 부하를 주는 처리를 반복해야함
대표 예시 FTP HTTP

:::note 통신에러 처리 방법

Stateful

이 때, 결과적으로는 상태가 있기에 햄버거 세트는 2개가 나온다.

Stateless

이 때는 상태가 없으므로 세트 하나만 주문된다. :::

애플리케이션 상태?

애플리케이션 상태 = 세션 상태

세션이란 로그인에서 로그아웃까지 상태를 지칭

참고로 세션과 늘 함께 언급되는 쿠키는 RFC6265에 정의됨

둘 다, 결국 무상태성을 지닌 HTTP의 상태 정보를 기억해주는 도구지만 동시에 개인정보를 위해 신중히 사용해야할 도구이다.

그래서 하고싶은 말은...

HTTP는 간결한 프로토콜이기에 강점이 있다.

메서드

8개 뿐이다!

메서드 의미
GET 리소스 조회
POST 자식 리소스 작성, 리소스 데이터 추가, 그 외의 처리
PUT 리소스 갱신, 리소스 작성
DELETE 리소스 삭제
HEAD 리소스 헤더(메타데이터) 조회
OPTIONS 리소스가 지원하고 있는 메서드 조회
TRACE 자신에게 리퀘스트 메세지를 반환(루프백) 테스트
CONNECT 프록시 동작 터널 접속 변환

왜 이게 중요한가? 그 유명한 CRUD가 가능하다

CRUD?
CRUD명 의미 메서드
Create 작성 POST/PUT
Read 읽기 GET
Update 갱신 PUT
Delete 삭제 DELETE

:::note

Web 성공 이유는 HTTP 메서드에 있다.

일반적인 프로그래밍 언어에 비해 HTTP는 8개 뿐이다.

하지만 이것은 REST의 통일 인터페이스 제약과 일맥상통하며, 메서드를 한정하고, 고정했기에 프로토콜이 단순성이 보증되었고 결과적으로 GET의 은닉된 안정성, PUT, DELETE의 멱등성(여러번 적용해도 결괏값이 달라지지 않는 것), POST의 만능성과 함께 Web의 성공으로 이어졌다.

:::

상태코드

HTTP는 Request <=> Response 프로토콜이다.

모든 Request에는 Response가 존재하다.

그리고 그 Response에는 의미있는 상태코드가 존재한다.

상태코드는 중요한가?

시스템 밑그림을 그리는 역할을 한다.

예를들어 같은 4xx 상태코드라면, 401 Unauthorized은 인증안됨 그러나 인증 가능, 403 Forbidden지속적으로 거절이다.

만약 이 둘이 분류되지 않았다면 시스템이나 API에는 혼란이 있었을 것이다.

상태코드 톹아보기

분류 의미
1xx 처리중
2x 성공
3xx 리다이렉트
4xx 클라이언트 에러
5xx 서버 에러

:::note

4xx 계열은 401~417까지 정의되어있다 그러나 RFC2324에 왜인지 418 I'm a teapot이라는 상태코드를 정의했다.

만약 이처럼 특수한 상태코드를 처리 못하는 경우는 어떻게될까? 바로 400 Bad Request 처리가 된다. :::

핵심 상태코드

HTTP 헤더

헤더는 어디에 쓰일까?

종류

특이한 헤더

엔티티 헤더

이하에서 Content-Length는 엔티티 헤더지만, Host와 User-Agent는 request 헤더

POST /myform.html HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Content-Length: 128
업그레이드 헤더(RFC7230)

HTTP/1.1은 Upgrade 헤더필드를 통해 다른 프로토콜로 업그레이드할 수 있는 기능이 있다.

GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: example/1, foo/2
Connection: upgrade
Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
Connection: Upgrade
Upgrade: websocket

캐시

캐시?

만일 우리가 SNS에 연결했을 때

캐시가 없다면
  1. SNS 서버에 Request
  2. 서버에서 처리 후에 웹 페이지 Response
  3. Web 페이지 확인
캐시가 있다면
  1. SNS 서버에 request
  2. 특정조건(e.g 로그인이 안 되어있다)이면 처리 없이 바로 웹 페이지 Response
  3. Web 페이지 확인

지속적연결

GET / HTTP/1.1
Host: example.com
Connection: close

맺는말

이 글을 쓰기 위해 약 2주 정도 조사하고 공부하면서, 여러 글과 영상을 보았지만 보고 메모하고 정리만 했지 이해가 되었는가 하면 여전히 이해하지 못했다.

그저 HTTP, HTTP1.1은 이런거구나.

그래서 REST 아키텍처 스타일이 나와 세상에 널리 퍼졌구나.

이런 느낌만 변했을 뿐이다.

시간이 흘러 다시 이 글을 보며,

아, 잘 못 정리했구나

아, 이런 소리구나

할 것이라 믿으며 메세지를 보면서 글을 마무리 짓자.

HTTP/1.1 200 OK

참조자료 및 읽을거리