jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다. 3ds Max를 사용해서 게임용 3D 캐릭터를 셋업하는 방법
이를 위해 오랜 실무를 경험해 온 저자의 고급 노하우들이 공개
위 내용은 GameDevForever의 저자분들의 홍보를 위하여 운영진 자체적으로 올린 광고이며 일체의 수익이 없습니다.(밥좀사줘요~)
Posted by Rhea Strike

으음, 본의 아니게 5일이나 늦었습니다.
백수 주제에 아파치 웹서버 설정 문제로 골치를 앓아 시간을 소비했습니다.
대신 오늘 포스트는 가장 실용적인 포스트와 예제가 될 것입니다.

여친 만들기는 여전히 노력조차 못하고 있는데, 도대체 왜 이렇게 사나... 생각중입니다.
최근 고등학교때 동기, 후배분, 선생님을 뵙고 오니 더 복잡한 생각이 듭니다.

이번엔 다리 휘었다는 댓글은 안달리길 바라며.

이번엔 다리 휘었다는 댓글은 안달리길 바라며.

오늘의 주제는 데이터베이스(Database)와 그것을 이용한 프로젝트입니다.
그런데 이상하게도 어느 게임 관련 서적에도 DBMS에 대한 이야기는 거의 나오질 않습니다.
먹고 사는데 중요한 정보는 쉽게 노출되지 않아서 일까요?
하지만 게임 업계에 근무하시는 분들은 이 DBMS야말로 핵심 요소라는 것을 잘 알고 계실 겁니다.

최근 KGC에서 N문사의 강산아님이 DBMS와 SQL 최적화에 대한 이야기를 해주시고 있는 것은,
그런 의미에서 아주 좋은 발전이라 생각합니다(서평을 바라신다면 한권 보내주시길 바랍니다. ^^).

열심히 읽어드리겠음.

열심히 읽어드리겠음.


자, 그럼 DBMS는 게임에서 어디에 쓰일까요?

1) 멤버쉽 전체 - 가입, 탈퇴, 로긴, 친구, 길드, 아바타...
2) 게임 컨텐츠 - 경험치, 레벨, 아이템, 공격력, 전적...
3) 몹정보 - 몹의 경험치, 레벨, 아이템, 공격력, 전적...
4) 사용자 패턴 분석
5) 그외 "정보"라고 할수 있는 모든 것을 담을 때

네, 다시 말해 게임과 서비스의 모든 것을 담고 있는 곳이 DBMS입니다.

또한 DBMS는 다양한 서버들에 있어 가장 쉬운 서버간 다리(brige)와 동기화 객체 역활을 해줍니다.

보통 회원 가입은 웹페이지(웹서버)에서 받습니다만, 게임 정보는 게임 서버를 이용합니다.
별것 아닌 단순한 형태이지만, 이미 한 DB에게 웹서버와 게임서버라는 역활이 다른 두개의 서버가 연결이 되었고
아무 쉬운 방법으로 두 서버가 한 사용자에 대한 정보를 공유한 것입니다.

그리고 이 웹서버와 게임 서버를 각각의 쓰레드 객체라고 생각하고 DB를 한 유저에 대한 유저 객체라고 놓고 본다면,
유저 객체에서 트랜잭션(transaction)을 이용해 쓰레드 동기화를 구현하고 있는 셈입니다.
이런 관점이 아키텍트로 나가는 첫 시점이라 생각합니다.

1. DBMS 기초
DB에 대해 익숙하신 분도 있고, 익숙하지 않은 분들도 많을 것입니다.
특히 학생 때에 DB에 대해 관심을 가지는 분들이 적습니다. 아마 비쥬얼한 것이 없고 DB를 사용하는 프로젝트도 없기 때문일 것입니다.
그래서 설명을 하긴 해야하는데...




.....




..................





......네, 코드도 재활용하는데 글이라고 재활용 못하겠습니까?
억지로 찾은 아래의 링크로 DB와 DBMS를 이용하는 법에 대한 내용은 날로 먹겠습니다.

날로 먹으니 더 맛있네요~

날로 먹으니 더 맛있네요~

1편 http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039130809
2편 http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039131033
3편 http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039131490

그러고 보니;;;;;;;;;;


