HTTP 는 HyperTest Transfer Protocol
HyperTest 문서를 전송하는 프로토콜로 시작했다.
그런데 지금은 모든 것을 HTTP 에 담아서 전송한다
대부분의 기능은 HTTP/1.1 에 개발되었고 그 이후로 개발된 HTTP/2 나 HTTP/3 는 성능 개선이 된 버전이다.
실제로 구글에서 개발자 모드로 하고 검색을 해보면 프로토콜에 h3(HTTP/3) 를 사용하는 것을 볼 수 있다.
HTTP 는 클라이언트 서버 구조로 되어 있다. 클라이언트가 HTTP 메시지를 생성해서 서버에게 요청을 보내고 응답이 올때까지 기다린다. 서버가 요청에 대한 응답을 만들어서 응답이 오면 응답 결과를 열어서 클라이언트가 동작하게 된다.
매우 단순한 구조이다.
그런데 이렇게 클라이언트와 서버를 분리를 하는 것이 중요하다. 이전에는 클라이언트와 서버가 한 뭉탱이에 있었다. 이렇게 분리를 하여 비즈니즈 로직과 데이터 같은 것은 서버에 다 밀어 넣고 클라이언트는 UI 와 사용성에만 집중한다.
이렇게 분리를 하면 좋은 점은 클라이언트와 서버가 각각 독립적으로 진화할 수 있다. 클라이언트는 복잡한 데이터를 다룰 필요가 없고 그냥 단순하게 UI 를 어떻게 그릴 것인가 어떻게 하면 사용자가 더 편하게 사용할 수 있는가에만 집중하면 된다.
서버도 사업이 잘되어서 트래픽이 100배 증가 한다고 하였을 때 클라이언트 부분은 손댈 필요 없이 서버에서 어떻게 대용량 트래픽을 관리할지에만 집중하면 된다.
HTTP 의 중요한 특징 중 하나로 무상태 프로토콜을 지향한다는 것이다. 이것을 영어로 Stateless 라고 한다.
이게 무슨말인가 하면 다음 예제를 보자.
Stateful 은 서버가 클라이언트의 이전 상태를 보존한다는 것이다. 위 예시로 보면 문맥을 보존한다는 것이다.
Stateful 상황을 풀어서 살펴보자.
고객이 노트북이 얼마냐고 물어보면 점원은 100만원이라고 말하면서 노트북이라는 상태를 유지한다. 즉, 고객이 노트북을 사려고 한다는 것을 유지한다.
고객이 2개를 구매한다고 하면 점원은 200만원이라고 얘기할 수 있다. 왜냐하면 고객이 노트북을 구매하려고 한다는 상태를 알고있기 때문이다. 그리고 결재 수단을 물어보면서 점원은 고객이 노트북을 구매하고 2개 구매한다는 상태를 유지한다.
고객이 신용카드로 구매하겠다고 하면 점원은 고객이 노트북을 2개를 신용카드로 구매하겠다는 것을 알고 결재를 완료한다. 노트북, 2개, 신용카드 ****상태를 유지한다.
Stateless 상황을 보자.
이전과 차이를 볼 수 있을 것이다. 무상태에서는 고객이 필요한 정보를 다 넘겨준다. 그래서 중간에 점원이 바뀌어도 아무 문제 없다.
그림을 통해서 살펴보자. 먼저 Stateful 이다.
클라이언트A 가 요청을 보내면 서버1 이 응답을 하면서 서버1은 클라이언트가 노트북을 2개 사고 싶다는 상태를 유지하고 있다. 이렇게 되면 서버를 늘리기 어렵다. 왜냐하면 클라이언트A 는 서버1 하고만 통신해야 하기 때문이다.
여기서 문제가 있다.
중간에 서버1이 장애가 오면 클라이언트A 는 다른 서버와 처음부터 다시 해야한다.
그런데 Stateless 는 애초에 요청할 때 부터 필요한 데이터를 다 담아서 서버에게 요청한다.
서버는 상태를 보관하지 않는다.
그러면 만약 서버1이 장애가 나면 다른 서버와 통신하면 된다. 중간에 다른 문맥이 필요 없다. 필요 데이터를 클라이언트가 다 담아서 보내주기 때문에 거기에 대한 응답만 해주면 된다.
서버를 쫘악 늘리는 것을 스케일 아웃이라고 하는데 이것을 수평 확장이라고 한다.
무상태는 스케일 아웃에 굉장히 유리하다.
그래서 큰 이벤트를 한다고 하면 백엔드에서는 장비를 수십대 늘릴 수 있다.
연결을 유지하는 모델에 대해서 먼저 살펴보자.
클라이언트1이 서버와 TCP/IP 로 연결을 한다음에 요청을 보내고 응답을 받는다.
그러고 클라이언트2가 서버에 접속해서 요청을 보내고 응답을 받는다.
이때 클라이언트1과 서버는 연결을 유지하고 있는다.
그러고는 클라이언트3도 서버와 연결을 한다. 이동안 클라이언트1과 클라이언트2는 서버와 연결을 유지하고 있다.
이러면 연결을 유지하는 서버의 자원이 계속 소모되고 있는 것이다.
그러다가 다시 클라이언트1의 요청이 오면 서버가 응답을 할 것이다.
이러한 방식의 단점은 클라이언트2와 클라이언트3이 놀고 있어도 서버가 연결을 계속 유지해야하는 단점이 있다.
그러면 이번에는 연결을 유지하지 않는 모델에 대해서 살펴보자.
클라이언트1에서 서버와 연결을 하고 요청을 보내고 응답을 받았다.
그러면 볼일이 끝나서 즉시 클라이언트1과의 연결을 종료한다.
클라이언트2와 3도 똑같이 서버와 연결을 해서 요청과 응답을 받고 그 즉시 바로 연결을 종료한다.
이러한 방식의 장점은 자원을 요청을 주고 받을 때만 연결을 유지하고 그 다음에는 끊어버려서 서버가 유지하는 자원을 최소한으로 줄인다.
웹 사이트 접속을 한다고 요청을 하면 연결을 하고 HTML 을 요청하여 응답 받고 종료한다. 그런데 이 웹 사이트에서는 자바스크립트도 필요해서 또 연결을 하고 요청하여 자바스크립트를 응답 받고 연결을 종료한다. 그런데 또 보니까 이 웹사이트는 이미지도 필요한 것이다. 그러면 또 연결해서 요청, 응답 받고 종료하고 너무 비효율 적이다.
지속 연결의 경우는 웹 사이트에 연결해서 HTML 을 응답 받고 연결을 유지하여 더 필요한 자바스크립트와 이미지도 요청하여 응답 받고 종료한다.
내부적인 로직에 따라 다르지만 몇 ms 만큼 유지하는 등의 방식으로 웬만한 웹 사이트에 필요한 자원을 다 받을 때 까지 연결을 유지한다.
HTTP/2 와 HTTP/3 에서는 이러한 지속 연결을 더 최적화 하였다,
HTML, TEXT, 이미지, 영상, 음성, 파일 JSON, XML, 등등 거의 모든 형태의 데이터를 HTTP 메시지로 전소안다. 서버간의 데이터를 주고 받을 떄도 대부분 HTTP 를 사용한다. 바야흐로 지금은 HTTP 시대
이전에 보았듯이 HTTP 요청 메시지와 HTTP 응답 메시지는 조금 달랐다. 먼저 HTTP 메시지 구조에 대해서 살펴보자.
이런식으로 있다. 여기서 empty line
은 무조건 있어야 한다.
공식 스펙에서도 볼 수 있다. message body
는 올수도 안올수도 있다.
시작 라인은 request line 과 status line 으로 나눠져 있다.
/
로 시작하는 경로*
, https://....?x=y
와 같은 유형으로 경로를 지정하는 방법도 있음start-line = request-line / status-line
status-line = HTTP-version SP status-code SP reason-phrase CRLF
HTTP 버전
HTTP 상태 코드 : 요청 성공, 실패를 나타냄
이유 문구 : 사람이 이해할 수 있는 짧은 상태 코드 설명 문구
:
OWS field-values OWS (OWS : 띄어쓰기가 있어도 되고 없어도 됨)