Socket

부스트캠프 챌린지가 끝나고, 마지막 미션의 후속편(?)으로 Underworld-Line이라는 소켓 통신 기반의 익명 채팅 프로그램을 만들었습니다.
근데… 소켓이 뭔가요?

소켓 프로그래밍과 HTTP 프로그래밍

일반적으로 Client가 필요로 하는 데이터들은 Server에서 관리합니다. 소켓 프로그래밍과 HTTP 프로그래밍은 네트워크를 통해 서버로부터 데이터를 가져오기 위한 통신 방법입니다.

소켓 프로그래밍

Socket Programming은 Server와 Client가 특정 Port를 통해 실시간으로 양방향 통신을 하는 방식입니다.
소켓 연결은 TCP/IP 프로토콜을 기반으로 맺어진 네트워크 연결 방식입니다. 클라이언트만 필요한 경우에 요청을 보낼 수 있는 HTTP 프로그래밍과는 달리 소켓 프로그래밍은 서버도 클라이언트로 요청을 보낼 수 있으며, 계속 연결을 유지하는 연결 지향형 방식이기 때문에 실시간 통신이 필요한 경우에 자주 사용합니다.
Twitch TV나 아프리카 TV같은 실시간 동영상 스트리밍 서비스를 예시로 들어보죠. 만약 이런 서비스를 HTTP 프로그래밍으로 구현하면 사용자가 서버로 동영상을 요청하기 위해서는 동영상이 끝나는 순간까지 계속해서 HTTP Request를 보내야 하고, 서버에 지속적으로 연결 요청이 들어가기 때문에 서버에 무리가 갑니다. 3-way handshake를 통해 연결 한 뒤 데이터를 전송하고, 이후 4-way handshake를 통해 연결을 해제하는 과정을 매 요청마다 진행하는 것이죠. 따라서 이런 경우에는 계속 연결을 유지하는 소켓 프로그래밍을 사용해야 합니다.

HTTP 프로그래밍

HTTP Programming은 Client의 Request가 있을 때에만 Server가 Response해서 해당 정보를 전송하고 곧바로 연결을 종료하는 단방향적 통신 방식입니다. 기본적으로는 소켓 연결 위에서 맺어지는 애플리케이션 계층의 연결 방식이며, 클라이언트가 요청을 보내면 서버가 응답하는 방식만 가능합니다. 서버가 클라이언트로 요청을 보낼 수 없네요..
어떤 홈페이지에 들어간다고 합시다. 해당 링크를 누르면 웹(클라이언트)은 웹 서버(서버)에게 홈페이지의 내용을 보여달라고 요청을 보냅니다. 이 요청에 걸리는 시간에는 클라이언트가 서버의 소켓에 연결하는 시간, 서버로부터 요청을 기다리는 시간이 포함됩니다.
HTTP 프로그래밍 방식은 실시간 연결이 아닌, 필요한 경우에만 서버로 접근하는 컨텐츠 위주의 데이터를 사용할 때 유용합니다. 만약 게시글의 데이터를 받은 이후에도 연결을 유지한다면 서버에 과부하가 걸리게 됩니다. 위에 적어놓은 저 handshake를 하는게 서버에게는 이로울 수도 있어요..
일반적으로 모바일 애플리케이션은 필요한 경우에만 서버에 정보를 요청하는 경우가 많은데, 이때 HTTP 프로그래밍을 사용하면 필요할 때만 서버에 연결을 함으로써 여러 이득을 볼 수 있습니다.

소켓 서버 vs 웹 서버

문득 그런 생각이 들었습니다. ‘보통 백엔드라고 하면 웹 서버를 의미하는데, 소켓 서버와 다른 걸까?’ 복잡합니다 복잡해..

  • 소켓 서버
    • TCP/IP, UDP/IP의 소켓을 직접 다루거나, 그것을 직접 다루는 엔진을 사용한 프로그래밍을 합니다.
    • 커넥션 풀을 직접 관리하며, 서버가 원할 때 클라이언트에 패킷을 보낼 수 있습니다.
    • 서버 자체의 메모리에 유저 데이터들을 저장하여 처리할 수 있습니다.
    • 보통 MMORPG나 실시간 스트리밍 등 실시간성이 중요시되는 게임 개발에 사용합니다.
    • 소켓을 다룬다는 것은 OS의 기능을 직접 다룬다는 의미입니다.
    • 주로 멀티 스레드로 개발됩니다.
    • 유저 데이터를 메모리에 저장하고, 멀티 스레드이기 때문에 잘 못 다루면 대혼돈을 겪을 수도 있습니다.
    • 소켓 서버의 최적화는 서버 머신 1대 당 몇 명의 동시 접속자 처리가 가능한가에 달렸습니다. 이는 곧 돈으로 연결됩니다.
    • 수평 확장이 어렵습니다.
  • 웹 서버
    • Node.js, 아파치, iis 등 웹 서버 프로그램을 띄우고, 그 안의 컨텐츠를 작업합니다.
    • 크게 보면 소켓 서버의 파생형입니다.
    • 모든 요청은 Web Request로 들어오며, 라우팅 된 주소가 각각의 함수, 인자값이 됩니다.
    • 모든 요청마다 별도로 연결을 맺고 끊는 방식으로 웹 요청과 동일합니다.
    • 서버 자체의 메모리에 유저 데이터를 들고 있지 않도록 개발됩니다.(수평 확장 때문)
    • 보통 실시간성이 적은 게임 개발에 사용합니다.
    • 매번 연결을 맺고, 메모리에 유저 데이터가 없어 DB에 접근해야 되기 때문에 상대적으로 속도가 느릴 수 밖에 없습니다.
    • 수평 확장이 비교적 용이합니다. 메모리에 유저 데이터가 없으므로 그냥 웹 서버를 여러 개 만들어 부하를 분산합니다.
    • 성능 개선과 실시간처럼 보이는 처리를 위해 각종 미들웨어를 공부하고 사용해야 합니다.

기타

TCP/IP -> HTTP -> WebSocket -> Socket.io 식으로 흐름이 구성되어 있습니다. 따라서 커다란 의미로 TCP/IP에 Socket.io가 포함됩니다. TCP/IP를 이용해서 HTTP 프로토콜로 웹 소켓을 구현한 것을 사용하기 쉽게 프레임워크화 한 것이 Socket.io입니다.
Socket.io는 TCP/IP로 통신합니다. 다만 사용중인 프로토콜이 텍스트 기반의 HTTP일 뿐입니다.
따라서 TCP/IP 소켓을 구현하는 서버/클라이언트 모듈을 사용하려면 net 모듈을 사용해야 합니다.

요약

  • 소켓 프로그래밍
    • 서버와 클라이언트가 계속 연결을 유지하는 양방향 프로그래밍 방식이다.
    • 서버와 클라이언트가 실시간으로 데이터를 주고 받는 상황이 필요한 경우에 사용한다.
    • 실시간 동영상 스트리밍이나 온라인 게임 등에서 자주 사용한다.
  • HTTP 프로그래밍
    • 클라이언트가 요청을 보내는 경우에만 서버가 응답하는 단방향 프로그래밍 방식이다.
    • 서버로부터 소켓 연결을 하고 응답을 받은 후에는 연결을 바로 종료한다.
    • 응답이 필요한 경우에만 서버와 연결을 해 요청을 보내는 상황에 주로 사용한다.
    • 모바일 애플리케이션의 개발에 주로 사용된다.

참고