[Network] 2-2. The Web and HTTP (1)

Park Yeongseo·2024년 7월 9일
0

Network

목록 보기
7/16
post-thumbnail

1. Overview of HTTP

하이퍼텍스트 전송 프로토콜(HTTP, HyperText Transfer Protocol)은 웹의 핵심이 되는 애플리케이션 계층 프로토콜이다. HTTP는 클라이언트 프로그램과 서버 프로그램, 두 프로그램에서 구현되며, 서로 다른 종단 시스템에서 실행되는 클라이언트 프로그램과 서버 프로그램은 HTTP 메시지를 교환함으로써 서로 대화할 수 있게 된다. HTTP는 이 메시지들의 구조 및 클라이언트와 서버의 메시지 교환 방식을 정의한다.

HTTP에 대해 더 자세히 알아보기 전에, 웹에서 사용하는 용어들을 훑어보자. 웹 페이지, 혹은 문서(document)에는 여러 객체(object)들이 있다. 여기서 객체란 HTML 파일, 이미지 파일, 자바 애플릿, 비디오 클립 등 어떤 URL을 주소로 가질 수 있는 모든 파일들을 말한다. 대부분의 웹 페이지에는 기본(base) HTML 파일과 여러 참조 객체들이 포함되어 있다.

이 기본 HTML 파일은 객체들이 가지고 있는 URL을 통해 해당 객체들을 참조하는데, 이 URL은 호스트명과 경로명의 두 부분으로 나뉠 수 있다. 예컨대 www.school.edu/dpt/picture.gif라는 URL에서 www.school.edu호스트명이고, /dpt/picture.gif경로명이다.

HTTP는 웹 클라이언트가 어떻게 웹 서버에게 웹 페이지를 요청하고, 또 어떻게 서버가 해당 웹 페이지를 클라이언트 전송하는지를 정의한다. 이에 대해서는 나중에 더 자세히 알아보겠지만, 간단히 말하자면, 클라이언트는 페이지의 특정 객체에 대한 HTTP 요청 메시지를 서버에 보내고, 서버는 요청을 받아 요청된 객체들을 포함하고 있는, 해당 메시지에 대한 HTTP 응답 메시지를 클라이언트에게 보낸다.

HTTP는 보통 UDP보다는 TCP를 기저 전송 프로토콜로 사용한다. HTTP 클라이언트는 우선 서버에 TCP 연결을 시작하고, 연결이 되면 브라우저와 서버 프로세스는 자신의 소켓 인터페이스를 이용해 TCP에 접근한다. 클라이언트는 HTTP 요청 메시지를 자신의 소켓 인터페이스로 보내고, HTTP 응답 메시지를 자신의 소켓 인터페이스로부터 받으며, 서버도 비슷하게 HTTP 요청 메시지를 소켓 인터페이스로부터 받고 HTTP 응답 메시지를 소켓 인터페이스로 내보낸다.

클라이언트와 서버가 소켓으로 HTTP 메시지를 내보내고 나면, 그 이후의 일은 모두 TCP의 몫이다. TCP가 신뢰할 수 있는 데이터 전송 서비스를 제공하므로, 한쪽에서 보낸 메시지는 반드시 상대에 도착함이 보장된다.

중요하게 알아야 할 것은, 서버는 클라이언트에 대한 어떤 상태 정보도 저장하지 않고, 클라이언트에게 요청된 파일을 전송한다는 것이다. 어떤 클라이언트가 동일한 객체를 단시간에 두 번 요청했다고 해보자. 서버는 해당 객체가 방금 서비스 된 객체라고 응답하지 않고, 그냥 그 객체를 응답에 담아 클라이언트에게 보낸다. 이렇듯 HTTP 서버가 클라이언트에 대한 어떠한 정보도 가지고 있지 않기 때문에, HTTP는 무상태 프로토콜(stateless protocol)이라 불린다.

2. Non-Persistent and Persistent Connections

많은 인터넷 애플리케이션에서 클라이언트와 서버는, 일련의 요청을 보내고 그 각 요청들에 대해 응답하는 식으로 장시간 통신을 하기도 한다. 애플리케이션의 종류에 따라, 이러한 일련의 요청은 계속해서 연달아 보내질 수도, 어느 정도의 구간을 가지고 정기적으로 보내질 수도, 혹은 간헐적으로 보내질 수도 있다.

어쨌든 이런 클라이언트-서버 상호작용이 TCP에서 이루어진다고 한다면, 애플리케이션 개발자는 이러한 요청/응답 쌍 각각을 여러 개별 TCP 연결에서 주고 받을지, 혹은 일련의 요청과 응답을 하나의 TCP 연결에서 주고 받을지를 선택해야 한다. 전자의 방식을 비지속 연결(non-persistent connection)이라 하고, 후자의 방식을 지속 연결(persistent connection)이라 한다. HTTP에서는 기본적으로 지속 연결을 사용하지만, 필요하다면 비지속 연결을 대신 사용하도록 설정할 수도 있다.

HTTP with Non-Persistent Connections

