[Network] Application Layer 2 - web과 HTTP

chxghee·2024년 9월 24일

웹은 온디맨드(on-demand) 방식으로 사용자가 원할 때 원하는 것을 수신한다.
웹 상에서 데이터를 주고 받을 때 HTTP 프로토콜을 따르게 되는데,
HTTP 프로토콜메시지의 구조 및 클라이언트와 서버가 메시지를 어떻게 교환하는지에 대해 정의하고 있다.

웹에대해 알기 전에 필요한 용어들을 알아보자.

  1. web page: 웹 페이지들은 여러 객체(object)로 구성된다.

    • 객체(object) : 단일 URL로 지정할 수 있는 하나의 파일 (HTML, JPEG 이미지, 자바스크립트 등)
    • 정확히 말하면 기본 HTML 파일과 여러 참조 객체로 이루어 짐 (기본 HTML 파일도 객체다)
    • 기본 HTML 파일은 페이지 내부의 다른 객체를 그 객체의 URL로 참조한다.
  2. 웹 브라우저(클라이언트)와 서버
    1) 브라우저는 페이지 내부의 객체에 대한 HTTP 요청 메세지를 서버에게 보낸다.
    2) 서버는 요청을 수신하고 객체를 포함하는 HTTP 응답 메시지로 응답한다.

  1. HTTP는 TCP를 전송 프로토콜로 사용한다.

    • 1) 서버와 브라우저 TCP 연결
    • 2) 연결이 이루어지면, 브라우저와 서버 프로세스는 각각의 소켓 인터페이스를 통해 TCP로 접속한다.
    • 3) 클라이언트는 HTTP 요청 메시지를 소켓 인터페이스로 보내고, 소켓 인터페이스로부터 HTTP 응답 메시지를 받는다.
      -> 마찬가지로, HTTP 서버는 소켓 인터페이스로부터 요청 메시지를 받고 응답 메시지를 소켓 인터페이스로 보낸다.
  2. 무상태성(stateless)

    • HTTP 서버는 클라이언트에 대한 정보를 유지하지 않는다.
      (각 요청이 독립적으로 처리되고, 서버가 이전 요청에 대한 상태를 기억하지 않는다.)
    • HTTP가 무상태성인 이유:
      1. 단순성
      2. 서버 부하 감소 -클라정보를 관리하지 않아도됨
      3. 확장성- 요청을 독립적으로 처리하므로, 클라가 여러 요청을 보내더라도 요청마다 다른 서버처리가능
      4. 캐시 사용의 용이성 - 서버는 중복된 요청을 처리할 필요 없이 캐시된 응답을 빠르게 사용가능

상태를 유지해야하는 상황에서는 세션(Session)쿠키(Cookie), 토큰(Token) 사용




비지속 연결과 지속 연결

비지속 연결(Non-persistent HTTP)

클라이언트-서버 상호작용이 TCP 상에서 발생할 떄마다 (object를 가져올 때) 연결-끊기를 반복하는 것

연결과정

1. HTTP 클라이언트는 HTTP 기본 포트 80을 통해 서버로 TCP 연결을 시도한다. TCP 연결과 관련하여 클라이언트와 서버에 각각 소켓이 있게 된다.

2. HTTP 클라이언트는 설정된 TCP 연결 소켓을 통해 서버로 HTTP 요청 메시지를 보낸다. 이 요청에 객체 경로도 포함된다.

3. HTTP 서버는 TCP 연결 소켓을 통해 요청 메시지를 받는다. 저장 장치로부터 경로의 객체를 추출한다.
HTTP 응답 메시지에 그 객체를 캡슐화 하여 소켓을 통해 클라이언트로 보낸다.

4. HTTP 서버는 TCP에게 연결을 끊으라고 한다. (그러나 실제로 클라이언트가 응답 메시지를 올바로 받을 때까지 끊지 않는다.)

5. HTTP 클라이언트가 응답 메시지를 받으면, TCP 연결이 중단된다. 메시지는 캡슐화된 객체가 HTML 파일인 것을 나타낸다.
클라이언트는 응답 메시지로부터 파일을 추출하고 HTML 파일을 조사하여 10개의 JPEG 객체에 대한 참조를 찾는다.