날로 먹은 위의 글은, 당시 테마가 MFC라서 MFC로 되어져있지만, MFC가 아니더래도 똑같습니다.

만약 여기에 더 추가한다면 ADO.NET과 요즘 유행(?)하는 NoSQL에 대한 이야기를 적어볼까 합니다.
그러나 ADO.NET은 DataSet을 비롯한 강력한 기능에도 불구하고 닷넷 프레임워크를 필요로 한다는 점이 결정의 걸림돌이 됩니다.
즉 ADO.NET을 이용한다면 서버도 C#을 써야 합니다. Managed C++ 따윈 잊으십시요.

또한 NoSQL은 트랜잭션 처리와 보안과 안정성에 있어서 연구(그리고 직접 뜯어고치는 재빌드 필수)가 더 필요하다고 봅니다.
BLOB을 대체하기 위한 방법으로는 좋으나 마냥 NoSQL이 진리다~!! 라고 생각하는 것은 아니라고 봅니다.
주위에 NoSQL이 뜬다고 우리도 걍 NoSQL로 개발해~ NoSQL로 뒤짚어~~라는 분 있으면 이 문장을 보여주세요.
그래도 말 안들으면 딴 회사 가세요~~~
참고로 저는 mongoDB을 DB계의 UDP라고 생각합니다. 현존 관계형 DBMS가 TCP라면 mongoDB은 딱 UDP 같은 느낌입니다.

본격 Native C++ 강좌인 이 연재에서는 ADO를 이용하여 DB를 연결하겠습니다.

2. Winsock과 ADO를 이용한 아바타 채팅 시스템
간만에 실전 코드로 돌아가봅시다.
우리가 만들 것은 소켓과 DB를 이용한 로그인 + 아바타 채팅 시스템입니다.
로긴에 성공하면 DB에 저장된 자신의 아바타가 화면에 나오며 상대와 채팅을 할때면 대화를 보낸 사람의 아바타가 표시됩니다.
프로젝트 명세서

1) DB에는 ID와 PWD, 그리고 사용자 이름과 아바타가 있다.
2) 클라이언트에는 서버에게 ID와 PWD를 보낸다.
3) 서버는 클라이언트가 보낸 ID와 PWD를 DBMS에 질의 한다. 이때 DB 연결 방식은 ADO를 이용한다.
4) 로긴에 실패하면 실패 패킷을, 성공하면 사용자의 추가 데이터(이름, 아바타)를 보낸다.
5) 클라이언트가 보내는 채팅 메시지에는 아바타 정보가 포함된다.


명세서가 나왔으니 가장 먼저 DB를 만들어 봅시다.
MS-SQL Server 같은 것이 있으면 좋겠지만 대부분 무리일 것이니 위의 강좌처럼 MS-Access를 이용하겠습니다.
Access는 Excel에게 밀려 Office를 설치하며 잊으시는 분도 많을 것입니다.
그러나 Access는 MS-SQL Server를 대신하여 공부하기에 정말 좋은 개인용 DBMS입니다.
MS-SQL Server 로 마이그레이션도 아주 훌륭합니다.

이런 이야기를 왜 드리냐면, 수많은 게임 회사들은 전담 DBA가 없는 경우가 많기 때문입니다.
초기 개발단계나 규모가 작은 개발사라면 서버 개발자가 DBMS를 만질 수 밖에 없는 안타까움이 있습니다(...가끔 SE질도 합니다.).
신입 서버 개발자라면 이력서에 자신있는 DBMS 하나를 꼭 적어보시길 바랍니다.

2,1 Database 설계
넹, 딸랑 한 테이블입니다.
JOIN이고 머고 필요없습니다. 이 강좌가 SQL 강좌는 아니니까요.

꼴랑 필드 4개

꼴랑 필드 4개


ID와 PWD를 소켓으로 받아 NAME과 AVATRA를 내려보냅니다.

ID와 PWD를 소켓으로 받아 NAME과 AVATRA를 내려보냅니다.


별다른 설명이 없어도 어떻게 사용될지 보입니다.
서버에서 요청할 SQL문은 SELECT NAME, AVATAR FROM USER WHERE ID='test1' AND PWD ='aaaa' 뿐입니다.
BOF랑 EOF가 같다면 당연히 로긴 실패가 되는 것이고요.
회원 가입과 아바타 설정은 웹프로그래머분이 웹서버에서 받아주세요~

