프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 디퍼드H

안녕하세요? 디퍼드H 입니다. 혹시 저의 강의를 기다리신 분 있나요? (없진 않겠죠? ㅡ.ㅡa) 갑작스런 싱가폴 친구들의 등장과 함께, 남의 집에서 얹혀살기(무지 불편했다는...), 이사까지...(조만간 다시 이사를 해야하는 실정입니다. 뭔가 복~~잡한 사연으로 인해) 여러일들 때문에 강의가 늦게 올라오고, 늦게 올라온 것도 모자라, 내용이 많이 부족하거나 적을 수도 있는 사연을 이해.. 이해 해주길 바라면서, 강의를 시작해보죠.

사실 저번 강의를 올리면서, 많은 고민을 했었습니다. 그 고민의 이유는 바로 메세지 시스템인데요. 사실 메세지 시스템은 저의 강의 가장 핵심적인 부분이기도합니다. 원래, 엔진을 처음 만드시는 분들 또, 학생(막 게임 프로그래밍에 접하신분들)을 위해서 강의를 하기에는 바로 메세지 시스템을 설명하기에는 조금 무리가 있다고 판단을 했거든요. 헌데, 예상외로 메세지 시스템에 대해 많이 궁금하신분들이 많아, 이번 강의는 메세지 시스템에 대해서 한번 짚고 넘어가고자 합니다.  물론 학생 분들이나 엔진을 처음 만드시는 분들은 아, 대충 이런 이야기이구나! 하고 넘어가더라도, 문제가 없을 겁니다. 왜냐? 시간이 지나서 다시 다룰거거든요. 전체적으로, 심도 있는듯 없는듯 한번 저의 메세지 시스템에 대해 한번 보도록 하죠.

제가 메세지 시스템을 만들때, 보통 롤 모델이 필요했습니다. 어떻게 만들어야 가장 효과적일까? 그렇게 생각하다보니 제일 먼저 떠오르는것이 우체국시스템이더군요. 우체국을 모르시는 분들은 없을거라 생각합니다. 우체국의 시스템은 오랫동안 아직도 유지되어 오고 있습니다. 이것은 바로, 그 시스템이 효과적이다라는 의미이겠죠. 이렇게 생각하면서 저는 메세지 시스템의 롤 모델은 우체국에서 이용되는 시스템(편지겠죠.) 정하고 메세지 시스템을 설계했었습니다. (사실 저 같은경우 어떠한 시스템이라던가 그외 필요한 것을 구현할때에는 보통 주위를 많이 이용하는 편입니다. 크게 많이 도움이 되더군요.) 우리가 보통 편지를 보내고 또, 다른사람에 받는데 까지에는 다음과 같은 방법이 이용됩니다. 우선 우린 편지를 씁니다.(편지를 쓸때에는 보내는사람, 받는사람, 주소, 그리고 내용이 들어가죠.) 편지는 편지통으로 들어가고, 그 편지는 우체국으로 모입니다. 우체국에서는 이편지를 주소에 따라 편지를 배정하고, 마침내 편지는 받는사람에게 가죠. 설마, 이렇게 편지가 여러분들께 가는것은 모르는 사람들은 없겠죠? (있다면 큰일입니다!) 이제 이 시스템을 우리가 구현할 메세지 시스템에 알맞게 바꾸어나가보도록 하죠. 우선 아래의 그림을 봅시다.

 

모든걸 다 넣으려고 하니, 그림이.. 크군요. 아무튼, 위의 그림을 보시면 이상한 클래스 이름들이 눈에 띕니다. 메세지 매니저 뭐 이름 그대로 아주 직관적이라 메세지를 처리하는곳이구나 라는게 감이 오지만 ISociable 클래스는 무엇인가? 라는 의문점이 생깁니다. 제가 메세지 시스템을 구현할 때, 정말 알맞은 변수명을 찾으려고 고생을 했는데 나온것이 ISociable 이었습니다. 우리 이전에 말했던 우체국 시스템(자꾸 우체국 시스템하니 좀 많이 어색한 것 같군요. 정말로 어색하지만 양해 부탁드립니다)을 이용해서 말한다면 주소 등록본(?) 아니 주민등록본(?) 과 비슷한 메세지(편지)를 서로 주고 받을 수 있도록 해주는 클래스라고 생각하시면되겠습니다. 편지를 주고 받는다 = 대화를 한다 -> 사회적이군! 이라는 결론으로 ISociable라고 지었는데, 개인적인 의견으로는 뭐 알맞다고 생각합니다(사실 멋지다고 생각한다는...)  이 클래스에는 메세지와 관련된 메소드와 변수를 가지고 있습니다.

 

