네트워크의 "연결" 과 관련한 주저리
네트워크의 "연결" 이라는 키워드를 언급하면, 다들 OSI 7계층을 떠올리고, 더 나아가서 TCP에 대해 떠올릴 수 있을 것이다.
솔직히 말해서 기술면접 아니면 그렇게 깊게 다룰일이 없을 것 같았지만... 막상 회사 업무를 하다보면 이런 네트워크적인 이슈가 발생할 때 마다 심심치 않게 언급되는 원인이 연결 자체인 경우가 많았다.
세미나에서도 한 번 언급하기도 했지만, 많은 분들이 회사에 처음 입사하던 나 처럼 (...) 기술면접용으로만 TCP를 다루고 있어서 이 참에 한 번 깊게 파고 들어보자.
또한, 연결이라는 키워드는 7계층에서도 다룰 수 있는 주제인데, 어떤 관점에서 이를 다룰 수 있을지도 알아보자.
소켓부터 살펴보자.
우선, 소켓이 무엇인지부터 생각해 볼 필요가 있다. (취준생 분들이 소켓을 어떻게 이해하는지 궁금해서 구글링을 해봤더니, 심각한 오개념으로 넘쳐나는 글들이 구글 최상단에 있어서 부득이하게 정리해본다.) 다만 글의 목적은 이게 아니므로, 글을 이해할 수 있고, 오개념을 거를 수 있는 수준으로만 알아보자.
정말 짧게 요약하자면, "통신을 위한 인터페이스" 정도로 요약할 수 있다. 인터넷을 통한 외부 네트워크와의 통신이던, 같은 PC 내 서로 다른 프로세스 간의 통신이던 가리지 않고 지원하는 인터페이스라고 보면 된다. (일반적으로 사용하는 BSD Socket 기준)
리눅스의 철학상 당연히 파일이며, 이에 따라 내부적으로 소켓을 구분할 때도 파일 디스크립터를 사용하고 있다. (이후 포스팅으로 작성하겠지만, 파일이기 때문에 각 프로세스가 맺을 수 있는 연결의 수 또한 파일 정책을 적용 받아 제한될 수 있다.)
엔드포인트의 정보를 포함하고 있기 때문에 하나의 연결에 대해 하나의 소켓이 존재하며, 따라서 하나의 프로세스는 동시에 여러 소켓을 가질 수가 있다. (상술했듯이 이 또한 파일이기 때문에, 하나의 프로세스가 여러 파일을 열 수 있다는 걸 생각하면 쉽게 이해할 수 있다.)
크게 분류하자면 Unix Domain Socket, Network Socket (Internet Socket)으로 구분이 가능한데, 아주 짧게만 알아보자.
Network Socket
우리가 흔히 "소켓" 이라고 말하면 떠올리는 것을 의미한다. (이 글의 이후 섹션에서도 해당 Network Socket을 소켓이라고 지칭할 것이다.)
Network Socket의 주 목적은 "우리가 Transport Layer의 내부 구현을 알지 못해도, API 형태로 원하는 방식으로 통신 흐름을 제어하기 위함" 이다. (사실 내부 구현에 대한 이해 없이 원하는 목적을 달성할 수 있도록 하는 것이 API의 목적인건 다들 알죠?)
우리가 일반적으로 "네트워크 통신" 을 한다고 말한다면 99.999%는 내부적으로 소켓을 사용한다. (어쨌거나 소켓은 API 이기 때문에, NIC에 다이렉트로 때려박는 방식을 사용하면 소켓을 안 쓸 수는 있다. DPDK, PF_RING 등의 대안이 있지만, 이건 Network I/O 의 성능을 극한으로 올리기 위해 개발된 도구이고, 웹서버 개발하는 우리의 입장에선 잊어버리는게 좋다.)
생각 이상으로 많은 블로그가 이 개념을 혼동하다보니 생각보다 많은 오해를 하는데...
- 이상할 정도로 많은 블로그가 "HTTP 통신" 과 "소켓 통신" 에 대한 비교를 한다.
- 당연히 HTTP는 7계층 프로토콜이고, 4계층에선 소켓을 쓰기 때문에, 애초에 비교가 불가능하다.
- WebSocket을 보고 소켓이라고 착각하는 것 같은데, WebSocket은 7계층 프로토콜이고, HTTP와 WebSocket 모두 Socket API를 내부적으로 쓰고 있다.
- WebSocket 스펙 자체가 실시간 통신을 구현하기 위해 Socket API를 직접 구현하여 사용하던 이전의 문제를 해결하기 위해 고안된거지, 그래봤자 대신 Socket API를 호출하는건 변함이 없다.
- 다만 프로토콜 스펙의 차이로 인해 HTTP는 데이터 전송 완료 후 TCP 연결을 해제하고, WebSocket은 그렇지 않고 연결을 유지할 뿐이다.