아, 그리고 가급적 DBMS에 질의는 생SQL문이 아니라 반드시 Stored Procedure를 써서 접근하는 습관이 중요합니다.
그런데 저는 이미 습관화 되어 있으므로 이번 예제에는 걍 생SQL문을 날렸습니다.
이는 단순히 SP가 빠르다는 이유가 아니라,
정기적으로 DBMS의 성능을 테스트(Query Profile)하는데 생SQL문을 쓰면 제대로 분석하기 힘들기 때문입니다.

2.2 ADO를 이용한 DB접근
이번 회 예제에는 가장 기본적인 형태의 ADO 클래스가 들어있습니다.
이미 다이렉트X를 날고 기는 독자분들에게 COM 컴포넌트 인터페이스 얻어오는 법은 장난일꺼라 생각되어 회원정보를 질의하는 부분만 보겠습니다.

if (S_OK == rad.RAConnect(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=..\\DB\\MyDB.mdb;")))
{
oRs = rad.RAGetDisconnectedRs(strQueryLogon.c_str());
CComVariant val;
if (oRs)
{
while (!oRs->EndOfFile)
{
// Get Name
val = oRs->Fields->Item[_variant_t(_T("NAME"))]->Value;
if (val.vt != (VT_NULL))
{
printf("NAME : %s\n",(char*)_bstr_t(val));
m_strName = (char*)_bstr_t(val);
}

// Get Avatar
val = oRs->Fields->Item[_variant_t(_T("AVATAR"))]->Value;
if (val.vt != (VT_NULL))
{
printf("AVATAR : %s\n",(char*)_bstr_t(val));
val.ChangeType( VT_I4 );
m_iAvatar = val.lVal;
}
bIsFind = TRUE;

oRs->MoveNext();
}
oRs->Release();
oRs->Close();
}
}

참 쉽죠?

ADO 연결 문자셋으로 MDB 파일에 접근한 후, Recordset 객체를 다시 만들어 SELECT의 결과값을 획득합니다.
이때 귀찮은 것이 COM 변수를 일반 변수로 변환하는 것일 겁니다.
NAME은 문자형이므로 _bstr_t를 그대로 변환하였는데 AVATAR는 INT형이라 CComVariant 에서 제공하느 ChangeType()으로 변환했습니다.
COM 변수를 변환할때는 atoi()같은 고전 함수보다 COM에서 제공하는 방법을 사용하는 것이 안전합니다.

...사실 요즘 COM 공부하시는 분들 별로 없으리라 생각됩니다.
예전에 게임 아카데미에서 COM 강의를 해보니 학생 분들 모두 전멸을 하여 아주 행복했습니다.
하지만 윈도우용 함수는 크게 WIn32 API와 COM으로 구분됩니다. SH로 시작하는 쉘함수들 역시 COM의 한 부분입니다.
닷넷 프레임워크 역시 COM과 XML의 조합입니다.
이중 디스패치 구현해가며 COM 컴포넌트를 직접 만드는건 시대에 뒤떨어지는 일이라 하더라도
기존 COM 컴포넌트를 이용하는 것이 어려우면 막강한 윈도우 OS를 반 밖에 사용하지 못하는 것이라 생각됩니다.

2.3 패킷 설계
DB와 ADO를 극복하고 가장 재밌는 부분으로 돌아왔습니다.
먼저 이 프로젝트에 사용될 패킷을 적어봅시다.

//
// MyPacket.h
//
#define MSG_LOGIN 1000
#define MSG_LOGINFAIL 1001
#define MSG_LOGINSUCC 1002
#define MSG_MESSAGE 1003

// 헤드 검출용 C, S
class CGENERIC
{
public:
DWORD head;
};

// 로긴 패킷 C->S
class CLOGIN : public CGENERIC
{
public:
char id[20];
char pwd[20];
};

// 로긴 실패 S->C
class CLOGFAIL : public CGENERIC
{
public:
};

// 로긴 성공 S->C
class CLOGSUCC : public CGENERIC
{
public:
char id[20];
DWORD avatar;
char name[20];
};

// 메시지 C->S->C
class CMESSAGE : public CGENERIC
{
public:
char id[20];
DWORD avatar;
char message[500];
};

전부 고정 패킷입니다. 아직 string이나 vector를 그래도 송수신하게 해주는 패킷 생성기를 만들지 않았으니까요.
누군가 패킷 생성기 대신 포스팅 해주실 분 없나요?
아직 패킷수도 많지 않으니까 패킷 클래스 이름에 송신용, 수신용, 알림용 네이밍 규격을 붙이지 않았습니다.

점점 포스트가 읽기 어려워지고 있습니다.

점점 포스트가 읽기 어려워지고 있습니다.

모든 패킷은 CGENERIC을 상속받고 있습니다.
일차적으로 모든 패킷은 CHAR에서 CGENERIC으로 캐스팅 되어 어떤 패킷인지를 분석하게 됩니다.
그런데 CGENERIC에 패킷 판독용 DWORD만 있고 실제 데이터 크기를 담은 정보는 없군요?
1회 포스팅 때 나갔던 소스를 보시면 CDataMessage라는 버퍼용 클래스가 있고 그것에서 앞부분 4Byte를 패킷 사이즈용으로 사용하고 있습니다. 즉, 모든 패킷은 CDataMessage로 다시 감싸는 구조로 되어있습니다.

명확한 설명을 위해 그림으로 다시 그려보죠.

CLOGIN 패킷으로 접속과 함께 로긴 정보인 ID, PWD를 보냅니다.

CLOGIN 패킷으로 접속과 함께 로긴 정보인 ID, PWD를 보냅니다.


DB 질의 결과에 따라 성공, 실패를 보냅니다. 성공시 NAME과 AVATAR를 보내며 실패면 클라이언트는 접속을 끊습니다.

DB 질의 결과에 따라 성공, 실패를 보냅니다. 성공시 NAME과 AVATAR를 보내며 실패면 클라이언트는 접속을 끊습니다.

이제 다른 클라이언트B가 접속을 합니다.

이제 다른 클라이언트B가 접속을 합니다.


누군가 접속을 성공하면 서버는 모두에게 CLOGINSUCC을 보냅니다. 이미 연결되어 있던 클라이언트는 이 정보를 누군가 입장했다고 판단합니다.

누군가 접속을 성공하면 서버는 모두에게 CLOGINSUCC을 보냅니다. 이미 연결되어 있던 클라이언트는 이 정보를 누군가 입장했다고 판단합니다.


서버는 단순히 CMESSAGE 패킷을 중계만 합니다.

서버는 단순히 CMESSAGE 패킷을 중계만 합니다.


2.4 클라이언트 구현
아래는 클라이언트의 핵심 구현부 입니다.
중요한 것은 로긴 성공과 메시지에 있어 같은 패킷을 이용하여 클라이언트에서 판정하고 있다는 것입니다.
패킷 처리 부분은 이미 서버와 클라이언트가 비슷하므로 서버는 별다른 설명이 필요 없을 것입니다.

// 일단 받은 패킷의 종류를 알아본다.
CGENERIC* pGenericPack = (CGENERIC*)szRecvData;


// 해당 패킷 처리로 따로따로 보낸다.
switch( pGenericPack->head )
{
case MSG_LOGINFAIL :
{
pMainWnd->OnCloseToServer(TRUE);
pMainWnd->AddToLog(_T("ID나 비밀번호를 체크하세요."));
}
break;

case MSG_LOGINSUCC :
{
CLOGSUCC* pLoginSucc = (CLOGSUCC *)szRecvData;
pLoginSucc->avatar;
pLoginSucc->name;
pLoginSucc->id;
CString strUserName, strID;

if(pMainWnd->m_strMyID.IsEmpty())
{
strUserName = pLoginSucc->name;
strUserName = strUserName + " 님 어서오세요.(By Server).";
pMainWnd->AddToLog(strUserName);

pMainWnd->m_iMyAvatar = pLoginSucc->avatar;
TRACE("%d\n", pMainWnd->m_iMyAvatar);

pMainWnd->m_strMyID = pLoginSucc->id;
pMainWnd->DrawMyAvatar();
}
else
{
strUserName = pLoginSucc->name;
strUserName = strUserName + " 님이 입장하셨습니다.(By Server).";
pMainWnd->AddToLog(strUserName);
}
}
break;

case MSG_MESSAGE:
{
CMESSAGE* pMessagePack= (CMESSAGE*)szRecvData;
CString strRecvMessage, strID;
strRecvMessage.Format("%s : %s", pMessagePack->id, pMessagePack->message);
strID = pMessagePack->id;

pMainWnd->AddToLog(strRecvMessage);

if ( pMainWnd->m_strID != strID)
{
pMainWnd->m_iOtherAvatar = (int)pMessagePack->avatar;
pMainWnd->DrawOtherAvatar(); // 상대 캐릭터
}

}break;



3. 인증샷, 하지만...
자, 이렇게 완성되었습니다.

덕내쩌는 클라이언트라 덕후가 아니면 받지 못함 ㅋㅋㅋㅋㅋㅋㅋ

덕내쩌는 클라이언트라 덕후가 아니면 받지 못함 ㅋㅋㅋㅋㅋㅋㅋ


이 포스팅을 읽으며 한가지 새로운 사실을 알수가 있는데,
서버에서는 별다른 연산이 없었지만 나름 아바타가 포함된 그럴싸한 채팅 시스템이 만들어졌습니다.
이는 DB라는 자료구조가 존재하기 때문이죠.
사실 게임 서버에서 타게팅, 넌타게팅, 3D 위치값 같은 게임 냄새 물씬 나는 요소는 결코 절대적인 비중을 차지 하지 않습니다.
개발자의 시선에서 게임 서버는 DBMS의 정보를 클라이언트에게 보내주고, 또한 클라이언트가 보낸 정보를 DBMS에 쌓기 위해 존재합니다.

3회만에 이 프로젝트를 포스팅 할 수 있어 무척 기쁩니다.
소스를 잘 만들었다는 이야기가 아니라, DB가 투하된 실전용 클라이언트/서버의 핵심을 선보였다는 것이며
그와 동시에 클라이언트/서버의 모든 문제점을 고스란히 알수 있는 프로젝트이기 때문입니다.

문제점이야 밤새도록 적을 수 있겠지만 우선 몇가지만 적어보죠.

4. 더 생각해볼 꺼리
오늘은 더 생각해볼 꺼리가 참 많네요.

1) 서로 채팅을 할때 NAME 대신 ID가 보여지고 있습니다. 기껏 만든 NAME을 자기만 보고 있는 셈이죠.
이를 ID와 NAME이 동시에 보여지도록 해봅시다.
또한 그렇게 할때 어떻게 하면 가장 작은 사이즈의 패킷을 보낼 수 있을까요?

2) 이 프로젝트에는 현재 치명적인 버그(?)가 있습니다!
한 클라이언트가 로긴을 실패하면 CLOGINFAIL 패킷을 받아 모든 클라이언트가 접속이 끊어지고 맙니다.
이 문제를 어떻게 해결할수 있을까요?
클라이언트에서 고치는 방법(패킷 수정 포함)과 서버에서 해결하는 방법, 각각 두가지 방법을 생각해봅시다.

3) DB 연결
현재 서버는 CLOGIN 패킷을 받을때 ADO로 DBMS에 연결과 질의, 그리고 닫기를 수행하고 있습니다.
만약 MMORPG처럼 다수의 사용자가 접속을 한다면,
아니 지금 프로젝트에서도 모든 사용자의 채팅을 서버에 저장한다면(법적인 문제를 떠나) DBMS는 뻗게 됩니다.
어떻게 하면 DBMS에게 무리를 주지 않으며 편안한 서비스를 할 수 있을까요?
단순히 DBMS 폴링도 좋은 방법이지만 그 규모조차 넘어서면 어떻게 할까요?
또한 게임 서버뿐만 아니라 웹서버에서도 사용자 정보를 갱신한다면(닉네임 변경) 어떤 문제와 해결점이 있을까요?

