구글 검색창에 hello를 입력 했다고 가정 하고, 클라이언트와 서버의 통신 과정을 자세히 살펴보자.
구글 창에서 입력을 받으면 웹브라우저는 URI를 위와 같이 변경하며, 이 URI를 파싱(parsing)해 HTTP 요청 메시지를 생성한다. 이때 DNS를 조회해 호스트의 IP주소를 가져온다.
검색한 내용을 조회하는 요청으로 GET을 보내며, 검색 내용q=hello
과 언어hl=ko
, HTTP 버전 HTTP/1.1
, 그리고 호스트 주소가 들어있다.
웹브라우저가 HTTP 메시지를 생성하면 애플리케이션에서는 이를 소켓 라이브러리를 통해 OS로 전달한다.
이 때 소켓은 TCP/IP를 연결하고(IP, PORT 주소 가져오기) 데이터를 전달한다. 이후에는 OS 커널에서 TCP/IP 패킷을 생성하는데, 이때 브라우저에서 만든 HTTP 메시지가 이 패킷에 포함된다. 마지막으로 네트워크 인터페이스를 통해 서버로 전송된다.
출발지/도착지의 IP와 PORT 주소가 들어있으며, 전송 데이터에 해당하는 HTTP 메시지가 들어있는 것을 확인할 수 있다
OS를 거쳐 만들어진 요청 패킷은 네트워크 인터페이스, LAN과 라우터를 거쳐 인터넷 상으로 전송되어 서버로 간다.
서버는 웹브라우저로부터 요청을 받으면 그 내용을 확인 후 해당 요청에 맞는 정보를 반환해준다. 이때, 서버에서 클라이언트에게 반환해주는 정보를 포함한 메시지를 살펴보면 위 그림과 같은 형식을 가진다. 응답 메시지는 HTTP 헤더와 HTTP 바디로 나뉘며, HTTP 헤더에는 HTTP 버전
, HTTP 상태 코드
, 정보의 타입
, 그리고 길이(Content-Length)
가 들어간다.
서버 측에서도 클라이언트 측에서 요청을 보낸 과정과 동일하게 패킷을 생성한 후 클라이언트에게 응답을 보내게 된다.
최종적으로 클라이언트의 브라우저는 클라이언트가 서버에게 요청한 HTML 정보를 화면에 렌더링 해준다.
HTTP(Hyper Text Transfer Protocol) 하이퍼미디어 문서를 전송하기 위한 프로토콜
같은 시간에 딱 맞춰 발생하는 대용량 트래픽(선착순 이벤트, 예약, 티케팅, 수강신청 등) 비연결성이 의미없을 정도로 트래픽 규모가 커서 당황할 수 있지만, 최대한 stateless하게 설계하는 것이 중요하다. 대용량 트래픽과 요청에도 서버의 규모를 확장해서 대응 할 수 있는 부분이 많다. 이벤트 설계 시 많이 사용된다(사용자가 이벤트 html을 어느정도 사용한 후에 이벤트 참여 버튼을 동작시키도록 하는 경우)
HTTP는 연결을 유지하지 않는 모델이다. 클라이언트에서 요청을 하면 서버는 응답을 하는데, 이 요청-응답의 상태가 연결이 되어 있는 상태에서 계속 왔다갔다 하는 것이 아니라 각 요청과 응답이 분리되어 있다. 하나의 선으로 연속적으로 연결되어 있는 상태에서 계속 주고받는 게 아니라 서로 쪽지를 주고받는 것처럼 단절되어 있다. 만약, 항상 연결되어 있는 상태라면 그 유지시간만큼 자원을 낭비하게 될 것이다. 이처럼 자원 낭비를 방지하기 위해 비연결성을 지향한다.
하지만 이렇게 비연결성을 지니면 한계점이 생기는데, 매번 요청할 때마다 TCP/IP 연결을 새로 맺어야 한다. 그만큼 3 Way Handshake 시간이 추가된다. 또한 웹 브라우저로 사이트를 요청하면 한 번에 다 보내주는 게 좋으니 필요 없는 다른 수많은 자원 역시 함께 클라이언트로 전송된다. 지금은 이것을 HTTP 지속 연결 방식으로 문제를 해결했다.
HTTP/3은 QUIC 이라는 계층 위에서 돌아가며, TCP 기반이 아닌 UDP 기반으로 돌아간다. QUIC은 TCP를 사용하지 않기 때문에 통신을 시작할 때 번거로운 3 Way Handshake과정을 거치지 않아도 된다.
Quic은 첫 연결 설정에 1-RTT(패킷의 왕복 시간)만 소요된다.
QUIC은 순방향 오류 수정 메커니즘(FEC, Forward Error Correction)이 적용되었다. 이는 패킷이 손실되면 수신 측에서 에러를 검출하고 수정하는 방식이며 열악한 네트워크 환경에서도 낮은 패킷 손실률을 자랑한다.
기본적으로 start line, header, 공백, body로 구성되어있는 HTTP 메시지는 요청 메시지와 응답 메시지로 분리되며, 각각의 구조는 다음과 같다.
- Request line
method
/request target
/HTTP 버전
method
: HTTP 메서드 - 서버가 수행해야 할 동작을 지정한다request target
: 요청 대상 - 절대경로[?query].절대경로
- Status line
HTTP 버전
/HTTP 상태 코드
/HTTP 상태의 간략한 이유
- 참고: 200(성공), 400(클라이언트 요청 오류), 500(서버 내부 오류)
- Header
필드명
":"OWS field-value OWS
- 필드명은 대소문자 구분이 없다. HTTP헤더의 용도는 HTTP 전송에 필요한 모든 부가정보를 포함시키는 것.
- 메시지 바디의 내용이 html인지, 메시지 바디의 크기나 압축의 여부, 인증 정보, 요청 클라이언트 정보, 응답하는 서버 애플리케이션의 정보, 캐시에 대한 정보 등이 들어있다.
- 사전에 약속을 한 클라이언트와 서버 간에 필요에 따라 임의의 헤더를 추가 할 수 있다.
- Body
- 실제 전송할 데이터를 담는 용도
- 바이트로 표현할 수 있는 모든 데이터를 전송할 수 있다.
REFERENCE: 모든 개발자를 위한 HTTP 웹 기본 지식