프로그래머는 역시 코드로 보는게, 바로 뙇(요즘 이게 대세더군요) 감이 오실겁니다. 이전에 설명한 내용이라 넘어가도록 하죠. 다음은 ISociable을 관리하는 객체인 ISociableManager가 있습니다. 우체국으로 생각한다면, 우체국의 중요부서중 하나라고 생각하시면됩니다. 나머지 하나는 물론 메세지 매니저죠. ISociableManager와 MessageManager의 상호작용으로 우체국의 역활인 메세지를 받아 저장하고, 매 프레임 마다 메세지를 Dispatch를 한다고 보시면 됩니다.  ISociableManager는 메세지를 Dispatch하는 역활을 맡고 있고, MessageManager는 메세지를 메세지 큐에 매 프레임마다 들어오는것을 보관하고 관리를 합니다. 우선 아래의 그림을 보도록 하죠.

 

위 그림은 그래픽 시스템에서 다이렉트x의 초기화를 위해 윈도우 값이 필요해, 윈도우 핸들값을 메세지를 요구할 경우를 가정해서 관계도를 나름 멋지게(?)그려보았습니다. 사실 그림과 간단하게 붙어있는 설명들을 읽으시면, 뙇 어떻게 MessageManager와 ISociableManager 상호작용을 해서 메세지 시스템이 구현되는지 한눈에 아실거라 생각이 들지만, 그렇지 않을 분들을 위해 설명을 시작하도록하죠. 이 예시만 이해가 되신다면, 여러분도 여러분만의 메세지 시스템 구현을 위한 준비가 되었다고 봐도 될 것입니다.

우선 윈도우 시스템과 그래픽 시스템은 ISociable클래스를 상속받아, 메세지 주고 받을 수 있습니다.(코드적으로 설명하자면, 윈도우 시스템과 그래픽 시스템은 RecvMessage 메소드를 들고 있고, ISociableManager에 등록도 되어 있다는 말이겠죠?) 윈도우 시스템에서는 메세지를 우선 메세지 매니저로 메세지를 보냅니다.  메세지 매니저는 그 메세지를 매니저가 가지고 있는 메세지 큐에 넣습니다. 다음 프레임에 메세지 매니저에서는 메세지가 Dispatch 되어야하는지 우선 확인을 합니다. 후일 메세지 시스템 구현 부분에서 자세하게 다루게 되겠지만, 메세지 클래스는 여러가지 멤버 변수들을 가지고 있습니다. 그 중 하나인, DelayTime의 멤버변수는 언제 메세지가 Dispatch되어야하는가를 가리키는 변수명입니다. 만약 DelayTime이 1.0f의 값을 가지고있다면 1초 후에 이 메세지를 Dispatch해야 한다는 것을 의미합니다. 게임 엔진이 60fps로 돌아간다고 가정했을때, 이 메세지는 약 60프레임 이후 메세지가 Dispatch 된다는 것을 의미합니다. 메세지 시스템에서는 매 프레임마다 이 변수의 값에서 -0.166666f 값을 빼주면서 0 이하가 된다면 이 메세지는 처리되어집니다. 메세지 처리가 준비되었을때, 메세지 시스템에서는 DispatchMessage 메소드를 실행시키기 시작합니다. 이 메소드는 메세지에서 수신자의 id혹은 이름을 꺼내서 ISociableManager에 등록되어있는 ISociable객체를 찾아서 RecvMessage 함수를 실행시킵니다. 예시로 돌아가서, 메세지에서는 수신자가 WindowSystem으로 되어 있었습니다. 현재 윈도우 시스템은 ISociableManager에 등록되어 있고 결국 메세지 매니저에서는 윈도우 시스템에서 구현된 RecvMessage 함수를 실행시키고 이 함수내에서 윈도우 핸들을 달라는 메세지에 알맞는 행동이 구현되어 있을 것입니다.  그럼 윈도우 시스템은 아마 윈도우 핸들 값을 동봉한 메세지를 날려주겠죠?(데이터를 어떻게 동봉하는가?는 후일 구현부분에서 다룰것입니다.)