아, 그리고 지금 현재에도 이 프로젝트에서 DB질의 시간이 가장 많은 시간을 소모하고 있을 것입니다.

4) 서버와 월드
이 프로젝트가 인기가 좋아 동접 20만명(...)의 프로젝트가 되었다면 합시다.
그래서 서버를 늘립니다.
서버를 늘렸을때 각각 다른 서버에 있는 사용자들끼리 채팅을 하게 해야할까요?
아니면 깔끔하게 포기할까요?

전자라면 서버"들"을 어떻게 구성해야 할까요?
후자라면 그게 바로 한 월드가 되며 다른 월드의 친구와는 게임을 당연히 할수 없을 것입니다.
그럼에도 불구하고 다른 친구에게 쪽지라도 보내고 싶다는 고갱의 건의가 왔고 기획팀에서 해달라고 하면 어떻게 할까요?

5) 지난 시간 소개해드린 WireShark로 보면 ID와 PWD는 그대로 드러납니다.
오픈하자마자 중국계 IP들의 놀이터가 되겠군요.
웹에서 로긴이 아닌 게임에서 로긴이라면 어떤 방식으로 숨겨야 할까요?

1), 2)는 네트워크 공부를 처음하는 분이라도 해결할수 있는 부분이고
나머지는 현업을 준비하는 분들에게 알맞은 토픽입니다.