6. 참조되는 JPEG 객체에 대해 1 ~ 4단계를 반복한다.

비지속 HTTP 응답시간

비지속 응답시간은 클라이언트가 HTML 파일을 요청하고 그 파일이 클라이언트로 수신될 때까지의 시간이다. 이 시간을 계산하는 방법은 다음과 같다.

비지속 응답시간 = 2 * RTT + file transmission time(파일 전송시간)

  1. RTT : 작은 패킷이 클라이언트로부터 서버까지 가고, 다시 클라이언트로 되돌아오는 데 걸리는 시간

그림에서
첫 RTT: TCP연결 시작 후 서버가 응답(3Way도 포함한다)
두번째 RTT: 클라이언트가 요청파일을 보내고 서버가 응답
HTML 파일 보내는 시간: 굵은 선

그런데 이걸 매 객체를 보낼때 마다 반복한다는 것이다.
(6개의 이미지 파일과 1개의 기본 HTML 파일을 클라이언트로 보내야 한다면, 7번을 해야한다)

비지속 연결의 장점

  1. 설계 단순성 - 요청처리 후 연결 끊기 반복하므로 단순한 구현 가능

  2. 리소스 관리 - 서버가 불필요한 연결을 계속 유지하지 않아도 되는 장점 즉, 서버는 제한된 리소스를 효율적으로 사용가능.

비지속 연결의 단점

  1. 각 요청 객체에 대해 매번 새로운 연결이 설정되고 유지되어야 한다.
    (TCP연결을 많이 해야함)

  2. TCP 버퍼가 할당되어야 하고, TCP 변수들이 클라이언트와 서버 양쪽에 유지되어야 하는데
    이는 수많은 클라이언트들의 요청을 동시에 서비스하는 웹 서버에는 심각한 부담이다.(오버헤드 큼)

  3. 매번 2RTT를 필요로 한다.

지속 연결(persistent HTTP)

처음 연결될 때 TCP 연결을 하고 그 연결을 유지하며 통신하다, 일정시간 사용하지 않으면 연결이 끊긴다. (디폴트 )

  • 객체에 대한 요구는 진행 중인 요구에 대한 응답을 기다리지 않고 연속해서 만들 수 있다. (파이프라이닝, pipelining)
  • HTTP1.1의 디폴트 모드는 파이프라이닝을 이용한 지속 연결을 사용한다.

지속연결 장점

  1. 오버헤드 감소: TCP 연결 설정 및 해제에서 발생하는 오버헤드가 감소.

  2. 지연 시간 감소: 여러 HTTP 요청을 한 번의 TCP 연결에서 처리하므로, 3-way handshake 및 연결 종료로 인한 지연 시간이 발생x

  3. 네트워크 성능 개선: 지속 연결은 TCP의 혼잡 제어 및 흐름 제어 기능을 잘 활용할 수 있어, 네트워크 성능이 향상. 지속적으로 데이터를 전송할 수 있기 때문에 네트워크 대역폭을 더 효율적으로 사용

지속 연결의 단점

  1. 서버 자원 소모: 연결을 유지하는 동안 서버가 더 많은 연결을 관리해야 하기 때문에, 서버의 메모리와 파일 디스크립터 같은 자원 소모(리소스 부족)

  2. 유휴 연결 처리 문제

지속 연결과 비지속 연결의 비교

항목비지속 연결(Non-Persistent Connection)지속 연결(Persistent Connection)
연결 설정각 HTTP 요청마다 새로운 연결을 설정하나의 연결로 여러 요청을 처리
TCP 연결 오버헤드연결 설정 및 종료 과정에서 오버헤드 발생한 번 설정한 연결을 계속 사용하여 오버헤드 감소
지연 시간각 요청마다 TCP 연결 설정으로 인해 지연 증가연결을 유지하므로 지연 시간 감소
네트워크 효율성비효율적 (여러 요청에 대해 매번 연결 설정)더 효율적 (한 번의 연결로 여러 요청 처리)
서버 자원 관리연결이 즉시 종료되므로 리소스 관리 용이연결을 유지하므로 서버 자원이 소모될 수 있음
HTTP 버전HTTP 1.0에서 기본HTTP 1.1부터 기본 설정



HTTP 요청 메세지

