티스토리 뷰

Network

2.2 웹과 HTTP

김남김 2022. 10. 14. 11:39

웹을 통해 우리는 채팅도 하고 메일도 주고받고 뉴스도 보고 영화도 보고 할 수 있는 것이 저엉~~말 많다.

이번 포스트를 통해서 이렇게 많은 서비스를 제공하게 해주는 웹에 대해 알아보고 웹이 사용하는 애플리케이션 프로토콜 HTTP에 대해 알아보자. 

 

HTTP 개요 

HTTP는 애플리케이션 프로토콜로써 각 다른 종단 시스템간 웹을 통해 (HTTP) 메시지를 전달하게 해준다. 

 

여기서 응답 메시지로 받은 웹페이지는 객체의 구성으로 (html 파일, JPG, 자바스크립트 등) 객체 묶음을 URL(naver.com)로 지정되는하나의 파일이다.

ex) 하나의 페이지에 html 텍스트 4개 ,JPEG 파일 한개가 있다면 해당 웹사이트는 6개의 구성으로된 것이다.

 

 

이렇게 구성된 웹 페이지를 어떻게 요청할까?

 

우리는 서버에  요청할 때 브라우저 상단에 아래와 같은 URL을 입력한다.

http :// www.naver.com/stock/tesla.gif  

 

웹서버는 이러한 URL 많이 갖고 있으며 각각URL에 지정할 수 있는 웹 객체를 갖고있다. 

그렇기에 해당 URL과 요청 값을 통해 클라이언트가 원하는 응답 메시지를 전달하게 되는 것이다.

(HTTP는 웹 클라이언트가 웹 서버에게 어떤 페이지를 어떻게 요청하는지와 어떻게 전송하는지를 정의한다.)

 

                  http                     http

client1 <----------> server <-----------> client2  

 

(내가 이거 보고싶으니까 HTTP1.1로 보내줘) HTTP 요청

(그래 너가 원하는 테슬라 주가 웹페이지야) HTTP 응답 

 


HTTP 와 TCP 

HTTP(애플리케이션 프로토콜)는 TCP(트랜스포트 프로토콜)를 사용한다. 

클라이언트는 HTTP 요청 메시지를 소켓에 보내고 소켓으로부터 HTTP 응답을 받는다. /서버도 마찬가지다. 

 

Client( Http )/ socket(TCP) ------------------socket(TCP) / Server(Http)

 

결국 실질적인 데이터 전달은 소켓(using TCP)간 일어난다. 

이러한 구조는 HTTP는 데이터손실, 복구, 순서배열을 걱정할 필요 없게 하며, 과정에서 발생하는 문제는 TCP와 프로토콜 스택의 하위 계층에서 맡게된다. 

 

 

HTTP는 TCP를 사용함으로 비상태를 유지하는데 비상태 프로토콜 이라고 해서

연결된 상태를 유지하지 않으며 서버가 클라이언트의 상태를 기억하고 있지않고 통신하게된다.

 

 

이게 무슨 말이냐면 

내가 네이버에 로그인을 시도한다고 치자                       

나 ---(로그인 시도)---> 네이버

 

 

네이버에서는 로그인이 성공했다고 내게 정보를 보낸다         

나 < ------(엉 로그인 됐어) ---- 네이버 

 

 

그러나 내가 로그인이 성공했다고 해서 네이버가 기억하고 있다는 것은 아니다          

나 ----(나 로그인했으니까 메일 확인좀!!) -----> 네이버 

나  <------(님 누구임? 남의 정보에 함부로 들어가려 하네? 실패) --- 네이버  

 

나야 나~&nbsp; 나몰라???

 

뭔가 이상하다.....

나는 분명 네이버 사이트에 로그인해서 메일도 주고받고 할 수 있는데 로그인 유지가 안된다니? 

네이버에서는 내가 로그인을 시도했고 성공했다는 사실을 계속 기억하고 있진 않는다. 

그러나 로그인 성공시에 로그인을 보장해주는 데이터를 실어주어 클라이언트가 계속해서 그 데이터값을 갖고 요청을 하면 로그인이 유지되는 것이다 .

 

나 ---(로그인 시도)---> 네이버

나 < ------(엉 로그인 됐어 + 토큰) ---- 네이버 