http://www.school.edu/dpt/home.index라는 페이지에 접속하려한다고 해보자. 이 페이지는 기본 HTML 파일과 10개의 JPEG 이미지 파일이 있으며, 이 모든 객체들은 같은 서버에 있다. 클라이언트가 해당 페이지를 요청하면 다음과 같은 일이 일어난다.

  1. HTTP 클라이언트 프로세스는 www.school.edu의 호스트명을 가지고 있는 서버의 80번 포트(HTTP 기본 포트)에 TCP 연결을 시작한다.
  2. HTTP 클라이언트가 HTTP 요청 메시지를 소켓을 통해 서버로 보낸다. 요청 메시지에는 경로명 /dpt/home.index가 포함되어 있다.
  3. HTTP 서버 프로세스는 소켓을 통해 요청 메시지를 받고, 경로명을 통해 자신의 스토리지를 검색해 해당 객체를 가져온다. 이 객체를 HTTP 응답 메시지로 캡슐화한 후 소켓을 통해 응답 메시지를 클라이언트에게 보낸다.
  4. HTTP 서버는 TCP에게 TCP 연결을 끊으라고 한다. 단, TCP는 해당 메시지가 클라이언트에게 도착했음이 알려질 때까지는 연결을 끊지 않는다.
  5. HTTP 클라이언트가 응답 메시지를 받고, TCP 연결이 끝난다. 이 메시지에 캡슐화된 객체는 HTML 파일이다. 클라이언트는 응답 메시지에서 파일을 추출하고, 이 HTML 파일을 분석하고, 10개의 JPEG 객체에 대한 참조를 찾는다.
  6. 10개의 JPEG 객체들에 대해, 위 과정을 반복한다.

비지속 연결에서는 위와 같이 TCP 연결이 정확히 한 요청 메시지와 한 응답 메시지 전송 동안만 유지된다. 따라서 위 예에서 사용자는 웹 페이지를 요청하면 11개의 TCP 연결이 생성된다.

다만, 위에서는 10개의 JPEG 객체들을 각자 순차적으로 요청해야하는 것처럼 모호하게 말했지만, 사실 그렇지는 않다. 현대 브라우저들은 보통 기본적으로 5-10개의 병렬 TCP 연결을 열어, 각각이 하나의 요청-응답 상호작용을 처리할 수 있도록 할 수 있다. 물론 사용자가 원한다면 최대 병렬 연결 수를 1로 만들어, 10개의 연결이 순차적으로 일어나게 할 수도 있겠지만, 병렬 연결을 활용하는 것이 응답 시간을 줄이는 데에 더 효과적이다.

여기서 다음으로 넘어가기 전에 잠깐, 클라이언트가 기본 HTML 파일을 요청하고 해당 파일을 받을 때까지 얼마나의 시간이 흐르는지를 대략적으로 계산해보자. 이 계산을 위해서는 RTT(round-trip time)를 이용하는데, RTT란 작은 패킷이 클라이언트에서 서버로 갔다가 다시 클라이언트로 돌아오는 데 걸리는 시간을 말한다. RTT에는 패킷-전파 지연, 패킷-큐잉 지연, 패킷-처리 지연 등이 포함되어 있다.

사용자가 하이퍼링크를 클릭했다고 해보자. 이때 브라우저는 브라우저와 웹 서버 사이의 TCP 연결을 시작한다. 이때 3-way handshake라고 불리는 과정이 일어난다(그림의 얇은 세 화살표). 3-way handshake의 첫 번째 두 과정은 1 RTT가 걸리는데, 클라이언트는 서버에 작은 TCP 세그먼트를 보내고, 서버는 이를 받아 또 작은 세그먼트를 클라이언트에게 보낸다.

이 두 과정이 끝나고 나면 클라이언트는 3-way handshake의 세 번째 부분과 함께 HTTP 요청 메시지를 TCP 연결로 보낸다. 이 요청이 서버에 도착하면 서버는 HTML 파일을 TCP 연결로 보낸다. 이 HTTP 요청/응답에도 1 RTT가 걸린다. 따라서 전체 응답 시간은 대충 2 RTT에 서버에서의 HTML 파일 전송 시간을 더한 정도가 된다.

HTTP with Persistent Connections

비지속 연결에는 몇 가지 단점이 있다. 우선 요청된 각 객체마다 새로운 연결이 만들어지고 유지 되어야 한다. 클라이언트와 서버는 이 각각의 연결에 대해, TCP 버퍼를 할당하고 TCP 변수들도 관리를 해줘야 하고, 이는 수많은 클라이언트로부터의 요청들을 처리해줘야 하는 웹 서버에게 큰 부담이 된다. 또한, 각 객체를 가져오는 데에 약 2 RTT가 걸리므로 시간적으로도 너무 느리다.

HTTP 1.1의 지속 연결을 사용하면, 서버는 응답을 보내고 나서도 얼마간 TCP 연결을 열어 놓는다. 이후 동일한 클라이언트와 이루어지는 요청/응답은 같은 연결을 통해 이루어진다. 지속 연결을 사용할 때, 위의 기본 HTML 파일과 10개의 이미지들은 모두 같은 연결을 통해 전송되며, 위와 같은 단일 페이지의 경우 뿐만 아니라, 한 서버에 있는 여러 웹 페이지를 보낼 때에도 마찬가지로 한 연결을 통해 전송될 수 있다.

0개의 댓글