첫줄은 요청 라인, 그 다음 줄들은 헤더 라인이다.

요청 라인

요청 라인은 3개의 필드, 즉 메소드 필드, URL 필드, HTTP 버전 필드를 갖는다.

방식 필드는 GET, POST, HEAD, PUT, DELETE 등의 여러 가지 값을 가질 수 있다.

메소드

  1. POST : form에 입력된 정보를 엔티티 body에 담아 보냄
  2. GET : 유저 데이터를 url로 넘길수 있다
  3. HEAD : HEAD로 요청이 오면, 응답 메세지에 본문(body) 없이 헤더(header) 정보만 반환
    (즉, 서버에 있는 리소스의 상태나 정보에 대한 헤더만을 확인할 수 있으며, 실제 데이터를 가져오지 않는다. = page를 반환받지않음 / 디버그시 사용)
  4. PUT : 서버에 객체를 업로드 할때

헤더 라인

  1. Host
    • 객체가 존재하는 호스트를 명시한다.
    • 이미 호스트까지 TCP 연결이 맺어져 있어 불필요하다고 생각될 수 있지만, 2.2.5절에서 나오는 웹 프록시 캐시에서 필요로 한다.
  2. Connection : 이 헤더 라인을 포함함으로써, 브라우저는 서버에게 지속 연결 사용을 원하는지 비지속 연결 사용을 원하는지 전달한다.
  3. User-agent : 서버에게 요청을 하는 브라우저 타입을 명시한다.
  4. Accept-language : 헤더는 사용자가 객체의 어떤 언어 버전을 원하고 있음을 나타낸다.



HTTP 응답 메세지

상태 라인과 상태 코드

상태 라인(status line)은 버전 필드상태 코드, 해당 상태 메시지를 갖는다.

상태 코드와 메시지

  1. 200 OK: 요청이 성공했고, 정보가 응답으로 보내졌다.
  2. 301 Moved Permanently: 요청 객체가 영원히 이동되었다. 이때, 새로운 URL은 응답 메시지의 Location 헤더에 나와있다.
  3. 400 Bad Request : 서버가 요청을 이해할 수 없다.
  4. 404 Not Found : 요청한 문서가 서버에 존재하지 않는다.
  5. 505 HTTP Version Not Supported : 요청 HTTP 프로토콜 버전을 서버가 지원하지 않는다.

헤더라인

헤더는 응답 메시지에 대한 추가 정보를 제공.

  1. Date: 응답이 생성된 날짜와 시간
  2. Server: 서버 소프트웨어 정보
  3. Content-Length: 응답 본문의 길이
  4. Last-Modified: 요청한 리소스의 마지막 수정 날짜 (클라이언트가 이 헤더를 사용해 캐싱 관리)

등등이 있다

본문

html 파일이나 json 파일을 담아 보낸다


서버가 사용자에 따라 서비스를 할 때면 stateful하게 사용자의 정보를 유지해야 관리가 용이하다.

하지만 http 프로토콜은 기본적으로 stateless이므로 http는 쿠키를 이용해 사용자를 구분할수있다.

쿠키는 http 메세지에 상태를 저장하고 주고 받으며, 서버 입장에서 서비스를 stateless하게 지원할수 있게 도와준다. (무상태성을 보안해줌)

쿠키는 보통 사용자 인증정보, 장바구니, 사용자화 추천, 로그인 세션 상태 등에 사용된다.

쿠키의 동작 과정

  1. 웹 서버에 HTTP 요청 메시지를 전달한다.

  2. 웹 서버는 유일한 식별 번호를 만들고 이 식별 번호로 인덱싱 되는 백엔드 데이터 베이스 안에 엔트리를 만든다.

  3. HTTP 응답 메시지에 Set-cookie: 식별 번호의 헤더를 포함해서 전달한다.

  4. 브라우저는 헤더를 보고, 관리하는 특정한 쿠키 파일에 그 라인을 덧붙인다.

  5. 다시 동일 웹 서버에 요청을 보낼 때
    브라우저는 쿠키 파일을 참조하고 이 사이트에 대한 식별번호를 발췌하여 Cookie : 식별 번호의 헤더를 요청과 함께 보낸다.

  6. 서버는 쿠키식별번호를 확인하여 사용자의 세션 정보를 조회하고, 사용자를 식별하여 이전 상태를 기억하여 처리한다.(쿠키는 사용자 정보와 관련되기 때문에 보안이 중요)


