<aside> ✅ 금주의 키워드
https://github.com/Gn0lee/webproxy-jungle
</aside>
네트워크는 우리 일상생활에서 매우 다양한 방식으로 사용된다. 하지만 네트워크는 클라이언트 서버 모델을 기본으로 확장되었으며, 꼭 지켜야 할 규약이 있다. 이번 proxy lab에서는 socket방식의 웹서버 구현을 하려한다. 네트워크에 대한 기초적인 지식과 proxy lab에서 어떤 식으로 구현 했는지 작성해보려 한다. 코드를 자세하게 들여다 보기 보다 전체적인 흐름을 파악해 보려 한다. 전체 코드는 위 github 링크를 통해 확인 할 수 있다.
네트워크
위에서 언급했듯이 네트워크는 기본적으로 클라이언트-서버 모델에 기초하고 있다. 클라이언트는 서버에 요청을 하고 서버는 그 요청에 맞는 데이터를 가공하여 응답한다. 이를 그림으로 표현하면 아래와 같다.

위의 그림을 보면 클라이언트 프로세스, 서버 프로세스가 있다. 명칭에서 알 수 있듯이 네트워크는 컴퓨터 전체가 연결되는 것이 아니라 프로세스와 프로세스가 연결된다. 여기서 컴퓨터 전체는 호스트라고 부른다. 그래서 한 호스트안에 클라이언트 프로세스와 서버 프로세스가 공존 할 수 있다. 그렇다면 클라이언트 프로세스와 서버 프로세스는 어떻게 통신 할까? 우선 컴퓨터는 네트워크를 하나의 I/O 장비로 인식한다. 다른 I/O 장비와 마찬가지로 네트워크 파일 지정자에 내용을 작성(request)하면 서버 프로세스가 그 내용을 읽고 자신의 네트워크 파일 지정자에 적는(response) 방식이다. 아래 그림과 같이 I/O 버스에 네트워크 어댑터를 통해 서버 프로세스와 연결된다.

어떻게 통신하는지 아주 아주 개략적으로 알아 보았으니 이제 어떤 방식으로 연결되어 있는지 살펴보자. 네트워크는 버스를 타는것으로 비유해 생각하면 이해하기가 쉽다. 아래 이미지와 연결하여 설명하면 다음과 같다. 우리가 서울에 있는 나의 집(Host A)에서 대전에 있는 친구 집으로 버스를 타고 간다고 생각해보자. 그러면 우선 대전 버스터미널로 가는 표를 예매(encapsulation)한다. 그리고 마을 버스(LAN1)을 타고 고속 버스 터미널(LAN1 adapter)에 가서 고속버스를 탄다. 버스를 타고 대전 버스터미널(LAN2 adapter)에 내려서 마을버스(LAN2)를 타고 친구 집(Host B)으로 간다. 이를 좀 더 상세히 설명하면 다음과 같다. 호스트 A에서 호스트 B로 가기위해서는 우선 LAN1에서 데이터를 패킷(packet)형태로 가공한다. PH와 FH는 택배 배송정보라고 생각하면 편하다. 이러한 패킷이 라우터에 가면 라우터의 프로토콜 소프트 웨어가 LAN2에 맞는 형식으로 재가공하여 LAN2로 보낸다. 만약 LAN2가 다른 라우터에 있으면 다른 라우터로 보낸다. LAN2로 들어온 데이터 패킷은 LAN2의 프로토콜 소프트웨어에 의해 데이터만 남고 그것을 서버 프로세스가 읽는다.

이러한 연결 관계를 internet이라 하고 우리가 일상적으로 사용하는 용어인 인터넷은 internet 중 가장 유명한 예시인 Global Internet으로 Internet이라고 기입힌다. Internet을 사용하는 host의 주소를 IP(Internet Protocol)주소라고 한다. 시작 부분에서 꼭 지켜야할 규약이 있다고 했었다. 이를 프로토콜(protocol)이라 하며 대표적으로 TCP와 UDP가 있다. TCP는 정보를 완전하게 받으려 하므로 신뢰 할 수 있고 따라서 응답시간이 느리다. 보통의 웹페이지에서 사용된다. 그리고 UDP는 정보가 모두 오지 않아도 상관이 없어 신뢰도가 떨어지고 응답시간이 빠르다. 주로 데이터가 좀 없어도 상관 없는 동영상 스트리밍에 사용된다. 이번 proxy lab에서는 TCP방식을 사용한다.
DNS
우리가 보통 인터넷 브라우저에서 http://naver.com이라고 작성하지 IP주소를 기입하지는 않는다. 이것은 DNS방식을 사용하기 때문인데 간단히 들여다 보면 다음과 같다.
DNS 란?
DNS란 Domain Name System의 약자이며 범국제적인 단위로 웹사이트의 IP 주소와 도메인 주소를 이어주는 시스템이다. 개략적으로 설명하자면 우선 우리가 브라우저에 naver.com을 입력하면 브라우저는 DNS서버에 naver.com의 IP주소를 물어본다. 그러면 DNS서버는 요청한 도메인 주소의 IP주소를 응답해 준다. 그러면 브라우저는 받은 IP주소를 활용해 네이버에 접속한다. 이를 간단한 그림으로 나타내면 다음과 같다.