나 ----(나 로그인했으니까 메일 확인좀!! + 토큰) -----> 네이버 

나  <------(토큰 읽어보니 김남김님이시군요? 네 알겠습니다 여기용 ) --- 네이버  

 

 


 

 

비지속 연결과 지속연결 

HTTP 입장에서 비지속 연결과 지속 연결 모두를 사용할 수 있다.

이를 통해 데이터를 주고받을 수 있는데 각 장단점을 살펴보자 

 

 

비지속 연결 HTTP

웹 페이지를 서버에서 클라이언트로 전송하는 단계를 살펴보자 

 

 

http :// www.naver.com/stock/tesla.index

(여기서  http :// www.naver.com  은 호스트 이름 이며

/stock/tesla.gif는 경로 이름이다. )

 

 

1. 클라이언트는 HTTP의 기본 포트번호 80을 통해 www.naver.com  서버로 TCP 연결을 시도한다. 

2. 1단계에서 설정된 TCP 연결 소켓을 통해 서버로 /stock/tesla.index 경로 이름을 포함한  HTTP 요청메시지를 보낸다. 

3. 서버는 소켓을 통해 요청 메시지를 받고 /stock/tesla.index 객체를 추출하여  HTTP 응답 메시지에 캡슐화하고 클라이언트에게 보낸다.

4. 서버는 TCP 연결을 끊으라고 한다 (클라이언트가 다 응답 메시지를 받을 떄까지 끊지는 않는다. )

5. 클라이언트가 응답 메시지를 받으면 TCP 연결이 끊어진다. 클라이언트는 응답 메시지로부터 파일 추출하고 조사하여 화면에서 확인한다. 

 

위 단계와 같이 TCP연결이 서버가 객체를 보내고 끊어지므로 비지속 연결을 확인할 수 있다. 

HTTP 1.0은 이러한 비지속 연결을 지원하며 TCP연결은 하나의 요청 메시지에 하나의 응답 메시지만 전송한다. 

예시로. 사용자가 웹페이지를 요청할 떄 객체 참조에 따라 11개의 TCP 연결이 만들어진다. 

++ 동시 연결하면 응답시간이 줄어들 것이다. 

 

 

RTT 측정 

그럼 이제 웹페이지이지를 클라이언트가 HTTP 요청을하고 클라이언트에게 HTTP 응답이 수신될 때까지의 시간을 측정해보자 . 

 

우리가 구하고자 하는  클라이언트로부터 -> 서버 -> 클라이언트의 시간을  RTT(round - trip- time)라고 한다. ( 큐잉지연, 패킷지연 등 포함) 

TCP 연결을 시도할 때 이는 세방향 핸드쉐이트(3way hand shake)를 포함한다. 

 

여기서

3 - Way Handshake란?

연결형 통신은 위에서 TCP헤더의 SYN, ACK를 통해 확인하며 데이터를 전송하는데 아래와 같이 이뤄진다. 

 

연결 확립 요청 SYN ->

컴퓨터 1                     <-연결 확인 응답 SYN + 연결 확립 요청 ACK                       컴퓨터 2

연결 확립 응답->

 

이처럼 데이터를 보내기전에 연결을 확립하기 위해 패킷요청을 3번 교환하는 것이 3 - Way Handshake 라고한다. 

(연결을 끊을 때는 FIN과 ACK 사용 )

 

연결 종료요청 FIN -> 

컴퓨터 1                                          <- 연결 종료 응답                                            컴퓨터 2

<-연결 종료 요청   

연결 종료 응답 ->

 

그렇게 HTTP 요청/응답은 이러한 연결과 함께 또 하나의 RTT를 필요로 하는데 

TCP 연결 초기화 하고 응답까지의 RTT 

파일 요청 후 (파일전송시간) + 파일 수신 까지의 RTT 해서 

 

총 TCP 연결 RTT + 파일 송수신 RTT 로  데이터 요청 응답의 총 시간을 정의하게된다. 

 


 

지속연결 HTTP 

비지속 연결은 단점이 있다.

그 단점은 각 요쳥에 대한 새로운 연결이 설정되고 유지되어야한다는 것인데. (TCP 하당, 유지) 

이는 클라이언트 측에서  수많은 요청을 보낸다는 것으로  서버에 부담을  줄 수 있다. (위에 설명한 바와 같이 요청/응답 시간에 각 객체는 2RTT를 필요로한다.)

 

