ⓐ HTTP ( HyperText Transfer Protocol )
웹페이지는 Object들로 구성되어있으며, 그 Object들은 다른 Web Server에 저장된다.
(여기서 Object는 HTML, JPEG, Audio File 등을 의미한다.)
웹페이지는 기본적으로 HTML파일이며, 주소는 host/path의 형식이다.
Client는 브라우저를 통해 서버에 HTTP Request를 보내고, 서버는 이에 대한 Response를 보낸다.
이 때, HTTP는 TCP 연결을 사용하며, Port 80을 이용한다.
최초의 HTTP는 Non-Persistent, 비-지속 연결만 사용했다.
그러나 비-지속 연결은 모든 오브젝트에 각각의 새로운 TCP Connect를 필요로 했기 때문에,
TCP 연결 생성의 Overhead와 한 오브젝트당 2RTT가 소요되는 점 때문에 새로운 연결방법이 필요했다.
(RTT란 Round Trip Time의 약어로 서버와 클라이언트간의 왕복에 걸리는 시간을 의미한다.)
HTTP 1.1에서 생겨난것이 Persistent, 지속 연결이다.
지속 연결에서 HTTP는 클라이언트와 서버가 연결을 끊기 전까지 데이터를 송수신한다.
그렇기 때문에 기존의 Non-Persistent 연결과 달리 하나의 TCP 연결로 통신하게 된다.
HTTP Request Message는 크게 Request Line과 Header Line, Body으로 나눌 수 있는데,
그 내용은 다음과 같다.
[Request Line]
- Method : GET, POST와 같은 Request방식이다.
- URL : path이다. 예를들어 aaa.com/test.txt에서 /test.txt이다.
- Version : HTTP의 버전이다.
[Header Line]
- Host : 접속한 주소, aaa.com/test.txt에서 aaa.com이다.
- User-Agent : 유저가 접속한 정보이다. Mozilla/5.0과 같은 것이다.
- Accept : 어떤 타입의 정보인지이다. text/html, application/json 등..
- Accept-Language : 유저의 언어이다.
- Accept-Encoding : 인코딩 타입이다.
- Connection : 비지속연결(close)인지 지속연결(keep-alive)인지이다.
HeaderLine에는 사용자의 정보를 담음으로써, 이 정보를 수신한 서버가 사용자 맞춤형으로 작동할 수 있게 해준다.
HTTP Request Method는 주로 POST, GET, HEAD, PUT이다.
- POST : form 등의 User input을 body에 담아서 그대로 Request하는 방식이다.
- GET : 유저 데이터를 URL에 담는 방식으로 ? 뒤에 적힌다.
- HEAD : Body없이 Header만 요청하는 메소드이다.
- PUT : POST와 유사하지만 한 번을보내도, 여러번을 보내도 똑같은 결과를 낸다. (이를 멱등성이라고 한다.)
위의 내용은 HTTP Request. 즉, 클라이언트가 서버한테 요청하는 내용이다.
그렇다면 서버가 클라이언트에게 응답하는 HTTP Response는 어떠한 구조일까?
HTTP Response는 Status Line와 Header Line으로 나뉜다.
[Status Line]
- Version : HTTP의 버전이다.
- Status Code : 요청의 결과를 나타내는것으로, 200 OK, 404 Not Found 등을 의미한다.
[Header Line]
- Date : 응답을 보낸 시간
- Server : 웹서버의 종류
- Last-Modified : 마지막으로 수정된 시간
그 외에도 ETag, Accept-Ranges, Content-Length, Content-Type 등이 있다.
기본적으로 통신에는 RTT가 소요된다고 했다.
이 RTT는 클라이언트와 서버간의 물리적 거리나 네트워크의 상태 등의 요인으로 변화하게 된다.
이런 RTT를 줄이기 위해 사용되는것이 Web Cache (a.k.a Proxy Server)다.
웹 캐시는 주로 유저들의 지역에 설치되며,
유저들이 요청하는 정보를 메인 서버에서 가져와 캐시에 보관한다.
그렇다면 다음 요청부터는 더 긴 RTT가 소요되는 Origin Server가 아니라 Web Cache에서 응답하므로 빨라지게 된다.
또한, 총 트래픽량도 줄일 수 있게 된다.
예시를 들어보자.
클라이언트 집단 A와 서버 B가 있다고 하고, A와 B의 거리가 멀어서 RTT는 2초라고 한다.
A가 요청하는 각 오브젝트는 100Kb이고, 1초에 15번씩 요청을 한다.
A와 B사이의 Access link의 용량은 1.54Mbps라고 둔다.
이 때, Access link utilization(사용량)은 (100Kb * 15) / 1.54Mbps로 = 0.97이다.
링크의 97%를 사용하고 있다는 뜻이고, 이는 Queueing Delay가 길어짐을 의미한다.
그렇다면 이를 해결하기 위한 방법은 어떤게 있을까?
먼저 Access link의 용량을 늘리는 방법이다.
1.54Mbps이기 때문에 0.97이면 154Mbps로 늘리면 0.0097일 것이다.
그러나 높은 트래픽을 감당할 수 있을수록 더 비싸고, 거리도 멀기 때문에 더 비쌀것이다.
즉, 경제적으로 합리적이지 못한 선택이 될 수 있다.
그러므로 두번째 해결방안인 웹 캐시다.
요청한 데이터가 캐시에 있다면 본 서버까지 가지 않고도 응답을 받을 수 있다.
그렇다면 캐시 히트율에 따라 Access link utilization도 줄어들 것이고, 이를 통해 end to end delay도 줄어든다.
또한, 웹 캐시는 링크 증축보다 훨씬 저렴하다고 하므로 좋은 선택일 것이다.
다음으로, HTTP는 Stateless한 프로토콜이다.
이게 무슨 의미인가 하면, 정보를 저장하지 않는다고 생각하면 편하다.
그래서 내가 접속한 기록이 있던 없던, 접속한 사람이 누구던 같은 데이터가 표시된다.
그러나 웹을 개발하다보면 Interactive한 기능들이 필요할 때가 있다.
이를 위해 Cookie라는것이 존재한다.
이 쿠키를 유지하기 위해서는
HTTP Request,HTTP Response에 Cookie header line을 넣고,
유저 브라우저(Client)와 백엔드 DB(Server)에 저장되어야 한다.
예를 들어, A가 사이트 B에 접속하면 서버에서는 A의 UUID를 생성하고 DB에 보관하며 Response에 담아서 보낸다.
그러면 A의 브라우저도 사이트 B의 쿠키를 저장하며, 다음부터 B에 요청보낼 때 쿠키 정보를 담아서 보낸다.
이런 쿠키는 주로 장바구니나 세션정보 저장 등에 사용된다.
또한, 쿠키는 사용자 정보를 담으므로 회사들은 서로 쿠키를 공유하기도한다.
다음으로 HTTP 버전이다.
앞에서 HTTP/1.1을 예시로 들었었는데, 이번엔 업데이트된 HTTP/2이다.
HTTP/1.1에서는 지속 연결을 도입하여 단일 TCP로 여러 오브젝트를 통신할 수 있게 되었다.
그러나 FCFS로 작동하기 때문에 앞의 오브젝트가 크면 뒤의 오브젝트는 크기와 상관없이 딜레이될 수 있다.
이런 현상을 Head-Of-Line Blocking이라고 한다.
이런 HOL Blocking 등을 완화하기 위하여 HTTP/2 에서는 increase flexibility에 중점을 두었다.
요청 방식이나 상태 코드 등 대부분의 헤더필드는 HTTP/1.1과 차이가 없다.
그러나 클라이언트가 지정하는 우선순위에 따라 FCFS가 아닌 방식으로 응답이 작동할 수 있고,
클라이언트가 요청하지 않은 오브젝트를 push할 수 있으며,
큰 개체를 분할하여 스케쥴해 HOL blocking을 완화하는 기능이 추가되었다.
그리고 최근에 HTTP/3이 표준화되었는데,
HTTP/2와의 차이점은 기존에 기본 TCP 연결 수준의 보안을 좀 더 강화하였으며,
UDP 기반의 오브젝트 에러나 혼잡제어 등이 추가되었다고 한다.
ⓑ E-MAIL ( 전자 우편 )
이메일은 우리에게 친숙하지만 그렇게 친숙하지는 않다.
굉장히 많은 정보가 이메일로 오지만, 실제로 그 이메일을 읽는 사람들은 얼마 되지 않으니..
내 메일함만 봐도 트위치 방송알람이나 광고, 결제 정보 등으로 도배가 되어있고
메일은 삭제만 해봤지 읽는건 별로 해본적이 없다. 아무튼...
메일을 구성하는 주요 3가지 컴포넌트는 다음과 같다.
User-Agent (a.k.a MailReader), 메일박스를 가진 사용자이다.
Mail-Server, 사용자마다 메일박스를 할당하고, 메일을 보내는 서버이다.
SMTP, 이메일을 보내기 위해 사용되는 프로토콜이고, 신뢰성을 위해 TCP를 통해 전송한다. 포트넘버는 25
SMTP 전송 프로토콜은 다음과 같다. (자세한 내용은 RFC 5321)
1. SMTP를 사용하는 클라이언트와 서버가 TCP Connection을 만든다.
2. Handshaking을 통해 연결을 확인한다. ( Status 220, 250 )
3. 메세지를 작성하고 전송한다. (EOM은 CRLF.CRLF)
4. TCP 연결을 종료한다.
SMTP와 HTTP의 차이점은
HTTP는 Client pull, 클라이언트가 요청을 보내는 것이고, 한 Response에 한 Object만 담긴다.
SMTP는 Client push, 프로토콜이 클라이언트에게 자신의 존재를 알리고, 메세지에 여러 오브젝트가 담겨 전송된다.
RFC 2822에서는 이메일 메세지 문법에 대한 표준이 있는데,
HeaderLine에는 To, From, Subject가 들어가고,
Body에는 ASCII Character로 구성된 Message가 들어가게 된다.
메일과 관련된 프로토콜로는
POP (Post Office Protocol) : 권한 부여, 다운로드, 다른 클라이언트에서 메일 읽기 불가능, Stateless
IMAP (Internet Mail Access Protocol) : 메세지 저장에 관한 기능이 더 추가된 프로토콜 (제목만 보여주기 등)
HTTP : Gmail, Yahoo Mail과 같이 웹 서버 위에서 동작하는 메일
이 있다.
ⓒ DNS ( Domain Name System )
인터넷 호스트들은 자신을 나타내기 위해 IP Address를 갖는다.
일반적으로 우리가 아는 IPv4는 32bit 숫자로 이뤄진 127.0.0.1와 같은 형태이다.
하지만 이런 형태는 사람들이 인지하기 어려우므로 google.com와 같은 이름을 사용하고 이를 DNS라고 한다..
그러나 데이터를 전송하기 위해서는 이런 이름이 아니라 실제 IP가 필요하고,
이름을 통해 IP를 알아내기 위해 DNS Server가 존재한다.
DNS Server는 Name을 IP로 번역하거나, Host/MailServer의 Aliasing 등의 일을 한다.
인터넷 사용자의 99.9%는 DNS를 통해 사이트에 접속하므로, DNS Server는 엄청난 양의 트래픽을 다룬다.
그렇다보니 부하 분산을 위해 여러 곳으로 나누게 되었다.
물론 그런 이유가 아니라도 중앙화시켜두면 한 DNS Server의 마비로 대참사가 날 수 있으므로 중앙화는 안된다.
DNS Server는 Root, TLD, Authoritative의 계층구조로 이루어져있다.
쉽게 알아보기 위해 아래부터 알아보자.
Authoritative 계층은 각 기관의 DNS Server라고 생각하면 편하다.
google.com, naver.com, amazon.com의 DNS를 관리하는 각각의 서버가 있다.
TLD 계층은 Top Level Domain의 약어로 .com, .org, .edu를 관리하는 DNS Server이다.
그렇다면 당연하게도 Root 계층은 TLD를 관리하는 DNS Server가 되겠다.
이런 계층 구조의 DNS구조와 별개인 Local DNS도 존재한다.
각 ISP가 가지고있는 DNS로, 사용자들은 가장 먼저 Local DNS에 접근한다.
Local DNS에서 찾지 못하면 Root, TLD, Authoritative를 거쳐 IP를 찾게된다.
이런 Local DNS는 DNS Cache의 역할도 하게 되는데, 일정시간이 지나면 지우게 된다.
그 이유는, 캐시에 저장된 동안 DNS에 변경이 발생하여 Out-of-date가 일어날 수 있기 때문이다.
DNS Server Querying은 두 가지 종류가 있는데
첫번째로 순차쿼리
root, TLD, Authoritative는 각각 요청에 대해 응답하고,
클라이언트는 각 응답에 대해 하위 계층으로 새로운 요청을 보낸다.
두번째로 재귀쿼리
Root는 자신이 받은 요청을 TLD로 보내고 TLD는 Authoritative로 보낸다.
Authroritative의 응답은 TLD와 Root를 거쳐 클라이언트에게 오게된다.
DNS Record도 여러종류로받을 수 있고, 4개만 설명해보면
A(Host) : 도메인이름과 IPv4를 준다.
CNAME(Canonical Name) : DNS상 실제 주소를 반환한다.
NS(NameServer) : 네임서버 목록을 반환한다.
MX(MailExchanger) : SMTP 메일서버를 반환한다.
DNS Protocol의 헤더는
Identification, Flags, Questions, Answers, Autorirty Records, Additional Info
로 이루어져 있다.
DNS 서버에 대한 주요 공격방식은
DDos Attack ( 트래픽 과부하를 유도하는 공격방식 )
Spoofing ( DNS쿼리를 가로채 수정해서 다시보내는 방식 )
이 있다.
ⓓ P2P ( Peer-to-Peer )
Client-Server방식과 달리 Server가 항상 켜져있지 않고, 클라이언트끼리 수평관계를 유지하는 방식이다.
각 클라이언트는 Peer로 불리고, 각 Peer는 서비스를 요청하면서 제공하는 주체이다.
그렇기 때문에 P2P방식은 Self-Scalability하다.
( Client-Server는 사용자수가 늘어나면 Server가 허용한계를 늘려야한다.
P2P는 사용자수가 늘어나면 허용한계도 같이 늘어난다. )
또한, C-S에서 Server는 고정 IP를 가지는 경우가 많지만, P2P의 각 Peer들은 그렇지 않다.
파일 전송을 예시로 C-S와 P2P의 차이점을 알아보자.
먼저, 한 서버에서 네트워크로 전송가능한 최대 업로드 속도는 Us다.
각 클라이언트들은 각자 Di의 속도로 다운받을 수 있고, 이 중 가장 느린 속도는 Dmin이다.
각 클라이언트의 업로드 속도의 경우 Ui, Umin이다.
그리고 전송할 파일의 크기는 F라고 하자.
C-S에서는 서버가 N개의 클라이언트에게 파일을 전송하기 위해 최소 N*F / Us의 시간이 필요하다.
클라이언트는 각자의 다운로드 속도에 따라 F/Di의 시간이 걸리고, 최대 F/Dmin의 시간이 걸린다.
이 때, C-S 구조에서 파일 전송에 걸릴 수 있는 최소 시간은 Max(NF/Us, F/Dmin)이다.
이 시간은 N의 크기에 선형관계를 갖는다.
P2P에서는 서버가 네트워크에만 파일을 올리면 되므로 최소 F/Us의 시간이 걸린다.
클라이언트는 각자 다운로드 속도에 따라 F/Di의 시간이 걸리고, 최대 F/Dmin의 시간이 걸린다.
그러나 각 클라이언트들은 다운로드하면서 파일을 업로드하기도 하므로, 최대 NF/(Us+Sigma(Ui)) 시간이 걸린다.
즉, P2P 구조에서 파일전송에 걸릴 수 있는 최소 시간은 Max(F/Us, F/Dmin, NF/(Us+Sigma(Ui)))이다.
N에 선형적이지만, N의 증가에따라 Sigma(Ui)도 같이 증가하므로 C-S만큼 증가량이 크지는 않다.
이러한 P2P를 사용하는 대표적인 예시는 BitTorrent다.
Torrent는 파일을 교환하는 피어들의 그룹이고, Tracker를 통해 토렌트의 피어를 추적할 수 있다.
피어들은 파일의 청크를 주고받고, 이렇게 주고 받는 관계를 Neighbors라고 한다.
그리고 일반적인 피어는 자신이 파일을 모두 다운받으면 떠나게 되는데 이를 Chern이라고 한다.
토렌트 환경에서 각 피어들은 주기적으로 다른 피어들에게 어떤 청크를 가지고 있는지 질의하고, 가장 희귀한 청크부터 먼저 다운로드한다. 이를 통해 토렌트 환경에서 청크가 유실되는 일이 최소한으로 되게 해준다.
각 피어가 청크를 다른 피어에게 보내줄 때에는 모든 피어에게 보낼 수 없으니 4개의 피어만 선택해서 보내주게 된다.
이 4개의 피어는 자신에게 가장 많이 보내준 피어들을 선정하며, 이 4개의 피어는 10초마다 재선정된다.
그러므로 업로드 속도가 빠를 수록 다운로드에도 유리해진다.
또한, 매 30초마다 랜덤으로 피어가 선택되는데 이를 Optimistically Unchoke라고 한다.
이것을 통해 청크가 없거나 적은 피어도 파일을 다운받을 수 있게 된다.
물론 운이 안좋으면...
최초의 P2P는 P2P지만 중앙화된 Directory Server를 가지고 있었다.
이 중앙서버는 각 피어의 주소와 가지고 있는 청크의 목록을 저장하는 역할이었으며, 각 피어는 Directory Server를 통해 자신이 필요한 청크를 다운받을 수 있는 피어를 찾게 된다.
그러나, 이 중앙 서버가 사라지면 P2P네트워크가 붕괴할 수 있고, 공유되는 파일이 불법파일이거나 하면, 중앙서버가 위치한 곳이 비 관계자더라도 법적책임을 받게되는 일이 생기게 된다.
이에 대한 대안은 Query flooding이다.
각 피어는 다른 피어들에게 내가 필요한 청크를 가지고 있냐고 Query를 보낸다. 만약 가지고 있다면 Query Hit이 돌아오고 청크를 받을 수 있게 된다.
그러나 이는 P2P 네트워크가 커질수록 쿼리의 양도 기하급수적으로 많아지므로 대규모 네트워크엔 적합하지 못했다.
그래서 생긴 새로운 대안은 Hierarchical Overlay로, 피어들을 그룹화하여 계층화하는 구조이다.
각 피어는 슈퍼노드이거나 슈퍼노드에 소속되어있다.
소속된 피어들은 슈퍼노드와 TCP 연결을 하고, 슈퍼노드는 슈퍼노드끼리 TCP연결을 한다.
슈퍼노드는 소속된 피어들이 가진 청크정보를 모두 가지고 있으므로, 슈퍼노드끼리의 통신만으로 Query가 된다.
이런 방식을 가지고 있는 대표적인 프로그램이 Skype다.
Skype를 이용하는 클라이언트들은 슈퍼노드와 연결되어있고, 슈퍼노드에는 소속된 유저의 이름과 IP등이 저장된다.
그리고 클라이언트는 슈퍼노드와 릴레이를 구현하는데, 이는 일반적으로 공유기등으로 인해 유저간 직접연결이 막히므로 슈퍼노드를 통해 통신하기 위함이다.
ⓔ 소켓 프로그래밍
소켓이란 UNIX의 BSD4.1에서 소개된 기능으로 다른 응용 프로세스와 통신하기위해 응용계층에서 만들어지고 OS가 관리할 수 있는 인터페이스이다.
소켓은 응용계층과 end-to-end transport protocol 사이의 문같은 역할을 한다.
먼저 TCP로 동작하는 소켓(SOCK_STREAM)이다.
서버는 반드시 실행중이여야 하며, 클라이언트의 연결을 받기위한 소켓을 열어둔다.
클라이언트는 TCP 소켓을 만들어 서버의 IP, Port를 입력해 연결한다.
서버는 클라이언트의 연결 요청이 오면 전용 TCP 소켓을 새로 만들어 연결한다.
다음으로, UDP로 동작하는 소켓(SOCK_DGRAM)이다.
Client-Server간의 연결이 없고, 당연히 HandShaking도 없다.
그렇기 때문에 TCP와 달리 데이터 전송에서 각 데이터마다 보낼 IP와 Port를 입력해야한다.
또한, Unreliable하기 때문에 데이터의 순서가 바뀌거나 소실될 수 있다.
TCP와 UDP에 대해서는 3장에서 더 자세하게 다룬다.
'3-2공부 > 컴퓨터네트워크' 카테고리의 다른 글
[기말] 8장 보안 (1) | 2022.12.10 |
---|---|
3장 네트워크 계층 (0) | 2022.10.28 |