HTTP
웹페이지는 HTML 파일, 이미지, Java applet, 오디오 파일과 같은 object 들로 구성되어있다.
이 각각의 오브젝트는 서로 다른 웹 서버에 존재할 수 있다.
웹 페이지는 base html 파일에 서로다른 각가의 오브젝트 URL로 연결시켜 구성한다.
HTTP (HyperText Transfer Protocol) 은 웹 서비스의 어플리케이션 계층 프로토콜이다.
HTTP의 Hypertext는 위에서 말한 오브젝트를 의미한다.
이 프로토콜은 client - server 패러다임을 따른다.
클라이언트는 웹 브라우저로, 웹 서버에 오브젝트를 요청하고, 얻어낸 오브젝트를 사용자에게 보여주는 역할을 한다.
서버는 웹 서버로, 웹 브라우저가 요청한 오브젝트를 HTTP 프로토콜을 사용하여 보내준다.
HTTP는 TCP를 사용하는 프로토콜이다.
사용자에게 보여줄 웹 오브젝트에 대해 조작, 훼손이 일어나서는 안되기 때문이다.
따라서 웹 클라이언트는 80포트에 TCP Connection을 생성하고, 서버는 TCP Connection을 받아 연결을 수락한다.
이후에는 이 연결을 기반으로 HTTP Message를 주고받고, 데이터를 주고받은 뒤 TCP Connection을 닫는다.
이때 HTTP에 대해 한가지 중요한 특성이 있는데, 바로 HTTP는 상태가 없다는 것이다. (stateless)
상태가 없다는 말은 서버가 과거 클라이언트에 대한 정보를 기억하고 있지 않다는 뜻이다.
똑같은 클라이언트가 똑같은 데이터를 요청해도, 내가 이 클라이언트에게 이 데이터를 보낸적이 있다는 것을 기억하지 않고, 새로운 클라이언트에게 새로운 데이터를 주는 것과 같이 행동한다.
이렇게 HTTP를 설계한 이유는 바로 성능때문이다.
과거의 상태를 모두 기억하려면, 과거의 상태를 저장하고, 이를 조회하는 기능이 필요하기 때문이다.
HTTP Connections
Non-persistent HTTP
한 클라이언트와 데이터를 주고 받을 때, 한번 들어온 요청에 대해 응답을 보내면 바로 TCP 연결을 종료하는 방식이다.
TCP Connection Open → 최대 1개 오브젝트 전송 → TCP 연결 종료
따라서 웹페이지 하나를 보여주는데 5개의 오브젝트가 필요하다면, 5번의 TCP 연결을 만들고 끊는 과정을 반복해야한다.
과거의 HTTP는 이렇게 설계가 되어있었다. (HTTP/1)
HTTP Response Time
HTTP Response Time을 이야기하기 위해서 RTT (Round Trip Time, 왕복시간) 개념이 필요하다.
RTT의 정의는 하나의 작은 패킷이 클라이언트와 서버를 왔다갔다하는데 걸리는 시간이다.
이 왕복하는 총 시간은 결국 클라이언트 입장에서 내가 보낸 요청에 대해 응답을 받을 때까지 걸리는 시간을 의미한다.
HTTP response time 은 이 RTT를 기반으로 생각할 수 있다.
처음 TCP 연결을 만들 때, 패킷이 한번 왔다가고, (RTT +1),
필요한 데이터를 요청하고 받으면서 한번 더 패킷이 왕복한다. (RTT + 1)
이때 필요한 데이터의 크기가 크다면, 그 데이터를 전송하는데 transmission delay 시간이 추가적으로 필요하다.
따라서 Non-Persistent HTTP response Time 은 아래와 같이 정의된다.
2 * RTT + file transmission time
이 시간이 하나의 오브젝트를 얻는데 걸리는 시간이므로, 5개의 오브젝트를 받으려면 전체 오브젝트를 얻는데 걸리는 시간은 이 시간의 5배이다.
Persistent HTTP
이 방식은 한번 TCP 연결을 만든 뒤, 그 연결을 통해서 필요한 여러개 오브젝트를 모두 주고받는다.
이후에 연결을 종료하는 방식이 Persistent HTTP 방식이다.
현재는 모든 브라우저가 당연히 이 방식을 사용하고 있다.
Persistent HTTP는 HTTP 1.1 버전부터 등장했다.
Non-Persistent HTTP는 오브젝트마다 2RTT의 시간이 필요하고, 각 TCP 연결을 만드는데 운영체제에 오버헤드가 발생하는 문제가 있다. (버퍼 설정, 상태 컴퓨터와 세그먼트 시작 번호에 대한 합의 등)
따라서 보통 여러개의 오브젝트를 필요로하는 브라우저는 여러개의 TCP 연결을 병렬로 만들어 전체 오브젝트를 얻는 시간을 줄이고자 하였다.
Persistent HTTP 는 데이터 요청에 대해 응답을 보낸 뒤, 연결을 끊지 않고 유지한다.
그리고 처음 응답받은 데이터에서 referenced object가 필요하다면, 즉각적으로 추가적인 요청을 보내고 데이터를 얻는다.
따라서 링크된 오브젝트를 얻는데는 RTT + file transmission time 의 시간만 필요하다. (데이터를 응답하는 시간이 반으로 줄어든다.)
(하나의 Connection 으로 어떤 데이터든 상관없이 여러번 데이터를 주고받는 것이 아니라,
하나의 연결에서 한번 데이터를 받았을 때, 그 데이터에 딸린 (연결된) 데이터들까지 한번에 받아오는 것까지가 HTTP/1.1 에서 개선한 점이다.)
HTTP Request Mesasge
이제 HTTP로 데이터를 요청하고, 받을 때 구체적으로 어떤 format의 데이터를 주고받는지 정리해보자.
HTTP Message는 request, response 2가지 타입이 있다.
그리고 각각의 메세지는 아스키코드로 구성되어 사람이 읽을 수 있는 형태로 되어있다.
HTTP request message는 위와 같은 구조로 되어있다.
첫번째 줄에는 request method, request url, http version 정보가 들어간다.
이 줄을 request line 이라고 한다.
그 다음에는 header line 들이 나온다.
어떤 컴퓨터에서 보낸 요청인지 요청을 보낸 컴퓨터 host 정보
요청을 보낸 브라우저, 컴퓨터 정보가 들어있는 User-Agent 정보
어떤 종류의 데이터를 받으려고 하는지 Accept 정보
어떤 언어로 데이터를 받고 싶은지 Accept-Language 정보
어떤 인코딩으로 데이터를 받고 싶은지 Accept-Encoding 정보
HTTP 1.1 을 사용하여 데이터를 받으므로, Connection 이 유지가 되어야 한다.
따라서 Connection 정보는 keep-alive로 요청을 보낸다.
헤더 정보 이후에는 한 줄을 추가적으로 띄워야 해서 마지막에 \r\n 이 한번 더 들어간다.
이후 내용은 HTTP body 가 들어가는데, POST 요청을 보내는 경우, request body에 데이터를 실어보내기도 한다.
정리하면 위와 같은 형태이다.
HTTP Request Method
POST
유저의 input 데이터를 받는 폼을 만들고, 폼에 적인 데이터를 서버에 전송할 때 자주 사용한다.
Request body 에 유저가 보낼 데이터를 담아서 보낸다.
GET
보통 서버에 데이터를 요청하여 얻어올 때 사용한다.
쿼리 메소드를 사용하여 서버에 데이터를 보낼 수도 있다.
URL?key=value&key=value 형식으로 데이터를 보낼 수 있다.
HEAD
GET 메서드와 유사하지만, 용도는 개발시 테스트를 하는 용도로 사용한다.
GET과 달리 서버가 요청에 대해 데이터를 보내주는 것이 아니라 header만 보내준다.
PUT
POST와 유사하게 데이터를 서버에 보내서 데이터를 생성하는데 사용한다.
차이점은 PUT은 서버에 있는 기존 데이터를 완전히 바꿔치기 하고 싶을 때 사용한다.
POST는 기존 데이터와 똑같은 데이터를 보내면 똑같은 데이터를 추가로 생성하는 차이점이 있다.
HTTP response message
이번엔 요청에 대해 응답을 받을 때 서버가 보내는 메세지 구조를 살펴보자.
첫번째 줄은 status line 이다.
HTTP 버전, status code, status phrase 정보가 들어간다.
header lines 는 request 와 비슷하게 여러 줄로 구성되어있다.
주요 내용은 아래와 같다.
Date: 웹 서버가 데이터를 보낸 시각
Server : 웹 서버 정보, 데이터를 보낼 때 사용한 암호화 툴 정보
Last-Modified: 내가 요구한 오브젝트가 마지막으로 갱신된 시각
이후에는 똑같이 한 줄을 띄우고, 서버가 보낼 데이터가 들어간다.
html 데이터면 html 소스코드가 쭉 들어가는 식이다.
response status code
200 : OK (request success)
301 : Moved Permanently (요청한 데이터가 다른 곳에 존재하고 있어서 해당 위치로 가라는 Location 정보를 헤더에 담아 응답해준다.)
400 : Bad Request ( 클라이언트가 보낸 request message를 해석할 수 없을 때 발생하는 에러이다.)
404 : Not Found ( 요청한 데이터가 존재하지 않을 때 발생한다.)
505 : HTTP version Not Supported ( 요청을 보낸 HTTP 버전이 웹서버에서는 지원하지 않는 HTTP 버전일 때 발생한다.)
브라우저없이 HTTP 요청 보내기
netcat 프로그램을 사용하여 웹 서버에 요청을 보내고 response를 확인할 수 있다.
터미널에서 nc -c -v domain port 를 입력하여 TCP 연결을 만든다.
이후에 HTTP Request 메세지를 직접 입력하여 요청을 보낼 수 있다.
또는 와이어샤크를 이용해서 패킷에 담긴 HTTP 메세지를 캡쳐해 읽어볼 수도 있다.
Cookie
HTTP는 기본적으로 stateless 로 설계가 된 프로토콜이다.
즉, 클라이언트의 상태를 서버에 저장하지 않는다.
이는 서버의 성능을 높일 수 있는 장점이 있지만, 상황에 따라 불편한 점이 있기도 하다.
그래서 이를 해결하기 위해 쿠키라는 기술이 등장했다.
쿠키는 크기가 작은 랜덤한 빅 시퀀스의 파일로, 클라이언트의 state 를 저장하고 있는 데이터로, HTTP 라는 stateless 프로토콜에 state 를 부여한다.
매 HTTP 요청을 보낼 때 쿠키를 함께 보냄으로써 클라이언트의 상태를 저장하고 서버가 알 수 있게 한다.
이를 통해 웹 트랜잭션 사이에 상태를 유지할 수 있도록 할 수 있다.
stateful protocol
만약 어떤 프로토콜이 상태를 저장하는 프로토콜이라고 해보자.
그렇다면 서버는 데이터베이스에 x라는 값을 유지하고 기억하고 있을 것이다.
클라이언트가 서버의 x라는 값을 바꾸기를 원해서 요청을 보낸다고 하자.
근데 이 x라는 값을 바꾸기를 원하는 클라이언트가 하나가 아닐 수도 있다.
이때 동시성 문제가 발생할 수 있어서, x라는 값을 바꿀 때는 하나의 클라이언트만 접근이 가능하도록 누군가 접근했다면 먼저 수정할 수 없게 lock을 걸어두고 값을 다 바꾸면 그 때 lock을 푸는 식으로 동작해야 한다.
그런데 만약 lock을 걸어두고 값을 수정하고 있었는데, 그 때 서버 컴퓨터가 갑자기 다운되었다고 해보자.
아직 lock 을 풀지 못했기 때문에 서버는 이 값을 lock을 걸기 전 시점으로 다시 되돌릴 수 밖에 없다.
중간밖에 수정하지 않은 값을 그대로 저장할 수는 없기 때문이다.
이런 문제가 발생하면 클라이언트 입장에서는 분명 내가 값을 변경하도록 했음에도 서버에는 이전값이 저장되어있는 현상이 발생하고, 이를 해결하려면 복잡한 방법이 필요하다.
그래서 HTTP는 stateless 프로토콜을 사용하고 있다.
Cookie's components
쿠키를 활용할 때 아래 4가지 컴포넌트가 필요하다.
1. 처음에는 서버가 response 메세지에 쿠키 헤더를 실어서 응답을 보낸다.
따라서 서버가 처음 쿠키 값을 세팅하여 클라이언트로 보낸다.
서버는 클라이언트 (웹 브라우저) 마다 따로따로 쿠키를 부여한다.
2. 클라이언트는 받은 쿠키 값을 갖고 있다가, 서버에 요청을 보낼 때 그 쿠키 헤더를 같이 보낸다.
서버는 이 값을 보고 이 클라이언트가 언제 우리 사이트에 왔었는지 알 수 있다.
따라서 쿠키 값은 클라이언트와 서버 모두에 저장해야 한다.
3. 쿠키 값은 클라이언트의 브라우저 프로그램에 파일로 저장된다.
4. 쿠키 값은 웹 사이트 서버의 백엔드 데이터베이스에 저장된다.
더 자세하게 과정을 정리하면
최초 접근시 쿠키를 생성하여 DB에 값을 저장하는 동시에 클라이언트에도 쿠키를 세팅하도록 set-cookie 헤더를 보낸다.
클라이언트는 이후에 요청을 보낼 때 세팅된 쿠키를 같이 보낸다.
서버는 해당 쿠키를 보고 DB에 접근해서 데이터를 읽고 쓴다.
일주일 뒤 다시 같은 클라이언트가 접근하면, 여전히 같은 쿠키를 같이 보내므로, 해당 쿠키를 통해 DB에 접근해서 값을 읽고 쓸 수 있다.
쿠키의 활용
1. 인증 (authorization)
쿠키는 위험할 수 있으나 인증 목적으로 사용할 수 있다.
쿠키에 어떤 특정한 값이 있다면, 그 값을 요청보낼 때 같이 보내기만 하면 그 클라이언트를 특정 유저로 인증하는 방식이다.
하지만 그 브라우저를 이용하는 사람이 실제로 누구인지 알 수 없기 때문에 이 방식은 굉장히 위험하다.
2. 개인화 (recommendations, 추천)
클라이언트가 어떤 상품에 관심이 있는지 쿠키값에 저장해서, 관심 상품을 추천하거나, 관련 홍보 메일을 보내는 데 사용할 수 있다.
3. 세션 (user session state)
인증과 비슷하게 자신의 메일함에 들어가서 메일을 읽고, 지우는 행위를 한다고 할 때, 이를 세션을 이용해서 이 유저가 한 행동이라고 확인할 수 있다.
쿠키는 웹 사이트가 그 사이트에 접속한 사람에 대한 정보를 수집하는 걸 도와주는 도구이다.
그리고 웹 사이트를 방문하다보면 자신의 의도와 상관없이 서드파티 쿠키를 저장하게 되기도 한다.
따라서 쿠키는 보안, 프라이버시에 문제가 있다.
쿠키와 광고
뉴욕타임즈 웹사이트에 접속을 한다고 해보자.
처음엔 GET 메서드로 HTML을 가져올 것이다.
그런데 가져온 HTML에 광고 영역이 있었다.
그리고 그 광고는 AdX 라는 사이트에서 제공하고 있다.
그러면 이 광고 이미지를 얻기 위해, 브라우저는 AdX.com 에 추가적으로 요청을 보내 광고 이미지를 얻어온다.
따라서 최종 접속한 웹사이트에서 뉴욕 타임즈의 뉴스 기사와 함께 AdX.com이 제공하는 광고를 같이 보게 된다.
여기에 쿠키가 관여하면 유저에게 맞춤 광고를 보여줄 수 있다.
먼저 처음 뉴욕타임즈에 방문하면서 GET 요청을 보낼 때, 서버가 해당 유저에게 쿠키를 부여한다고 하자.
이렇게 최초로 부여받은 쿠키를 "first party cookie" 라고 한다.
이 쿠키는 의도적으로 방문한 웹 사이트에 의해 부여되는 쿠키이다.
그리고 다시 광고 이미지를 얻어오기 위해 AdX.com 에 추가적인 요청을 보낸다.
이때 AdX.com 도 브라우저에 쿠키를 설정한다.
이 쿠키는 유저가 의도하고 방문하지 않은 AdX.com 라는 사이트에 의해 설정된 쿠키이다.
이런 쿠키를 third-party cookie 라고 한다.
이 상황에서 이번엔 뉴욕타임즈가 아니라 양말을 사기 위해 socks.com 이라는 사이트에 들어갔다고 해보자.
그런데 이 사이트에서도 AdX.com 의 광고를 달고 있는 것이다.
그러면 이때도 브라우저는 자연스럽게 Socks.com 으로 HTTP 요청을 보낼 뿐 아니라 AdX.com으로도 요청을 보내게 되고, 이때 AdX.com 은 한번 방문했던 사용자가 또 자신에게 광고 데이터를 요청했음을 알 수 있게 된다.
이를 서버에 모두 저장하면 AdX.com 은 유저가 자신의 광고가 달린 사이트 중 어떤 사이트에 접속했는지를 알 수 있고, 이 정보를 토대로 사용자의 관심사에 맞는 광고를 제공하게 된다.
이를 도식화한 이미지가 위와 같다.
그래서 first party cookie 는 유저가 설정되는 것을 인식할 수 있지만 third party cookie는 유저가 자신도 모르게 설정되기 때문에 이슈가 제기되었다.
그래서 third party cookie는 파이어폭스나 사파리같은 브라우저에서 기본적으로 막고 있다.
이런 문제에 의해 EU가 쿠키를 개인 정보로 간주하고 사용자에게 고지를 해야한다는 법을 제정했다.
GDPR (General Data Protection Regulation) 이라는 규정이다.
따라서 어떤 웹사이트에 방문했을 때 사용자는 쿠키를 수락하지 않을지, first cookie만 수락할 지, third party cookie 까지 수락할지 선택할 수 있다.
'CS > 컴퓨터 네트워크' 카테고리의 다른 글
[컴퓨터 네트워크] 11. Application Layer (4) : HTTP/2 (0) | 2024.04.16 |
---|---|
[컴퓨터 네트워크] 10. Application Layer (3) : Web Cache (0) | 2024.04.16 |
[컴퓨터 네트워크] 8. Application Layer (1) : 어플리케이션 계층 개요 (0) | 2024.04.11 |
[컴퓨터 네트워크] 7. Protocol layers (0) | 2024.04.10 |
[컴퓨터 네트워크] 6. Security (0) | 2024.04.08 |