그러한 대안으로 지속 연결 HTTP가 있다. 

HTTP/1.1 지속 연결에서는 서버 응답을 보낸 후에 TCP 연결을 유지하여

같은 클라이언트와 서버간의 이후 요청과응답은 같은 연결을 통해 보내지게 된다. 이러한 요구는 진행 중인 요구에 대한 응답을 기다리지 않고 연속해서 만들어 질 수 있다(파이프라이닝(piplining)) . 

이러한 연결은 HTTP 서버에서 일정 기간 사용되지 않으면 연결을 끊는 형식을 갖는다. 

 

HTTP의 디폴트 모드는 파이프라이닝을 이용한 지속 연결을 사용한다. (이후에  지속연결, 비지속 연결의 성능을 비교할 것이다.) 

 

 

 


 

 

HTTP 메시지 포맷 

우리가 어떠한 서버로 요청 메시지를 보내고 응답 메시지를 보내는지  포맷에 대해 알아보자 

먼저 HTTP 요청 메시지다. (해당 요청은 5줄이지만 더 많을 수도 있다. )

 

 

HTTP 요청 메시지

 

 

GET / somedir/page.html   HTTP/1.1

HOST : www.someschool.edu  

Connection : close

User-agent : Mozilla/ 5.0

Accept-language: fr 

 

 

해당 요청은 CR(carriage return)과 LF(linf feed)로 구별된다. 

HTTP 요청 메시지의 첫줄은 요청라인(Request Line) 이라하며,

이후의 줄들은 헤더 라인(Header Line)이라고 부른다다. 

 

 

요청 라인은 3개의 필드  method 필드 / URL 필드 / HTTP 버전 필드를 갖는다. 

GET / somedir/page.html   HTTP/1.1

 

헤더라인은 객체가 존재하는 호스트를 명시하고 있다. 

HOST : www.someschool.edu  

 

브라우저는 서버에게 지소 연결 사용을 원하지 않다 말하고 있다. 

Connection : close

 

해당 헤더 라인은 서버에게 요청을 하는 브라우저 타입을 명시하고 있다. 

User-agent : Mozilla/ 5.0

 

해당 헤더는 사용자가 객체의 프랑스어 버전을 원하고 있음을 나타넨다. 

Accept-language: fr 

 

 

위에서 GET 요청을 보면 아래에 다른 entity body가 없음을 확인할 수 있는데 

이는 GET 요청시 서버에 파라미터를 통해 URL 값에 추가하여 확정된 URL경로로 접근하여 원하는 데이터를 갖게 된다 .

ex) naver.com 에다가 추가된 naver.com/stock/tesla?page=1&count=2 같이 볼 수 있다.

 

 POST 요청의 경우 추가적으로 entity body 에 값을 실어 서버에 해당 데이터를 저장해달라고도 요청할 수 있다. 

 

그외에도 DELETE PUT HEAD가 있다.

(GET 데이터 요청<읽고 싶어요> , POST 데이터 등록< 데이터 저장해줘요> DELETE 데이터 삭제< 해당 데이터 삭제해줘요>, PUT 데이터 수정< 해당 데이터 수정해줘요>, HEAD? 잘쓰지 않는다.) 

 

 

 

 

 

요청메시지 포맷을 알아봤으니 다음으로 응답 메시지 포맷에 대해 알아보자

HTTP 응답메시지 

HTTP /1.1  200 OK

Connection : close

Date : Tue, 18 Aug 2015 15:44:04 GMT

Server: Apache/2.2.3  (CentOS)

Last-Modified : Tue, 18 Aug 2015 15:11 03 GMT

Content - Length: 6821

Content-Type : text/ html

 

+++

(데이터 데이터 데이터 데이터 데이터 데이터) 

 

 

 

해당 HTTP 응답메시지는 상태라인, 6개의 헤더라인, 개체 몸체로 이루어져 있다.

 

상태라인은 3개의 필드 버전 필드, 상태 코드, 해당 상태 메시지를 갖는다. 

HTTP /1.1  200 OK

 

클라이언트에게 메시지를 보낸 후 TCP 연결을 닫는데 사용한다. 

Connection : close

 