이것으로 이번 포스팅을 마치도록 하겠습니다.
늦어져서 다시 한번 죄송하고요, 이번 포스팅의 서버에서는 ADO 질의 이외에는 일체의 로직이 없었습니다.
다음 시간에는 서버에 로직과 자료구조를 투척해보겠습니다. 바로 게임으로 들어가는 관문인 로비(Lobby)를 만들어볼까 합니다.

언젠간 이런 날이... .

언젠간 이런 날이... .

내용은 맘대로 퍼갈수 있지만 동의없는 수정은 안되며 출처(http://www.gamedevforever.com/ , http://rhea.pe.kr/ )를 명시해주세요.

프로젝트 다운로드 : http://rhea.pe.kr/attachment/cfile22.uf@1272AD3A4F32B534061400.zip

댓글을 달아 주세요

  1. Favicon of http://gamedevforever.com Rhea Strike 2012.02.09 05:25 신고  댓글주소  수정/삭제  댓글쓰기

    한동안 가스비 지로용지가 안날라온다고 했더니,
    오늘 56만원이 날라왔습니다.
    동기형 batch 프로세스의 잔인함을 보여주는 사례라 생각됩니다.
    현물로 위로해주세요... .
    혹은 접대비 항목으로 법인카드 긁어주세요~

  2. Favicon of http://gamedevforever.com 죠쉬 2012.02.09 10:43 신고  댓글주소  수정/삭제  댓글쓰기

    에에에에... 답을 달고 싶은데...
    이번 회의 문제는 출제 의도를 모르겠거나
    전혀 경험이 없는 분야라...

    (답을 달고시퍼 달고시퍼 달고시퍼~~~~)

    특히 4번의 '다른 서버로 메시지 전달'이 매우 궁금합니다.
    답이 뭔가영???

    그리고, 네기마 카드 이미지 파일좀 얻을 수 없을까영? (응? 더쿠 인증 한건가?)

    • Favicon of http://rhea.pe.kr/ Rhea 2012.02.09 11:07 신고  댓글주소  수정/삭제

      3), 4)는 본격 분산서버에 대한 떡밥입니다. 서버끼리 통신해야죠. :-)
      아마 그거 이야기는 튜터리얼 편이 끝나고이지 않을까 합니다.

      네기마 카드는 저도 없어요, 딱 저만한 쫴끄만한 이미지여요. 그것도 퀄엉망.

  3. Favicon of http://bluekms21.blog.me 크로스 2012.02.09 11:13 신고  댓글주소  수정/삭제  댓글쓰기

    이번에도 좋은 글 감사드립니다~!
    그런데 C++코드를 올리실때 http://bluekms21.blog.me/10131355275 이런걸 써보시는건 어떠신지요?
    자신있는 DBMS라.. 전 사실 윈7 초반에 SQL Server를 깔려다 대 실패한 뒤로 mySQL을 쓰고있는데
    예제는 엑세스DB로 되어있군요.. 이력서에 엑세스DB로 적어도 되는걸까 싶네요.. ㅇ<-<


    그냥 생각해 본 대답들입니다...
    부끄럽고요;; 틀렸으면 누가 보시고 비웃지만 마시고 알려주시면서 비웃어주세요.. ㅠ_ㅠ;;

    1) 체팅을 시도한 클라이언트의 키값인 ID만 입력받아
    NAME는 DB에서 SELECE 해서 띄워주는 방법을 생각해 봤는데...
    느릴거같네요..? 혹시 다른 방법이 있으시면 가르쳐 주시면 좋겠습니다;;

    2) [클라에서 고치는 방법]
    - 로그인 성공 시 플레그를 설정하여 CLOGINFAIL을 받아도 끊어지지 않게 한다
    [서버에서 고치는 방법]
    - 로그인 실패 시 접속 시도한 소켓에게만 CLOGINFAIL을 전송한다
    전송되는 페킷의 양을 생각했을 때 서버에서 고치는 방법이 나을것 같네요?

    3) 일단 폴링에 대해 검색해봤습니다만...
    클라이언트에서 질의를 날리고 DBMS는 응답만 한다. 는것 같네요. 일단 이것도 해 놓고
    로그인 전용 로비를 따로 만드는것으로 해결되지 않을까 싶습니다.

    4) 깔끔하게 포기합니다
    대신 기획자의 강렬한 열망이 느껴질 경우 해당 아이템을 '케쉬템'으로 팔아서 서버의 부하를 줄입시다.
    아마도 경영진도 좋아할 것입니다. 하핫;;;
    전자라면 역시 체팅이나 쪽지 전용 서버를 구축하여 전체 메시지는 별도로 처리하는게 좋을것 같습니다.

    5) 페킷을 암호화해서 전송하면 될것 같습니다...만
    사실 제가 암호화나 보안 방식에 대해서는 많이 부족합니다;;
    그냥 게임가드같은거 쓰면 안될까? 싶기도 하고요;;
    이 글에 보안방식은 범위 밖이겠지만 다른 훌륭하신 분들이 언젠간 강의해주실거라 믿습니다!

    추신 : 일단 나갔다 온 뒤 이 좋은글을 제 블로그로 모셔가겠습니다.. 하핫;;
    언제나 좋은 글 감사합니다.

  4. Favicon of http://bluekms21.blog.me 크로스 2012.02.09 11:36 신고  댓글주소  수정/삭제  댓글쓰기

    그런데.. 글쓰신 Rhea君님과 Rhea님은 동일인물 이시죠??

  5. 하늘향기 2012.02.09 14:37 신고  댓글주소  수정/삭제  댓글쓰기

    매번 좋은 글(숙제) 올려주셔서 감사합니다 :)

    • Favicon of http://gamedevforever.com Rhea Strike 2012.02.09 16:43 신고  댓글주소  수정/삭제

      ASSERT(1 == sizeof(RHEA'S_HEART));

      글로만 보는 감사는 사양합니다.
      간혹 "그냥 댓가없이 많은 사람이 봐주셨으면 하는걸요~"라고 하시는 분들이 있는데,
      그거슨 "져도 괜찮아, 출전에 의미가 있는거야..."하는 것과 같습니다.

      저는,
      향응! 향응! 향응! 향응!
      향응! 향응! 향응! 향응!
      향응! 향응! 향응! 향응!
      향응! 향응! 향응! 향응!
      누나/여동생을 바쳐라!!
      을 원합니다.

    • Favicon of http://gamedevforever.com 죠쉬 2012.02.09 17:31 신고  댓글주소  수정/삭제

      웃흥~
      울 누님이 82 학번이신데... 괜찮으신가요?
      거부하시려면
      제게 향응을 제공하셔야 할겁니다.
      냐하하하하하~~~~!!!!

    • 하늘향기 2012.02.18 12:48 신고  댓글주소  수정/삭제

      ㅠㅠ 누나를 바치고 싶어도... 4분 다.. 임자 있는몸이라서 ㅠㅠ

  6. Favicon of http://alucardkang.tistory.com SanAh Kang 2012.02.09 17:03 신고  댓글주소  수정/삭제  댓글쓰기

    아아 좋군요! 하지만 회는 무리입니다! ㅋㅋ

    책은.. 출판사랑 최종 수정본 왔다갔다 하고 있습니다.ㅎㅎ

    SQL Server Express Edition 같은 무료 버전을 학습용으로 사용하면 그만입니다. ㅋ

    게임 개발에 들어가는 db설계, 최적화 이슈는 사실 그리 많지는 않습니다만 최적화를 위해 공부해야 하는 부분이 워낙 광범위하고 깊이 들어가야 하는지라 세미나 등으로 알려드리기엔 터무니 없이 시간이 부족해버립니다.
    *Index 설명에 8시간 정도 걸린다거나... ㅡㅅ ㅡ;;

  7. 오메가 2012.02.09 19:12 신고  댓글주소  수정/삭제  댓글쓰기

    재밌는 떡밥을 던져주셔서 감사합니다.

    생각해 볼 거리의 3, 4번에 대한 대답이 "우리도 걍 NoSQL로 개발해~ NoSQL로 뒤짚어~~" 가 아닌가 싶습니다.

    게임에서 이용되는 데이터 중에서 채팅과 같이 ACID가 요구되지 않으며 부하가 큰 부분이나 웹서버와 공유해야 할 부분을 NoSQL에서 처리하는 것도 한 가지 방법이 될 수 있을 것 같구요,
    트랜잭션 처리 등의 모델은 언급하신 MongoDB나 Redis, Memchached 같은 속도와 스케일링 위주의 Key-Value 개념의 NoSQL 대신 Cassandra나 HBase 등의 진화된(?) DB를 이용하면 좀 더 편하게 처리할 수 있을 것 같네요.
    실제로 Facebook도 메시지 시스템을 HBase 위에 얹어놨는데 써 보신 분들은 아시겠지만 거의 실시간입니다. (http://www.facebook.com/note.php?note_id=454991608919)


    지나가다 답변에 불타오른 김에 5번도 질러보자면,
    일단 로그인 과정이나 개인정보 전송 등에만 부분적으로 SSL을 이용한다는 원론적이면서도 대책 없는 대답 하나랑
    패스워드 전송에 있어서는 뜬금없이 떠오른 방법으로...
    1. 서버가 클라이언트에 SALT로 쓸 문자열을 보낸다.(SALT는 매번 랜덤하게 바뀌어야 하구요)
    2. 클라이언트는 패스워드의 해시에 SALT를 붙인 다음 해싱해서 서버로 로그인을 시도한다.
    3. 서버는 <1에서 보냈던 SALT 값을 DB의 패스워드 해시에 붙여 다시 해싱한 결과>와 <2의 결과>를 비교하여 로그인 시켜준다.
    를 한 번 던져 봅니다.

  8. Favicon of http://bluekms21.blog.me 크로스 2012.02.10 23:22 신고  댓글주소  수정/삭제  댓글쓰기

    http://bluekms21.blog.me/10131514869 로 퍼갔습니다. 출처 명시 확실히 했구요...
    너무 좋은 글이라 본문을 소장하고 싶어서 시작한 일인데 사람들이 저를 오덕으로 봅니다. 어쩌죠?

  9. Favicon of http://gamedevforever.com 김포프 2012.02.17 07:44 신고  댓글주소  수정/삭제  댓글쓰기

    이번엔 다리가 매우 맘에 듭니다 -_-;

  10. 황금나무 2012.02.17 11:51 신고  댓글주소  수정/삭제  댓글쓰기

    정말 재미있게 보고 있습니다.
    책 많이 보고 헤딩해야 알수있는 내용들이 담겨있네요.
    저도 본문을 퍼가고 싶지만... 음 친구들이 어떻게 볼지.

  11. Favicon of http://mythinking.ba.ro 우리 2015.12.01 21:08 신고  댓글주소  수정/삭제  댓글쓰기

    구글링하다가 이 블로그에 오게되었습니다. 강좌도 잘 보고있구요. 혹시 게임서버 구동을 위한 서버팩구축에 대해서만 다룬 강좌도있나요? 와이어샤크로 현존게임서버의 패킷분석과 서버팩 제작간의 연관성만을 자세히 다룬 강좌가 있나해서 댓글달아봅니다.



티스토리 툴바