데이터를 송/수신하는 과정에서 OS에 내장된 프로토콜 스택은 큰 역할을 담당하고 있다.
브라우저가 프로토콜 스택에 송신을 의뢰하면 프로토콜 스택(네트워크용 소프트웨어)과 LAN 어댑터(네트워크용 하드웨어)가 연동하여 네트워크 상에 메시지를 송/수신한다.
그렇다면 TCP/IP 계층 구조가 어떻게 데이 송/수신을 진행하는지 그림으로 알아보자.
위 사진에서 위쪽에 있는 계층이 작업을 의뢰하면 아래쪽에 있는 계층이 그 작업을 수행하는 방식으로 구성되어 있다.
물론 이 상하 관계가 확실하지 않거나 상황에 따라 역전되는 경우도 있으므로 그렇게까지 엄밀히 생각할 필요는 없다.
가장 위에 있는 계층은 네트워크 애플리케이션으로써 브라우저, 메일러(메일을 쓰는 SW), 웹 서버, 메일 서버 등이 해당된다.
이전에 배웠던 Request Message 및 Respond Message를 만들고 데이터 송/수신을 의뢰하는 부분으로 모든 네트워크 애플리케이션이 데이터를 송/수신하는 동작 과정은 유사하다.
네트워크 애플리케이션에는 Socket 라이브러리가 존재한다.
이전에 DNS 리졸버를 설명할 때 언급했지만 애플리케이션이 Socket 라이브러리의 프로그램을 실행시키면 실행된 프로그램이 프로토콜 스택에 의뢰를 진행하는 방식으로 데이터 송/수신이 진행된다.
네트워크 애플리케이션에 존재하는 Socket 라이브러리의 프로그램에 의하여 OS 내부에 있는 프로토콜 스택으로 데이터가 이동된다.
프로토콜 스택의 윗부분에는 TCP와 UDP라는 데이터 송/수신을 담당하는 프로토콜이 존재한다.
그리고 그 아래에는 패킷 송/수신 동작을 제어하는 IP 프로토콜이 존재한다.
TCP와 UDP는 나중에 자세히 알아볼 것이다.
일단 지금은 DNS 서버 조회 같은 짧은 제어용 데이터를 송/수신할 때 UDP를 사용하고 일반적인 경우에는 보안성이 좋은 TCP를 사용한다 정도로만 알고 있자.
이후 프로토콜 스택은 IP 프로토콜을 통해 패킷 송/수신 동작을 제어한다.
인터넷에서는 Message 형식의 데이터를 그대로 네트워크에 담아 보내지 않는다. 데이터를 작게 나눈 패킷이라는 형태로 만든 뒤 네트워크에 담아 운반하는데 IP는 이 패킷을 상대 서버까지 운반하는 것이 주 목적인 프로토콜이다.
IP 내부에는 ICMP와 ARP라는 프로토콜이 존재한다.
ICMP는 패킷을 운반할 때 발생하는 오류를 통지하거나 제어용 메시지를 통지할 때 사용한다.
ARP는 IP 주소에 대응되는 이더넷의 MAC 주소를 조사할 때 사용한다. 이 또한 나중에 자세히 공부할 것이다.
위에 존재하는 "프로토콜 스택" 및 "Socket 라이브러리"는 HW가 아닌 SW이다.
즉, 눈에 보이지는 않는 추상적인 개념인 것이다.
이러한 추상적인 요청을 실제로 실행하기 위해선 HW가 존재해야 할 텐데 바로 LAN 어댑터가 SW에 의해 정해진 송/수신 방식을 실제로 수행하는 주체가 된다.
LAN 어댑터는 케이블로 디지털 신호를 송/수신함으로써 네트워크 통신을 가능하게 한다.
이 LAN 어댑터라는 HW를 제어하는 소프트웨어도 필요할 텐데, 바로 이 SW를 LAN 드라이버라고 한다.
설명하며 MAC 주소, ARP, 패킷 등 여러 가지 새로운 개념이 나왔는데 나중에 자세히 설명하니 일단 이런 것이 있다 정도로만 알고 넘어가자.
눈치가 빠른 사람은 알 수도 있겠지만 소켓은 실체가 존재하는 개념이 아니다.
단지 개념적인 것으로써 분명 그것에 존재는 하지만 눈으로는 볼 수 없는 추상적인 개념임을 먼저 알고 있자.
프로토콜 스택은 상대 서버 측에 데이터를 보내기 위해 IP 주소, 포트 번호, 통신 진행 상태 등의 제어 정보를 기록해 둔다.
프로토콜 스택은 이러한 제어 정보를 저장하기 위해 따로 메모리 영역을 가지고 있는데 바로 이 영역이 소켓이다.
프로토콜 스택은 소켓에 저장되어 있는 제어 정보를 계속 참조하며 동작한다.
예를 들어 데이터를 송신할 때는 소켓에 저장되어 있는 상대측 IP 주소와 포트 번호를 활용해 데이터를 송신한다.
또한 데이터를 송신하는 과정에서 데이터가 없어질 수 있기 때문에 송신한 데이터에 대한 응답이 돌아왔는지와 동작 후의 경과 시간 또한 소켓에 저장되어 있다. 그리고 프로토콜 스택은 이런 정보를 바탕으로 송신 데이터가 누락되었는지 확인할 수 있다.
소켓이라는 것은 추상적인 개념이라 말로만 들으면 이해가 잘 안 갈 수 있으니 실제 사례를 눈으로 보며 더 학습해 보자.
윈도우에서는 "netstat" 명령을 통해 소켓 내용을 화면에 표시할 수 있다.
출처 : https://www.configserverfirewall.com/windows-10/netstat-command-to-check-open-ports-in-windows/
먼저 "-ano" 옵션 의미부터 알고 가자.
이후 각 Column이 어떤 의미를 가지는지 알아보자.
*:*
: UDP 프로토콜. 소켓을 상대측의 주소나 포트와 연결하지 않는 프로토콜이므로 기입할 수 없음부가 설명을 조금만 더 하면 소켓에 대해 이해가 쉬울 것이다.
위 netstat 명령의 1 행이 1개의 소켓에 해당한다.
만약 웹 서버에 접근하기 위해 소켓을 만든다면 위 사진에 새로운 한 행이 추가되는 것이다.
또한 개인 컴퓨터도 서버의 역할을 수행할 수 있는데 위 사진에서 확인할 수 있듯 0.0.0.0이라는 연결되어 있지는 않지만 존재하는 소켓이 있다.
이러한 사용되고 있지는 않으나 존재하는 소켓에 다른 서버의 소켓이 연결을 수행함으로써 두 개 서버 사이에서 데이터를 송/수신할 수 있게 된다.(이때 로컬 컴퓨터는 웹 서버 역할을 수행할 것이다)
마지막 행인 "192.168.122.176:49719"와 "52.139.250.254:443" 행 데이터는 아래와 같은 의미를 가지는 것이다.
로컬 컴퓨터의 LAN 어댑터에는 "192.168.122.176"이라는 IP 주소가 할당되어 있다.
그리고 4992라는 PID를 가진 프로그램은 로컬 컴퓨터에서 "222.233.54.144"라는 IP 주소를 가진 서버와 통신하고 싶다.
이때 로컬 컴퓨터는 443 Port 번호를 활용해 상대 서버의 소켓에 접근할 수 있으며 상대 서버는 49719라는 Port 번호를 활용해 로컬 컴퓨터의 소켓(마지막 행 데이터 소켓)에 접근할 수 있다.
이 두 소켓을 활용해 데이터 송/수신 과정이 진행되는 것이다.
소켓에 대해서 자세히 알아봤으니 이젠 네트워크 애플리케이션(브라우저)이 socket 명령을 실행할 때 프로토콜 스택 내부가 어떻게 동작하는지 알아보자.
socket 명령을 수행하면 일단 브라우저는 프로토콜 스택 내부에 있는 TCP 담당에게 소켓을 작성해 달라고 의뢰한다.
이후 프로토콜 스택 내부의 TCP 담당은 의뢰에 따라 1개의 소켓을 만든다.
프로토콜 스택이 소켓을 만들 때 최초로 하는 일은 소켓 1개 분량의 메모리 영역을 확보하는 것이다.
이때 프로토콜 스택이 자체적으로 메모리를 할당하는 것은 아니고 OS 내부에 존재하는 "메모리 관리"라는 소프트웨어 모듈에게 의뢰를 함으로써 소켓 1개 분량의 새로운 메모리 영역을 얻게 된다.
만약 메모리 관리라는 소프트웨어 모듈이 존재하지 않고 모든 프로그램이 자체적으로 메모리를 사용해 버리면 1개의 메모리 영역이 다수의 프로그램에 할당되어 중복 사용될 수도 있고 이 경우 다른 애플리케이션의 데이터를 파괴할 가능성이 있다. 이 때문에 1개의 SW가 메모리를 관리함으로써 이미 할당된 메모리를 다른 프로그램에서 멋대로 사용하지 못하게 하는 것이다.
소켓의 메모리 영역이 할당되었다면 할당된 메모리 영역에 소켓이 초기 상태임을(즉, 지금 만들어졌다는) 알리는 제어 정보를 저장하며 이 과정을 통해 소캣이 만들어진다.
소켓이 만들어졌다면 소켓을 구별하는 식별자인 디스크립터를 애플리케이션에게 알려준다.
디스크립터를 받은 애플리케이션은 이후 프로토콜 스택에 데이터 송/수신 동작을 의뢰할 때 디스크립터의 정보를 같이 넘긴다.
이렇게 하면 프로토콜 스택은 디스크립터를 통해 소켓을 찾아갈 수 있고 소켓에 저장되어 있는 여러 가지 상대 서버에 대한 제어 정보를 사용할 수 있으므로 애플리케이션 측에서 상대 서버에 대한 정보를 모두 보낼 필요가 없어진다.
만약 소켓이 존재하지 않는다면 상대 서버의 IP 주소, 포트 번호 등의 제어 정보를 프로토콜 스택에 동작을 의뢰할 때마다 같이 보내줘야 할 것이다.
하지만 소켓이 있을 경우 정수형 값인 디스크립터만 전달해 주면 프로토콜 스택이 알아서 소켓을 찾아가 상대 서버 IP 주소나 포트 번호 같은 제어 정보를 파악할 수 있으므로 큰 장점을 가지게 된다.