가끔 웹 캐싱과 혼동이 되는데,
웹 캐싱정적 리소스를 프록시 서버에 저장하여 서버로의 요청을 줄여 성능을 향상시키기 위한 것이고,
쿠키클라이언트의 상태 정보를 유지하여 사용자 맞춤형 정보를 제공한다.



웹 캐시(프록시 서버)

예를 들어 한국에 있는 내가 미국에서 서비스 하는 웹페이지 서버에 접속을 한다고 하자, 그러면 미국에 있는 서버에 직접 TCP연결을 하고 통신을 하면 오버헤드가 상당히 크다(응답시간도 길고.. 등등)

이 문제를 해결하기위해 미국 서버의 최근 자주 사용된 웹 object들을 (웹 캐시) 중간에 프록시 서버를 두어 내가 미국 서버에 직접 통신하지 않고 프록시 서버와 통신을 하면 훨신 빠른 웹 서핑을 할 수 있을 것이다.

웹 캐시의 동작 과정

  1. 브라우저는 웹 캐시와 TCP 연결을 설정하고 웹 캐시에 있는 객체에 대한 HTTP 요청을 보낸다.

  2. 웹 캐시는 객체의 사본이 저장되어 있는지 확인하고,
    저장되어 있다면 클라이언트 브라우저로 HTTP 응답 메시지와 함께 객체를 전송한다.
    갖고 있지 않다면, 원 서버로 직접 TCP 연결을 설정한다.

  3. 이후 웹 캐시는 캐시와 서버 간의 TCP 연결로 객체에 대한 HTTP 요청을 보낸다. 기점 서버는 웹 캐시로 HTTP 응답 메시지를 보낸다.

  4. 웹 캐시의 객체를 수신할 때, 객체를 지역 저장장치에 복사하고 클라이언트 브라우저에 HTTP 응답 메시지를 보낸다. (이때, 이미 설정된 TCP를 통해 보낸다.)

그렇다면 캐시(cache) = 프록시 서버는 요청과 응답을 모두 하는 클라이언트이면서 서버이다.

cf) 일반적으로 웹 캐시는 ISP(university, company, residential ISP)가 구입하고 설치한다.

웹 캐시의 사용이유 (장점)

그렇다면 웹 캐시를 사용하개 되면 무슨 장점들이 있는지 알아보자.

  1. 클라이언트 요구에 대한 응답 시간을 줄일 수 있다.
    -보통 클라이언트와 캐시 사이에 높은 속도의 연결이 설정되어 있어 웹서버 캐시에 객체를 갖고 있다면 병목 현상을 줄일 수 있다.

  2. 웹 캐시는 한 기관에서 인터넷으로의 접속하는 링크 상의 웹 트래픽을 대폭 줄일 수 있다.
    -직접 원서버와 연결이 된다면, 네트워크 코어로 여러 요청이 몰려 트래픽이 생긴다.

  3. 인터넷 전체의 웹 트래픽을 실질적으로 줄여주어 모든 애플리케이션의 성능이 좋아진다.


웹 캐시 성능 비교

웹 캐싱 X

가정
• 접속 링크 속도: 1.54 Mbps
• 라우터와 서버 간의 왕복 시간(RTT): 2초
• 웹 객체 크기: 100K 비트 (100,000 비트)
• 브라우저에서 서버로의 평균 요청: 15초당 요청
-> 브라우저로의 평균 데이터 전송률: 1.50 Mbps (평균 요청 * 웹 객체 크기)
• LAN의 용량: 1 Gbps (1,000 Mbps)

퍼포먼스 계산

  • LAN 이용률 = 평균 데이터 전송률 / LAN 용량

    		= 1.50 Mbps /  1 Gbps(= 1,000 Mbps) = 0.0015
  • 접속링크 이용률 = 평균 데이터 전송률 / 접속링크 용량(속도)

    	= 1.50 Mbps / 1.54 Mbps = 0.97
  • end-end delay
    = 라우터와 서버 간의 왕복 시간 + 접속 링크 딜레이 + LAN 딜레이

    = 2초  + 0.97(= 분 단위) +  0.0015(= 마이크로 초 단위)
	= **분 단위로 소요된다.**