응답 생성, 보낸 날짜를 나타낸다. 

Date : Tue, 18 Aug 2015 15:44:04 GMT

 

송신되는 객체의 바이트 수를 나타낸다.

Content - Length: 6821

 

개체 몸체 내부의 객체가 HTML 텍스트인 것을 나타낸다.

Content-Type : text/ html

 

 

위에서 상태 라인에 상태 코드는 중요하므로 약간의 예시 번호를 나열하겠다. 

 

200 OK : 요청 성공, 정보가 응답으롤 보내졌다. 

 

301 Moved Permantely : 요청 객체가 영원히 이동되었다. 

 

400 Bad Request : 서버가 이해할 수 없는 요청이라는 오류 코드다. 

 

404 Not Found : 요청 문서가 서버에 존재하지 않는다는 오류 코드다. 

 

505 HTTP version Not Supported: 요청 HTTP 프로토콜 버전을 서버에서 지원하지  않는다는 코드다. 

 

 

 


 

 

사용자와 서버간의 상호작용 : 쿠키 

HTTP 서버는 상태를 유지하고 있기 때문에 수천개의 TCP 연결을 다룰 수 있게 되는데, 접속을 유지할 때 (로그인 유지) 같은 경우는 어떻게 할까?

저기 위에 로그인을 시도했을 때 토큰이라는 데이터를 갖고 있던 것을 기억하는가?  

그 방법을 통해 서버는 사용자를 추적해서 어떤 상태인지를 알 수 있다. 

 

 쿠키 기술은

1 HTTP 응답메시지 쿠키 헤더라인 

2 HTTP 요청 메시지 쿠키 헤더라인

3 사용자 브라우저 내에 쿠키파일

4  웹사이트 백엔드 데이터 베이스 

로 4가지가 있다. 

 

다시금 위에 설명으로 돌아가 네이버에 로그인을 시도해보자 

 

나 ---(로그인 시도)---> 네이버

 

여기서!  네이버 서버가 나라는 클라이언트에게 연결을 인정해주는 토큰 값을 쿠키에 담아준다. 

나 < ------(엉 로그인 됐어 + 토큰) ---- 네이버 

 

그렇게 나라는 클라이언트는 요청 쿠키 헤더라인에 받았던 토큰을 담아 요청을 하게되면

나 ----(나 로그인했으니까 메일 확인좀!! + 토큰) -----> 네이버 

 

서버내에서 해당 쿠키에 토큰값을 해석 혹은  데이터베이스에서 대조 후 로그인을 인정하게 되는 것이다. 

나  <------(토큰 읽어보니 김남김님이시군요? 네 알겠습니다 여기용 ) --- 네이버  

 

 


 

 

 

웹 캐싱

프록시라고 들어봤는가? 무슨 뜻인지 아는가? 

나무 위키에게 물어보자 

Proxy. 대리(행위)나 대리권, 대리 투표, 대리인 등을 뜻한다.

굳이 왜 프록시에 대해 알아야 했냐면 웹에서요청에 대한 응답을 프록시 서버를 통해  캐시처럼 보여줄 것이기 때문이다.

이게 무슨 말인가? 

 

위에 이전 설명에 따르면 클라이언트가 본래 서버로 HTTP 요청을 보냈던 것으로 기억한다. 

그러나 똑같은 요청에 계속해서 똑같은 응답을 보내는데 데이터 베이스에서 값을 가져오고 하면 오버헤드가 심하다. 

 

"내가 이미 보여준걸 또 보여달라고? 잠시만... 하... 데이터 베이스에서 또 가져올게.. 기다려봐..ㅠ"

흠냐.. 일어나서 가져오자.. 읏챠...

 

굳이 똑같은 요청에 계속해서 응답하기위해 똑같은 행동을 서버에서 반복해야할까? 

그렇지 않다. 

 

그래서 client ------ proxy server ------ origin server 식으로 둔다. 

 

프록시 서버에서는 이전 요청에 대한 HTTP 응답값을 기억하고 있어 똑같은 요청이 들어왔을 시 저장된 응답을 다시금 클라이언트에게 전달하게 된다. 

그렇게되면 기점서버 (orgin server)에 가지 않고도 응답을 줄 수 있게된다. ( 덜 움직였으니 더 많은 요청에 orgin server 가 응답할 수 있게된다.)

 

