10.2 릴레이 서버 구동과 클라이언트 접속
퐁 게임의 OOP(Object Oriented Programming) 버전을 베이스로 해서 네트워크 게임으로 변환되면서 추가되고, 확장되는 부분만 추가로 설명해 나가는 방식을 취하겠다. 그러나 여러분들이 초보자임을 감안해야 하는데 네트워크에 대한 아주 기본적인 지식과 추가로 nethelper의 기본 사용법은 사전에 익혀야 하기 때문에 그 부분에 대한 설명을 먼저 하고 넘어가도록하겠다.
먼저 네트워크(Network) 관련 기본 용어정리를 하자. 우리는 네트워크 중에서도 컴퓨터 간의 유/무선(Wired/Wireless) 네트워크 만들어 필요한 정보를 상호교환하기 위한 목적인 컴퓨터 네트워크(Computer Network)로 한정한다.
랜(LAN) vs 인터넷(Internet)
각 용어의 구분은 네트워크의 규모의 차이에 의한 것으로 가장 기본 단위인 LAN(Local Area Network)은 제한된 지역 내에서 컴퓨터들을 연결하는 네트워크를 의미합니다. 여기서의 제한된 지역이란 보통 한 집, 한 교실, 한 사무실 또는 한 건물 정도의 규모라 생각하면 된다. 주변에서 손쉽게 볼 수 있는 것은 가정이나 사무실에서 무선 와이파이(WiFi) 라우터(Router)를 이용해 통신장치가 내장된 전자기기(컴퓨터 포함)들 사이에 통신망을 구성한 것이다. 인터넷은 이러한 네트워크의 기본단위인 LAN간의 연결을 점점더 확대하여 그 네트워크 규모를 전 세계단위로 확대한 것이다.
IP 프로토콜(Protocol)과 IP 주소(Adddress)
그렇다면, 네트워크 상에 묶여있는 기기 간에 데이터를 보내기 위해 기본적으로 무엇이 필요할까? 데이터를 송수신하기 위해서는 데이터를 어떤 형태로 가공한 후 어떠한 방식으로 주고 받을지에 대한 각 기기 간에 사전에 상호 약속을 전제해야 한다. 이러한 상호간의 통신을 위한 규약에 대해 프로토콜(Protocol) 이란 용어로 부른다. IP(Internet Protocol, 인터넷 프로토콜)라 불리는 통신규약은 이름 그대로 인터넷을 구성하기 위한 통신규약으로, 인터넷을 구성하는 기본 단위인 LAN에서부터 이 통신규약을 지켜서 통신해야 하는 것이다. 이 통신규약 안에서는 네트워크 안에 존재하는 통신하고자 하는 상대를 인식하고 구분하기 위한 인식체계를 갖고 있는데 그것은 우리가 실생활에서도 널리 쓰는 방식인 주소(Address)를 기반이다. 집 주소, 이메일 주소를 알면 그 상대를 특정해서 우리가 필요한 데이터(메시지 또는 편지 등)를 전송할 수 있는 것처럼 말이다. 따라서, IP 주소는 IP 프로토콜 통신규약으로 통신하게 위해 인터넷 상에 위치한 모든 통신기기들에게 부여되는 임시적인 주소인 것이다. 여기서 임시적으로 부여된다는 의미는 모든 기기에 그 주소가 사전에 영구적으로 할당되는게 아니라, 통신망에 연결해 통신이란 활동을 할 때만 임시적으로 사용할 수 있도록 인터넷 통신망에 연결되는 순간에 일시적으로 부여된다.
여러분 컴퓨터가 현재 네트워크에 연결되어 있는가? 그렇다면 할당받은 IP 주소를 반드시 갖고 있을 것이고, 내가 할당받은 그 IP 주소는 어떻게 확인할 수 있을까? 다음의 방법을 통해 확인할 수 있다.
Windows
명령 프롬프트(Command Prompt) 이용:
윈도우 키 + R을 눌러 실행 창을 엽니다.
cmd
를 입력하고 Enter 키를 누릅니다.명령 프롬프트 창이 나타나면
ipconfig
를 입력하고 Enter 키를 누릅니다.IPv4 주소가 컴퓨터의 IP 주소입니다.
macOS
터미널 이용:
Finder > 응용 프로그램 > 유틸리티 > 터미널을 실행합니다.
ifconfig
를 입력하고 Enter 키를 누릅니다.en0 또는 en1(Wi-Fi의 경우) 섹션에서 inet 뒤에 오는 주소가 IP 주소입니다.
클라이언트(Client)와 서버(Server)
두 용어의 영어 뜻 그대로 클라이언트(Client)는 고객이란 뜻으로 서비스를 요청하는 자이고, 서버(Server)는 고객의 요청에 응대해 서비스를 제공하는 자이다. 그런데, 네트워크에서의 클라이언트이든 서버는 컴퓨터 단위의 개념이라기 보다, 컴퓨터에 돌아가는 프로그램으로 보는게 이해가 쉽다.
우리는 앞서 릴레이(중계) 서버에 대해 살펴봤다. 서버를 프로그램이라고 했는데, 즉, 릴레이 서버란 프로그램을 실행시켜 놓으면, 그 서버 프로그램은 이제 메시지의 중계자 역할로서 온라인 게임 참여자들의 클라이언트 프로그램 간에 상호 데이터(메시지)를 이쪽으로 저쪽으로 넘겨 전달해주는 서비스를 제공하는 행위인 서빙(Serving)을 시작하게 된다. 우리가 네트워크 상에 연결된 불특정 다수와 같이 온라인 게임을 하기 위해 이 릴레이 서버 컴퓨터는 물리적으로 어디에 위치시키면 가장 좋을까? 여러분이 실제 상업적인 게임 서비스 제공한다라면 당연히 네트워크 상에 모든 사용자에게 가장 접속이 용이한 곳이면서 동시에 모든 게임 참여자들에게 빠른 네트워크 속도를 제공할 수 있는 장소를 고려할 것이다. 그런 곳이 어딜까? 그렇다. 여러분들이 한번쯤을 들어봤을 용어인데 그런 장소를 데이터 센터(Data center) 또는 클라우드(Cloud)라고 부른다. 물론 그런 물리적 장소를 임대하는 것은 비싼 비용이 들어간다.
릴레이 서버 구동과 클라이언트 접속
우리는 이제 막 네트워크 게임 만들기를 배우는 수준에서 저런 장소가 당장 필요할까? 당연히 필요가 없다. 그러나, 혹시나 나중에 상당히 원거리에 떨어져 사는 친구와 여러분이 만든 온라인 게임을 함께 하고 싶을 때가 올 수도 있는데, 그때는 한번 클라우드 상에 가상 컴퓨터를 임대하는 것도 고려해보도록 하자. 그러나 당장은 이 릴레이 서버 프로그램을 단지, 여러분 본인 컴퓨터에서 실행시켜 당장은 본인 컴퓨터가 릴레이 서버역할을 하게 하자. 릴레이 서버 프로그램은 nethelper 라이브러리 내에서 제공되는데 여러분 각자의 컴퓨터에서 다음과 같이 명령 프롬프트 창 또는 터미널에서 프로그램을 실행할 수 있다.
여기서 그룹명은 온라인게임에 참여자들이 모이게 되는 공간인 그룹(group)의 이름 나타내는 것으로 미리 그룹의 이름을 정해놔야 그 그룹명 식별자를 통해 게임참여자들이 해당 공간에 합류할 수 있게 된다. 우리는 온라인으로 같이 퐁(pong) 게임을 할 예정이므로, 방 이름을 pong_game 이라 하겠다. 그 그룹명과 함께 실행하면 다음과 같은 실행결과를 볼 수 있다. 서버가 잘 시작되었다면 클라이언트들의 접속을 대기하고 있단 의미의 listening 이란 메시지를 볼 수 있을 것이다. 서버는 온라인 게임이 진행되는 동안은 계속 실행된 상태(alive) 이여야 하므로, 실행된 창 그 상태를 건드리지 말고 그대로 유지하도록 하자.
다음으로 클라이언트들 즉, 릴레이 서버에 만들어진 그룹방에 접속해 실제 게임을 하게 되는 네크워크 게임 프로그램을 만들 건데, 정확히는 릴레이 서버의 pong_game이라 불리는 그룹방에 접속하는 부분을 먼저 코딩해 보자.
nethelper 라이브러리에서 NetNode 라는 네크워크 게임유저로서 한 일원(node)이 되는 객체를 import 한 후, 10번라인에서 그 객체를 생성하고 있다. NetNode 객체에는 connect 라는 멤버함수가 있는데, 4개의 파마리터값을 인자로 갖는다. 첫번째로 릴레이 서버의 IP주소, 두번째로 본인의 그룹방에서의 id, 세번째가 그룹방 이름, 네번째는 서버와의 연결성립이 완료될 때까지의 대기유무를 나타낸다. 각각의 인자값(argument)들을 자세히 살펴보자.
첫번째, 릴레이 서버주소가 'localhost' 이다. 원래 IP주소는 4개의 숫자가 점으로 구분된 형태라는 점을 알고 있을텐데, 예외적으로 본인 컴퓨터 자기자신을 나타내는 IP 주소로 고유하게 약속된 값인 127.0.0.1 이란 주소를 대신해 간편하게 나타내는 동일표현으로 localhost 를 사용할 수 있다. 그말은 만약 'localhost' 란 값을 쓰기 싫으면, 대신해 '127.0.0.1' 란 값을 지정해도 된다는 뜻이다. 두번째, 그룹방에 접속시 본인 id를 Player1 으로 하겠다는 것인데, 그 말은 곧 그룹방에 젤 먼저 들어가는 사람은 게임전체를 총괄하는 주인(host)을 담당하게 된다는 것이다(23번 라인). 릴레이 서버방식의 게임상 그룹방에 한사람은 반드시 호스트의 역할을 해야는게 룰인데, 우리 게임에선 젤 먼저 그룹방에 접속하는 사람이 호스트가 되기로 한다. 이 게임은 단 2인만 즐기는 일대일 대전형 게임이고, 본인이 호스트가 되었다면 본인의 상대가 되는 게임유저의 id는 자연스럽게 Player2 가 될 것이다(18번 라인). 19번 라인에 my_bar라는 글로벌 변수는 나중에 내가 조작하는 반사판이 좌/우측 중에 어떤 것인지를 구분하기 위한 용도로 우리 게임에서는 호스트는 항상 좌측면의 반사판(bar1)을 조작하게 되며, 상대가 되는 게임유저는 우측(bar2)를 조작하도록 한다. 참고로 해당 코드를 실행시킨다면 당장은 코드실행시 해당 변수(bar1 또는 bar2)가 없다는 에러가 발생하므로 임시로 주석처리를 하여 실행시키도록 하자.
순서상 두번째로 그룹방에 접속하는 사람은 곧바로 21번 라인으로 진입하게 되는데 그 이유는 connect 멤버함수는 호출시 인자값으로 넘긴 원하는 id값을 이미 그룹 내 다른 유저가 사용 중이라면, 곧바로 False값을 리턴하게 되기 때문이다. 따라서, 두번째 접속자는 호스트의 역할은 아닌 호스트로부터의 제어명령과 게임상태정보 받아 처리하면서 게임에 참여하는 일반 유저가 된다.
참고로 우리 온라인 퐁 네트워크 게임 프로그램은 호스트용/일반유저용을 구분하여 각각 별도로 개발하지 않고, 한 프로그램에서 두 가지 역할을 다 소화가능하도록 만들 예정이다. 따라서, 위에 릴레이 서버와의 네트워크 연결을 위한 것도 두 역할(호스트/일반유저)을 다 소화할 것이고, 이 pong_net.py 라는 프로그램을 시험해보기 위해서는 명령 프롬프트(또는 터미널) 창을 새로 2개를 띄워놓고, 각각의 창에서 이 pong_net.py 라는 프로그램을 각각 실행시켜 보기 바란다. 2개의 창 어느쪽에서든 먼저 실행시킨 쪽이(접속시킨 쪽이) pong_game 그룹방에서의 호스트(Player1)가 되는 것을 알 수 있다.
참고로 그룹에 두 명의 게임유저가 다 모여야 게임시작조건이 되고, 먼저 그룹에 입장했고 상대가 입장하기를 기다리는 부분에 UI적인 처리가 필요하며, 다음의 코드를 통해서 처리할 수 있다. 여기서 num_peers 라고 하는 글로벌 변수값에는 현재 그룹 참여자의 총수를 실시간으로 나타낸다.
지금까지 네트워크 게임시작을 위한 릴레이 서버를 통한 게임유저들 간의 기본적인 연결이 끝나고, 다음 절에서부터 본격적으로 네트워크 게임진행을 위해 필요한 코드를 추가해 보도록 하자.
Last updated
Was this helpful?