따라서 접속 링크가 거의 포화 상태에 가까운 97%의 용량을 사용하고 있기 때문에, 전체 지연 시간(end-to-end delay)이 매우 커진다.

트래픽 강도가 1에 가까워지면 회선의 지연(평균 큐잉 딜레이)매우 커지고 한없이 증가한다.

-> 접속 링크가 병목 구간이 된다.

cf) 단위 (3개씩 올라감)

10^12	테라 (tera)	1 000 000 000 000
10^9	기가 (giga)	1 000 000 000
10^6	메가 (mega)	1 000 000
10^3	킬로 (kilo)	1 000

웹 캐싱 X, 접속 링크 성능 높이면?

그렇다면 링크의 성능을 올리게 되면 어떻게 될까?

위의 가정에서 접속 링크를 154 Mbps 로 100배 빠른 걸로 교체하면,

퍼포먼스 계산

  • LAN 이용률 = 평균 데이터 전송률 / LAN 용량

    		= 1.50 Mbps /  1 Gbps(= 1,000 Mbps) = 0.0015
     
  • 접속링크 이용률 = 평균 데이터 전송률 / 접속링크 용량(속도)

    	= 1.50 Mbps / 154 Mbps = 0.0097 
    • 용량에 비해 데이터를 조금 보내게 된다. (포화x)
  • end-end delay
    = 라우터와 서버 간의 왕복 시간 + 접속 링크 딜레이 + LAN 딜레이

    = 2초  + 0.0097(= 마이크로 초 단위) +  0.0015(= 마이크로 초 단위)
	= **초 단위로 소요된다.**
  

성능이 몇 분단위에서 몇 초 단위로 소요되므로 비약적인 증가가 일어났다.
하지만, 네트워크 코어의 링크를 바꾸는 것은 비용이 많이 든다

-> 이를 해결하기 위해 웹 캐싱을 이용


웹 캐싱 이용

가정 추가
• 캐시 히트율(Cache hit rate): 40% (요청 중 40%는 캐시에서 처리됨)
• 60%의 요청이 원본 서버에서 처리됨.

퍼포먼스 계산

  • 접속 링크 사용 요청 비율: 60%의 요청이 원본 서버에서 처리
    -> 요청의 60% 만 접속 링크를 사용
접속 링크를 통한 브라우저로의 데이터 전송률 60 = 0.6 * 1.50 Mbps = 0.9 Mbps
  • 접속 링크 이용률 = 접속링크를 통한 데이터 전송률 / 접속링크 용량(속도)
0.9 / 1.54 = 0.58

이때 이용률이 0.97에서 0.58로 낮아졌다.
이는 캐시 덕분에 더 적은 트래픽이 접속 링크를 통해 원본 서버로 전달되기 때문
traffic intensity가 0.6 정도라 회선 지연(큐잉딜레이)은 작다


  • end-end delay = 0.6 (원 서버 - 사용자 딜레이) + 0.4 (캐시 - 사용자 딜레이)
= 0.6[ 2초 + 접속링크 딜레이(0.58) + 랜 딜레이(0.0015)] + 0.4[렌 딜레이(0.0015)]
= 0.6(2.01) + 0.4(밀리세컨) = ~1.2 초

1.2초 단위로 전체 지연시간이 줄어든다


이렇게 캐시를 도입했을 때, 접속 링크의 이용률이 크게 감소하고 전체 지연 시간이 1.2초로 줄어드는 효과
(캐시 덕분에 트래픽이 줄어들고, 네트워크 지연 시간도 대폭 감소)

결론적으로, 캐시를 도입하면 네트워크 병목 현상이 크게 완화되고, 데이터 전송 지연도 줄어드는 성능 향상이 있음을 보여줍니다.



조건부(conditional) GET

웹 캐싱을 이용할 때 현재 캐시 만료 시간이 다 되었다면 프록시 서버의 캐시가 최신인지 아닌지 체크를 해야한다.
왜냐하면 이전 웹 페이지를 가지고 있을 때 그걸 클라이언트에 전달하게되는 일이 생기면 안되기 때문이다.