요청이 많이오는 서버에 해당 서버 컴퓨터가 요청량을 받아드리지 못하면 서버 컴퓨터를 증설한다. 

그러나 프록시 서버를 만들어 요청에 대한 응답하는 루틴을 통해 기점 서버가 하는 일이 줄어든다면? 

결과적으로  프록시 서버를 통해 실질적으로 기점서버에 오는 요청이 줄어드니  전체적으로 받아드릴 수 있는 요청의 값이 증가하게된다.

 

++ 

게다가 콘텐츠 전송 네트워크 CDN(Content Distribution Network) 의 사용 증가로 통해 웹 캐시는 인터넷에서 중요한 역할로 자리매김 하고 있다. 

 

 

웹 캐시를 통해 이전에 요청에 대한 응답을 저장할고 있는 것은 알겠다. 그런데 만약 프록시 서버에서 갖고 있는 응답이 최신이 아니라면 ? 

 

조건부 GET 

프로시 서버에서 존재하는 캐시가 항상 새것이 아닐 수도 있다. 그렇기에 HTTP를통해 브라우저에 전달되는 값이 최신 값인지 캐싱해주는 방식을 갖고 있다. 

(HTTP 요청 메시지가 GET 요청을 사용하고  If - Modified -Since 헤더라인을 포함 하고 있다면 그것이 조건부 GET 메시지다 .) 

 

조건부  GET에 대한 응답으로 웹 서버가 여전히 응답 메시지를 보내지만 객체를 포함하지 않을 수도 있다 (캐시가 최신이라면)  하지만 최신의 값이 존재했다면 개체 몸채에 새로운 응답값을 넣어 보낼 수 있게된다. 

 

 


HTTP 버전별 특징 

 

HTTP / 1.1 

HTTP /1.1에서는 TCP 연결이 공정하게 병목 링크로 공유하여 같은 크기의  가용한 대역폭을 공평하게 나누게 해준다. 이러한 방법으로 n 개의 TCP 연결이 병목 링크에서 작동하고 있다면 대역폭의 1/n 개씩 갖게된다.  HTTP/1.1 브라우저들은 6개까지  병렬 TCP 연결을 열 수 있다.

 

 

HTTP/2

HTTP /2 의 주요 목표는 TCP 연결의 수를 줄이는데 있다. 

이는 소켓을 줄일 뿐만 아닌 TCP 혼잡 제어를 가능하게 하게 하겠다는 것인데 오직 하나의 TCP 연결만을 사용하게 될경우 HTTP/2는 HOL블로킹을 막기위해  신중한 메커니즘이 필요하다. 

이러한 메커니즘으로는 HTTP/2 프레이밍,메시지 우선순위화 및 서버 푸싱이 있다.

 - HTTP/2 프레이밍 

    HTTP/2 프레이밍은 각 HTTP 메시지를 독립적인 프레임으로 쪼개고 순서 상관없이(인터리빙) 전송하게한다. 

    이러한 방법은 본래 a뒤에 b가 보일 것을 크기에 따라 a와 b가 같이 보이게하는 현상으로 통해 사용자가 인지하는 지연

     시간을 상당히 줄인다.

 

 - 메시지 우선순위화 및 서버 푸싱

    개발자들이 서버가 요청들을 상대적 우선순위를 조정하게하는 방법이다.

     요청을 병렬적인 데이터 스트림으로 쪼개 가중치를 부여함으로써 이는 처음 요청에 대한 응답 외에도 서버는 클라이언트의 요청

    없이 추가적인 객체를 클라리언트에게 푸시하여

     보낼 수 있게된다. HTTP 요청을 기다리는 대신 서버는 HTML 페이지를 분석할 수도 있으며 해당 객체들에 대한 요청이

    도착하기도 전에 해당 객체들을 클라이언트에게 보낼 수 있게된다. 

 

 

HTTP/3 

다음 3장에서 다룰 QUIC를 통해  HTTP/3는 메시지 멀티플렉싱(인터리빙), 스트리별 흐름제어, 저지연 연결 확립과 같은 여러 특징을 갖고 있다. 그러나 새로운 HTTP ㅍ로토콜로서 현재 인턴ㅅ 드래프트로 나와있으나 완전히 표준화된 상태는 아니다. 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함