DNS 서버의 종류
전세계 사용자들이 매번 DNS 서버에 접속하여 IP주소를 물어보면 DNS서버가 터지거나 시간이 매우 오래 걸릴 것이다. 그래서 캐시의 개념으로 중간 역할을 하는 DNS서버들이 있다.
전체적인 DNS 동작 원리

전체적인 DNS의 동작원리를 위 이미지를 바탕으로 설명하면 다음과 같다. 우선 브라우저는 Recurcive DNS 서버에 요청한 도메인의 IP주소가 있는지 물어본다. 만약 Recurcive DNS 서버에 문의한 IP주소가 있다면 바로 브라우저에 알려준다. 하지만 Recurcive DNS 서버에 데이터가 없다면 Recurcive DNS 서버가 Root DNS에 어느 TLD DNS 서버에 가야할지 문의한다. 답변을 받으면 전과 같은 방식으로 해당 TLD DNS서버에 어느 Authoritative DNS 서버로 가야하는지 문의하며 TLD DNS서버는 가야할 Authoritative DNS 서버를 알려주며 Recurcive DNS 서버는 해당 Authoritative DNS 서버에 방문하여 IP주소를 받아온다. 마지막으로 Recurcive DNS 서버는 요청받은 도메인 주소의 IP주소를 브라우저에 알려준다. 브라우저도 기본적으로 방문했었던 페이지의 IP주소를 캐시형태로 저장하여 매번 Recursive DNS 서버에 묻지 않는다.
위 내용은 아래 블로그 내용을 참고하였습니다.
Socket
이번 프록시 랩에서 사용하는 소켓 연결방식을 간단하게 설명하고자 한다. CSAPP 책에서 정의하는 Socket은 다음과 같다.
<aside> ❗ Socket의 정의
To the kernel, a socket is an endpoint of communication To an application, a socket is a file descriptor that lets the application read/write from/to the network
</aside>
소켓은 연결의 맨 끝점이며 프로세스는 소켓에 Write하여 request하며 소켓 내용을 Read하여 Response를 파악한다. 그렇다면 이러한 소켓은 어떤 과정을 거쳐서 만들어 질까? 클라이언트와 서버의 소켓 생성과정은 약간 다르다. 이를 그림으로 나타내면 다음과 같다.

위의 과정에서 사용된 함수들에 대해 조금 더 설명하고자 한다.
getaddrinfo
이 함수는 연결에 필요한 정보를 담은 구조체를 생성한다. 구조체 안에는 IP주소,어느 방식의 프로토콜을 사용하는지 등등에 대한 정보를 담고 있다.
socket
연결에 사용할 소켓 식별자를 생성한다.
connect
클라이언트가 서버에 연결 요청을 한다.
bind
서버의 정보를 소켓에 입력한다.
listen
클라이언트의 연결요청을 기다린다.
accept
클라이언트의 연결요청을 확인하고 이상이 없다면 연결하여 연결 파일 식별자를 만들어 통신을 시작한다.
rio(robust i/o) 관련 함수들
프록시 랩에서 만든 라이브러리로 안정적으로 파일의 내용을 읽고 쓰게끔 도와준다.(CSAPP 10장)
이러한 여러 함수들을 묶은 것이 open_clientfd와 open_listentfd 함수이다. 이 두 함수를 이용하면 보다 깔금하고 간단하게 클라이언트와 서버를 연결 할 수 있다. 이 socket은 위 github의 tiny.c와 proxy.c에서 확인 할 수 있다.
Proxy Server
프록시 서버란 내가 연결하고자 하는 서버의 중간에 위치하여 나와 서버의 통신을 대신한다. 이를 그림으로 간단하게 나타내면 다음과 같다.

프록시 서버는 이전에 프록시 서버에 요청된 내용들을 저장하고 있다. 만약 사용자가 요청한 내용이 이전에 요청했던 것이라면 프록시 서버가 바로 응답해 주면 된다. 이를 통해 사용자는 매번 서버까지 갈 필요가 없어 서버의 부하를 줄여 줄 수 있다. 또한 사용자가 서버에 접속하지 않아 보안적으로 더 안전하다. 이러한 프록시는 서버의 위치에 따라 두가지로 나눌 수 있다.
느낀점 및 더 보아야 할 것