2.11 더 읽을거리
이 장에서는 컴퓨터 네트워크의 전반적인 내용보다 온라인 게임을 개발할 때 유용하게 활용하는 내용 위주로 서술했습니다. 이외에도 심화 내용을 원하는 사람을 위한 자료를 소개합니다.
OSI 모델의 계층 3에서 IP 패킷이 어떻게 목적지에 갈 수 있는 라우터로 전달되는지 이해하려면 라우팅(routing)과 주소 결정 프로토콜(Address Resolution Protocol, ARP)을 찾아보세요. 자세한 내용은 《Data Communications and Networking》(McGraw-Hill, 2012)에 잘 설명되어 있습니다. 이 도서에서는 OSI 모델의 계층 1~7을 자세히 설명합니다.
IPv6과 IPv4를 모두 잘 지원하는 프로그램을 개발하려면 Dual Stack과 NAT64/DNS64에 대한 이해가 필요합니다. 자세한 것은 http://goo.gl/OlCFHP 혹은 http://goo.gl/tXUCRQ를 참고하세요.
TCP 흐름 제어는 등기 우편의 원리와 비슷하지만, 실제로는 훨씬 복잡합니다. 세그먼트를 보내는 것과 응답(ack)을 받는 것이 동시다발적으로 진행되고, 응답이 오지 않으면 세그먼트를 보내는 속도를 일시적으로 제한한다든지 제한한 속도를 최대한 효율적으로 해제하는 등 알고리즘이 맞물려서 작동합니다. 자세한 것은 앞서 언급한 도서에서 ARQ와 혼잡 제어 부분을 참고하세요.
네트워크 게임의 성능 최적화를 위해 TCP를 직접 쓰지 않고 UDP 위에 TCP 같은 흐름 제어를 별도로 구현하는 경우도 있습니다. 예를 들어 패킷을 유실하여 재송신을 의도적으로 더 빠르게 하고 싶을 때 유용한 방법입니다. 이를 구현하는 것을 흔히 Reliable UDP 혹은 RUDP라고 합니다. RUDP를 구현한 예로는 프라우드넷이나 RakNet 등이 있습니다.
송신자와 수신자 간 오가는 메시지는 제3자가 도청하거나 변조할 수 있습니다. 즉, 해커의 개입이 있을 수 있습니다. 이를 방지하려면 송신자와 수신자 간 메시징을 암호화해야 합니다. 이것은 5.8절에서 다룹니다.
NAT 라우터에서 홀펀칭 혹은 포트 매핑을 가능하게 하는 기술은 다양합니다. 자세한 것은 Full cone NAT, uPNP 등을 참고하세요. 서로 다른 공유기 뒤에 있는 기기끼리 통신을 하는 기법들도 있습니다. 프라우드넷이나 STUN이 그러한 역할을 합니다.
NAT 기술은 일반 사용자에 해당하는 클라이언트뿐만 아니라 서버에서도 많이 활용됩니다. 대표적인 것이 클라우드 서비스입니다. 클라우드 서비스에서는 인터넷 주소 1개를 여러 서버 기기가 공유합니다. 이 경우 NAT 기술이 사용되는데, NAT 기기는 L4 스위치 혹은 로드 밸런서라고 합니다.
IPv6과 IPv4가 혼용되는 세상이지만, 이들은 서로 호환되지 않습니다. IPv6을 아직 지원하지 못하는 통신망이 구동되는 곳에서는 설비 교체 비용이 비싸 고민할 수밖에 없습니다. IPv6을 전혀 지원하지 않는 네트워크와 IPv6 네트워크 사이에서도 주소 변환을 해야 할 때가 있는데, 이때 역시도 NAT 기술이 사용됩니다. 그리고 이러한 NAT 기술을 NAT64 & DNS64라고 합니다.
메시지 안에 여러 필드를 넣거나 꺼내는 과정을 일일이 손으로 코딩하는 것은 번거롭습니다. 그리고 프로그래머가 실수를 하기도 합니다. 메시지 안에 필드를 넣거나 꺼내는 과정을 기계로 자동화할 수 있으면 여러분 일이 더 쉬워지겠지요.
메시지를 송신하는 쪽에서는 필드를 채우고, 메시지를 수신하는 쪽에서 필드를 꺼내는 것은 각각 다음과 같이 추상화(abstraction)를 할 수 있습니다.
• 여러분이 직접 메시지 필드를 채우는 대신 어떤 함수가 메시지 필드를 채워서 송신합니다. 이 메시지에는 메시지 종류가 무엇인지(예를 들어 로그인 요청인가? 채팅 보내기인가?)가 먼저 들어가고, 그다음 여러분이 정의한 필드들이 들어갑니다. 이 함수는 기계적으로 자동 생성되며, 여러분은 메시지가 무슨 필드를 가지는지 함수 선언 형태로 표현만 하면 됩니다.
• 생성한 함수를 단순히 호출함으로써 메시지 송신을 할 수 있습니다.
• 메시지를 수신하는 쪽에서는 메시지 종류가 무엇인지 판단하고, 메시지 종류에 맞추어서 필드들을 꺼내 옵니다. 이 과정을 담당하는 코드 역시 기계적으로 자동 생성됩니다. 그리고 메시지 종류와 필드에 맞는 함수를 호출합니다. 여러분은 이 코드에서 호출하는 함수를 미리 만들어 두기만 하면 됩니다.
결국 이 모양새는 ‘원격지에 있는 함수 호출’과 같습니다. 그래서 이를 원격 프로시저 호출(Remote Procedure Call, RPC) 혹은 원격 메서드 호출(Remote Method Invocation, RMI)이라고 합니다. 자세한 것은 6.6절에서 설명합니다.
원격 프로시저 호출(RPC)이나 원격 메서드 호출(RMI) 모듈에는 다음과 같은 것들이 있습니다.
• 아파치(https://thrift.apache.org) 혹은 구글 gRPC(https://grpc.io)는 특정 게임 엔진에 종속되지 않는 오픈 소스 모듈입니다. 소프트웨어 개발에서 범용적으로 널리 사용됩니다.
• 프라우드넷의 RMI 기능(http://proudnet.com)을 이용해서 메시지 필드 처리를 쉽게 할 수 있습니다. gRPC나 Thrift와는 다르게 게임 개발에 특화되어 있어 군더더기가 없습니다.
• 유니티 엔진의 네트워킹 기능(http://bit.ly/2Geultd)이나 언리얼 엔진의 RPC 기능(http://bit.ly/2UHdRwW)도 효과적입니다. MMO 게임을 개발할 목적이 아니라면 게임 엔진의 기본 기능이므로 별다른 준비 과정 없이 바로 사용할 수 있습니다.
여러분이 직접 RPC나 RMI 모듈을 만드는 방법도 있습니다. 이것은 ‘빠르고 효율적인 원격 프로시저 호출 구현’9을 참고하기 바랍니다.
9 《GAME PROGRAMMING Gems 5》(정보문화사, 2006), p.723.