지금까지 여러분들과 함께 메세지 시스템은 어떻게 만들것인가? 만들어지는가? 에 대해서 확인해보았는데요. 오늘은 자세한 듯하면서, 또 어찌보면 아닌듯이 알아보았습니다. 어떤분들은 지금까지의 내용으로도 충분히 여러분만의 메세지 시스템을 만들 수 있다고 생각이 듭니다. 여러분들은 충분히 할 수 있습니다! 이번강의에서 일부러 메세지 클래스를 어떻게 만드는건가? 또 MessageManager와 ISociableManager 구현과 팁은 포함시키지 않았습니다. 이 내용은 후일 강의를 진행해 나가면서, 때가 되면 다루어 보도록 하겠습니다. (많은 댓글과 열혈한 성원은 강의 진행에 무지 도움이 되어 메세지 시스템 구현 강의가 빨리 진행될 것을... 알려드립니다 ~ ㅋ^^) 사실 오늘 넘 정신이 없다보니 중간중간 여러분들이 이해 안되는 부분이 있을 수 있을거라 생각이 (엄청) 듭니다. 여러분들 중 이해가 안되거나 궁금한 내용은 댓글로 남겨주신다면 최대한 성실히 답변해드리도록 하겠습니다.

 

댓글을 달아 주세요

  1. 오로나(flyingcode) 2012.06.04 21:10  댓글주소  수정/삭제  댓글쓰기

    ㅎㅎ 잘 읽었습니다.

    다음 연재 기대 할게요 ^^

  2. 익티크 2012.06.05 00:19  댓글주소  수정/삭제  댓글쓰기

    글을 읽다가 의문점이 생겨서 댓글을 남깁니다.

    1. 어떤 객체를 ISociableManager에 등록시킬 건지는 객체를 디자인 한사람이 정하는 건가요? 아니면 무조건적으로 등록이 되는것인가요?

    2. 사실 제일 궁금한것은 메시지 처리 방식입니다. Switch case가 아닌 멋드러지고 효율적인 방법을 기대해도 괜찮을까요?

    • Favicon of https://gamedevforever.com 디퍼드H 2012.06.05 03:00 신고  댓글주소  수정/삭제

      답변 드릴게요~ 전 궁금한걸 질문하는 사람이 젤 좋더군요. 부족한 강의를 열심히 읽어주셨다는 것이기 때문에 ~^^ 암튼 질문하신 답변은 아래와 같습니다.
      1. 등록시킬건가, 안시킬건가는 프로그래머 디자인하는사람의 마음입니다. 주소 등록은 해놓지만 편지는 안받을 수 있듯이 말입니다. 혹, 그렇게 하고 싶다면, ISociable클래스를 상속받는 객체이더라고, ISociableManager클래스에다가 따로 등록 또는 해제 메소드를 따로 선언해놓게 직접 해준다면 상관없겠죠? (물론 이럴때, observer pattern을 써준다면, 더 좋을수도 있겠죠?)

      2. 간드러지고, 효율적인 방법 기대해도 좋습니다. 제가 생각하기에는 최대한 상속을 배제하여 만들었기 때문에 다가올 강의를 기대해주세요.

    • 이재원 2012.07.22 08:13  댓글주소  수정/삭제

      저도 궁금한게 있는데여
      메시지를 switch case로 하면
      그 어느방법보다 가독성이 뛰어나다고 생각되거든여
      굳이 switch statement를 안써야되는 이유는 있나요?
      개인적인 경험으론
      어떤 방식으로 처리하더라도 어딘가 숨겨진 부분에서
      switch를 쓰게되는데 그저 눈에 보이지 않을뿐이었거든여
      굳이 복잡하게 할필요없지 않나요?

  3. 익티크 2012.06.05 07:33  댓글주소  수정/삭제  댓글쓰기

    출근하기 전에 샤워하면서 갑자기 의문이 들어서 급 컴터 켜서 댓글을 남깁니다.

    프레임당 1번의 디스패치가 이루어지는건가요?
    이런 질문을 드리는이유가 요청했을때 다음 프레임이 아닌 그 프레임에 요청 결과를 받고 싶은 경우때문에 그렇습니다.

    • Favicon of https://gamedevforever.com 디퍼드H 2012.06.05 15:38 신고  댓글주소  수정/삭제

      예 맞습니다. 프레임당 한번 디스패치가 일어나는겁니다. 메세지 매니저에서 프레임당 한번 업데이트, 디스패치는 하는겁니다. 메세지 업데이트 순서에 따라 그다음 프레임이라고 할 수 있고 또 아닐수도 있습니다. 예로 들어 익티크님께서 메세지 매니저 업데이트 함수를 맨처음으로 두었을경우 그래픽 시스템에서 보낸 메세지는 그다음 프레임에 디스패치가 되지만, 업데이트 함수를 맨 뒤로 놓았을경우, 그 프레임에 디스패치가 되지 때문입니다. 보통 메세지 디스패치 되는 시각은 위글에서 설명했듯이 elapseTime 혹 Delaytime이라는 변수로 결정되는데 이 변수들을 0.0f로 지정해 놓는다면 최대한 빠른 프레임에 메세지가 디스패치 될 것입니다.
      또 궁금한거 있으시면 댓글 남겨주세요! 언제든 환영입니다.~^^

  4. Favicon of https://jenemia.tistory.com 제네미아 2012.06.06 12:34 신고  댓글주소  수정/삭제  댓글쓰기

    안녕하세요, 허접 게임 개발자 지망생 학생인데 질문 남겨볼께요!

    처음 읽을 땐 이해가 안되서, 두번 째 읽을 때 생각이 든게,
    제가 얼마전에 소켓 프로그래밍을 처음 접해서 서버와 클라이언트간에 패킷을 주고 받은 것을 코딩한적 있었습니다.
    패킷에는 게임에 필요한 객체 리스트들(적,타워 등)과 클라이언트 id 등이 들어있어, 서버에서는 이를 분간하여 클라이언트에게 보내고,
    각 클라이언트들은 그것들을 받아 처리를 하는 구조였습니다.(2인용 디펜스 게임을 위해..)
    아무튼,
    제 질문은 메세지 시스템과 소켓 시스템(제가 위에서 언급한 구조?)의 차이가 무엇일까요 ??

    • Favicon of https://gamedevforever.com 디퍼드H 2012.06.06 16:04 신고  댓글주소  수정/삭제

      네 안녕하세요. 제네미아님.
      제가 보기에는 소켓 프로그래밍과 메세지 시스템과 크게 다르지 않다고 보여집니다. 다만 한가지 결정적 차이점이 있다면, 소켓 프로그래밍에서는 패킷을 외부적으로 주고 받는가 하면, 메세지 시스템은 한 어플리케이션에서 즉 한개의 프로그램 동일한 메모리를 이용한 데이터 교환인 것입니다. 소켓 프로그래밍에서는 데이터를 주고 받을때 따로 serialize를 한 다음, 데이터를 직접적으로 주고 받는가 하면, 메세지 시스템에서 큰 데이터를 받을경우 void*를 선언해 줘서 동일상 메모리를 추적해 다시 알맞을 타입변환을 해서 클래스와 같은 큰 데이터를 받을 수 있게 됩니다. 자세한 내용은 다음에 다시 다룰 메세지 시스템을 기대해주세요. 멋지게 다룰 예정입니다( 사실입니다!) ~^^

    • 이재원 2012.07.22 08:19  댓글주소  수정/삭제

      네트워크 게임을 만들어본적이 있는데여..
      서버-클라이언트간의 통신은 클라이언트에서
      인풋을 서버로 보내주고
      서버에서는 그 인풋을 통해 모든 연산을 한뒤
      화면에 뭘 그려라! 이런식으로 만들었었던거 같은데
      음 위 내용은 서버에서만 사용하면
      네트워크게임 메시지시스템이랑 같지 않은가여?

  5. Favicon of http://fegs.kr FeGs 2012.06.11 12:31  댓글주소  수정/삭제  댓글쓰기

    ㅎㅎ 잘 읽었습니다! 아직 잘 모르겠지만, 모르는 상태에서 간단히 구현을 해보고 이후의 강좌의 내용과 비교해봐야겠군요!

  6. 가배향내 2013.03.06 13:41  댓글주소  수정/삭제  댓글쓰기

    연재 더 보고싶어요.ㅠㅠ