즉, 복사본이 클라이언트에 캐싱된 이후 웹 서버에 있는 객체가 갱신되었을 수도 있는 상황에서, HTTP는 클라이언트가 브라우저로 전달되는 모든 객체가 최신의 것임을 확인하면서 캐싱해주는데,

이러한 방식을 조건부 GET(conditional GET) 이라고 한다.

조건부 get은
1. GET 방식을 사용하고,
2. If-modified-since 헤더를 포함한다.

조건부 GET 동작과정

(위의 상황에서 클라이언트 = 프록시 서버 의미.)

  1. 브라우저의 요청을 대신해서 프록시 캐시는 요청 메시지를 웹 서버로 보낸다.

  2. 웹 서버는 캐시에게 객체를 가진 응답 메시지를 보낸다.

1. 캐싱 이후 웹 서버에 있는 객체가 갱신되지 않았을 때

  1. http 요청 메세지에 If-modified-since 헤더를 포함하여 캐시가 최신 캐시인지 확인하는 메세지를 서버에 보낸다.

  2. If-modified-since 헤더data가 서버에 저장된 Last modified 값과 일치하면 그 캐시는 최신캐시인 것이 인증된다.

  3. 서버는 304 Not Modified 메세지를 보낸다 (웹 페이지는 보내지 않음)

    • 사용자가 해당 캐시를 사용하라는 메세지

2. 캐싱 이후 웹 서버에 있는 객체가 갱신되었을 때

  1. http 요청 메세지에 If-modified-since 헤더를 포함하여 캐시가 최신 캐시인지 확인하는 메세지를 서버에 보낸다.

  2. If-modified-since 헤더data가 서버에 저장된 Last modified 값보다 이전 이라면 그 캐시는 오래된 캐시이다.

  3. 서버는 200 OK 메세지와 함께 새 웹 페이지를 같이 보낸다.

  4. 이때 프록시 서버는 받은 웹페이지를 브라우저에 보내고 지금 시간 정보와 함께 캐시에 저장한다.



HTTP 변천사

HTTP1

HTTP1.1는 기본 동작이 지속 연결을 사용한다,

지속적인 연결을 사용할 때 웹 페이지당 오직 하나의 TCP 연결을 가짐으로써,
아래 설명하듯이 서버에서의 소켓 수를 줄이며 전송되는 각 웹 페이지는 공정한 네트워크 대역폭을 가질 수 있다.

그러나 하나의 TCP 상에서 모든 웹페이지를 보내면 HOL(Head of Line) 블로킹 문제가 발생할 수 있다.

문제점

  1. HOL 블로킹 문제
  • head od line 블로킹
  • 하나의 TCP 연결에서 비디오와 사진을 보낼 때, 먼저 무거운 비디오 같은 객체를 보내면 사진 같은 가벼은 객체는 기다려야한다

-> HTTP/1.1에서는 여러 개의 병렬 TCP 연결을 열어서 위 문제를 해결

  1. loss recovery
  • retransmission 하는 시간이 오래 걸린다.

HTTP2

HTTP2의 주요 목표 중 하나는 하나의 웹 페이지를 전송하기 위한 병렬 TCP 연결의 수를 줄이거나 제거하는 데 있다.

이는 서버에서 열고 유지되는 데 필요한 소켓의 수를 줄일 뿐만 아니라 목표한 대로 TCP 혼잡 제어를 제어할 수 있게 하는 데 있다.

http1의 HOL 블로킹 문제를 해결 -> 프레이밍(framing) & interleaving

위와 같이 각 데이터 객체를 여러 프레임(framing)으로 나누고, 번갈아(interleaving) 데이터를 전송하고 반대편 사이트에서 재조립하는 것이다.

서버 푸싱

  • 특정 클라이언트 요청에 대해 여러 개의 응답을 보낼 수 있다.
    처음 요청에 대한 응답 외에도, 서버는 클라이언트의 요청 없이도 추가적인 객체를 클라이언트에게 푸시하여 보낼 수 있다.

메시지 우선순위화 도 개발자가 지정할수 있다.

HTTP3

HTTP2의 보안 문제와 loss 처리시 지연 문제를 해결한다.

UDP를 사용

profile
다 같이 화이팅! 🙋‍♂️

0개의 댓글