꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 친절한티스

연재화 되고 있는 WPF 글입니다. 원래 연재할 생각은 없었는데... DX11도 해야하는데... WPF만 잡고 있네요. DX11은 다른 능력자 분이 연재 해주시겠죠? 아마 풍풍풍님이 해주실거야...


게임을 제작하게 되면 게임에 등장하는 여러 오브젝트들을 만들게 됩니다. 그런데 이 오브젝트들은 많은 속성 값을 가지게 됩니다. 위치라든가, 크기, 속도, 텍스쳐는 어느 것을 쓰는지, 이 객체에 쓰일 이펙트는 어떤 것인지 같은 것 말입니다. 보통 이런 속성 값들은 툴을 이용해 제어하게 됩니다. 그런데, 이 속성 값들을 지정해주기 위해서는 입력 필드가 필요하겠지요?


윈폼이나 WPF에서는 체크박스, 텍스트박스 같은 기본 컨트롤등이 제공되고 있습니다. 이 컨트롤들을 이용해 위에서 말한 속성 값들을 정의 할 수 있습니다. 하지만 많은 수의 속성 값들을 제어 하기에는 역부족입니다. 각각의 오브젝트들이 같은 속성 값을 가지고 있는 것도 아니고, 오브젝트 종류에 따라 많게는 수십가지의 속성 값을 필요로 하는데 이 많은 속성 값들을 위한 입력 필드들을 재구성하고, 추가하는 것을 만들라 하면 누구라도 멘붕이 올 것입니다.


벌써 부터 하기 싫어진다...


수많은 속성 값들을 손쉽게 제어할수 있는 컨트롤이 있으면 어떨까요? 게다가 제작도 간편해야 합니다. 툴을 만들때 딱! 하니 뙇! 하고 나와주면 얼마나 좋겠습니까? 그런데 그게 실제로 존재합니다.


ㅋㅋㅋㅋ


그게 무엇인지 알아보기 전에 다른 이름 있는 게임 엔진 툴들은 이것을 어떻게 처리 하고 있는지 한번 살펴 보죠.






내노라 하는 게임 엔진들을 보면 항상 보이는 놈이있죠. 직접 툴을 만들어 보시면서 사용해보신 분들도 계실겁니다. 바로 프로퍼티 그리드 ( Property Grid )죠. 이 프로퍼티 그리드는 그 이름 답게 수많은 속성 값들을 제어할수 있게 도와주는 아주 유용한 컨트롤입니다. 특히 이 프로퍼티 그리드가 유용한 이유 중 하나가 바로 다양한 타입의 값들을 제어 할수 있다는 것입니다.


툴에서 사용되는 많은 속성 값들은 타입이 제각각 입니다. 단순 불린 ( Boolean ) 타입 부터 정수, 실수는 물론이고, Point, Vector3/4, 16진수 컬러값까지 다양한 값들이 존재합니다. 프로퍼티 그리드는 이런 다양한 타입들을 한 곳에서 제어할수 있는 수단을 제공해주죠. 불린은 체크박스 형태로, 스핀 컨트롤로 정교한 실수값 설정, 브러시 컨트롤을 이용한 색 추출, 그리고 포인트나 벡터 같이 동시에 다수의 값들이 필요한 타입까지도 말이지요.


좋습니다. 그렇다면 어떻게 해야 이 프로퍼티 그리드라는 놈을 내가 만드는 툴에 뙇~ 하고 넣을 수 있을까요? 안타깝게도 이 프로퍼티 그리드라는 놈은 WPF에서 기본으로 제공해주는 컨트롤이 아닙니다.


이런 고자 같은 WPF 같으니...


그렇다면 어떻게 WPF에서 프로퍼티 그리드를 사용해야 하는가? 고맙게도 이미 많은 능력자 분들께서 WPF에서 프로퍼티 그리드를 사용할수 있게 만들어 공개해두셨습니다. MS도 참 웃긴게 비쥬얼 스튜디오 Visual Studio 에서도 사용 되는 컨트롤을 왜 기본으로 제공 안해주는지 모르겠습니다(블렌드 Blend 같은 툴 팔아먹으려고 그러는 것 같아요).


일단 제가 찾아서 사용해본 몇몇 프로퍼티 그리드등이 있는데, 각각 구현 방식도 다르고, 비쥬얼도 다르지만 가장 제대로 작동하고, 사용하기 쉬웠던 것은 Jaime Olivares 라는 분이 만드신 Native WPF 4 PropertyGrid 였습니다.



프로퍼티 그리드를 사용하기 위해서는 먼저 C#의 프로퍼티에 대해 알아야합니다. 이 프로퍼티 기능은 C++ 식으로 말하면 일종의 Getter/Setter 인터페이스라고 할수 있습니다. 소스를 보시면 쉽게 이해 되실 겁니다.

public class Person
{
    public enum Gender { Male, Female }

    private string m_strName;
    private int m_iAge;
    private Gender m_eGender;

    public Person()
    {
        m_strName = "친절한티스";
        m_iAge = 21;
        m_eGender = Gender.Male;
    }

    public string nameProp
    {
        set { m_strName = value; }
        get { return m_strName; }
    }

    public int ageProp
    {
        set { m_iAge = value; }
        get { return m_iAge; }
    }

    public Gender genderProp
    {
        set { m_eGender = value; }
        get { return m_eGender; }
    }
}

멤버 변수는 private 으로 설정 되어있고, 그 멤버 변수에 대한 nameProp, ageProp, genderProp 프로퍼티들이 선언 되어있습니다. 외부에서 멤버 변수의 값을 쓰거나 읽을때 이 프로퍼티들을 이용하게 되죠.

Person prop = new Person();
prop.nameProp = "김포프";
prop.ageProp = 22;
prop.genderProp = Person.Gender.Female;

...이렇게 말이죠.


갑자기 C#의 프로퍼티 기능에 대해서는 왜 말하는 거지? 하고 의아해 하실 수 있는데, 프로퍼티 그리드가 바로 이 프로퍼티 기능을 이용하기 때문입니다. 게다가 무려 프로퍼티를 선언해 두면 프로퍼티 그리드에서 알아서 컨트롤에 생성을 해줍니다!!!!!!!


그렇다면 정말로 프로퍼티 그리드에 위의 속성값들이 나오는지 만들어보겠습니다. 두큰두큰~ 위에서 받은 WpfPropertyGrid.cs 파일을 프로젝트에 추가 해주고 아래 그림과 같이 프로젝트에 참조를 추가 해줍니다.



그리고 프로퍼티 그리드를 추가할 윈도우 xaml 파일을 열어 아래와 같이 추가해줍니다.



이제 프로퍼티 그리드에 표시해줄 속성 값을 가지고 있는 오브젝트를 생성해서 적용해주면 됩니다.

public MainWindow()
{
    InitializeComponent();

    Person prop = new Person();
    prop.nameProp = "김포프";
    prop.ageProp = 22;
    prop.genderProp = Person.Gender.Female;

    // 프로퍼티 그리드에 적용
    propertyGrid1.SelectedObject = prop;
}

끝입니다. 참쉽죠? 정말 제대로 나올까요? 한번 실행해보겠습니다.



22살의 아리따리운 미소녀 김포프 프로퍼티 그리드가 나타났습니다. 우왕~ 그런데 좀 이상하군요. 카테고리 분류도 없고, 속성값 이름도 프로퍼티 이름이 그대로 나옵니다. 다른 엔진 툴에서 사용되는 프로퍼티 그리드를 보면 카테고리도 잘 분류되어있고, 속성값 이름들도 그럴싸하게 명명되어 있는데 말이죠. 이를 바꿔주기 위해서는 C#의 Attributes를 이용해주어야 합니다.

public class Person
{
    public enum Gender { Male, Female }

    private string m_strName;
    private int m_iAge;
    private Gender m_eGender;

    public Person()
    {
        m_strName = "박기헌";
        m_iAge = 31;
        m_eGender = Gender.Male;
    }

    [Category("인적사항")]
    [DisplayName("이름")]
    public string nameProp
    {
        set { m_strName = value; }
        get { return m_strName; }
    }

    [Category("인적사항")]
    [DisplayName("나이")]
    public int ageProp
    {
        set { m_iAge = value; }
        get { return m_iAge; }
    }

    [Category("기타등등")]
    [DisplayName("성별")]
    public Gender genderProp
    {
        set { m_eGender = value; }
        get { return m_eGender; }
    }
}

Category와 DisplayName Attributes를 추가 하였습니다. 어떻게 바뀌었을까요?



카테고리가 생겼고, 속성 값명도 지정해준대로 잘 나옵니다. 짝짝짝~~

...계속


( 예상보다 내용이 너무 길어져서... 상하로 나눠서 써야 할것 같군요. 진짜 연재가 되어버렸네... )

반응형
,
Posted by 알 수 없는 사용자

꽤 오래 전에 본 글인데, 컷씬 관련한 기획 관련 요소를 정리하다가 생각나 검색해 찾았습니다. 기획보다는 게임개발 영역 모두가 참조할만한 내용이 많다고 생각되어 공유해 봅니다. (컷씬 관련한 기획 요소 정리는 추후 포스팅할 '게임개발에서의 스토리 혹은 내러티브' 편에 추가해 다루겠습니다.) 번역글이라고 여기 올리면 안되는건 아니겠죠;;;;

 

원문 출처 : http://www.gamasutra.com/view/feature/3868/shoot_to_thrill_biosensory_.php

번역문 출처 : http://blog.naver.com/nail9s/140067768882

 


Shoot to Thrill: Bio-Sensory Reactions to 3D Shooting Games

스릴을 쏴라 : 3D슈팅 게임을 하는 동안에 생체 감각기관의 리액션

 

플레이어의 리액션을 어떻게 측정할 것인가? 원래 게임 디벨로퍼 매거진에서 출판되었던 이 기사에서는 엠센스라는 회사가 뇌파와 심장 박동 그리고 심지어 눈의 깜박임을 측정하여 하프라이프2에서부터 기어즈 오브 워 까지의 게임을 플레이하는 유저들의 리액션을 측정하는 방법을 보여준다.

 

2007년에 엑박360이 플레이스테이션3 WII보다 일년 일찍 발매되면서 차세대의 시대가 활짝 열렸다.  그리고 곧이어 플레이스테이션3 Wii가 새로운 타이틀들과 함께 시장을 강타하였다. 그중에서도 슈팅게임 장르는 그래픽 뿐만 아니라 새로운 게임플레이에도 놀라운 발전을 이루었다.

 

컨텐츠와 인간의 관계, 컨텐츠를 통한 감정의 변화, 컨텐츠에 의한 인지적 반응과 같은 것들을 독점적인 뇌 모니터링 EEG와 바이오 센싱 기술로 연구하는 센프란시시코에 위치한 엠센스에서 연구 중인 리서치의 일부를 살펴봄으로써 어떤 게임이 성공적이고 세련된 차세대 슈팅 타이틀인지에 대해 정확하게 이해할 수 있다.

 

어디에 관계가 있으며, 어디에서 그렇지 않은가? 새롭고 진보적인 게임플레이에 플레이어는 어떻게 반응하는가? (흥분을 저하시키는 것은 무엇인가?) 우리는 차세대 타이틀에서 일어나는 광범위한 트렌드가 어떤 것인지 알 수 있다.

 

우리는 현재 시장에 나와 있는 새로운 1인칭 혹은 3인칭 슈팅 게임 게임들에 대해 플레이어들이 어떻게 반응하는가를 지켜보기 시작하였다. 베틀필드 2142, 콜오브듀티2, 피어, 기어즈오브워, 고스트리콘 어드밴스 워파이터2, 그리고 레지스탕스 : 인류의 몰락이었다. 우리는 거기에 이전 게임들의 미래를 파악하는 능력을 증명하기 위해 2개의 명작 게임인 헤일로2와 하프라이프2를 추가하였다.

 

우리는 각각의 우리가 게임이 유저에게 긍정적인 인상을 만들기에 가장 중요한 시간이라고 판단한 게임의 초반 90분의 동안의 플레이어의 반응을 측정하였다.

300시간이 넘는 게임데이타와 생리적 데이터는 우리가 발견한 발전을 만들어내었고 분석하였다.

우리는 섣부른 예측을 하거나, 선입견을 가지지 않았으며 오직 데이터가 무엇이 작동하고 작동하지 않는지에 대해 설명할 수 있도록 하였다. 이를 통해 유출한 결과는 한편으로는 이미 존재하는 영원한 좋은 게임 디자인 기술에 대해 입증하였고 또 다른 한편으로는 게이머들이 신경을 쓰고 있었으나 말하는 방법을 찾지 못하고 있던 것들에 대해 밝혀주었다.

 

What Went Right 무엇이 잘되었는가?

 

1. 중요한 감정적 테마를 가진 컷신 동영상

 

감정적 반응의 생리적 데이터에 의해 밝혀낸 결과에 따르면 완벽한 컷신을 위한 규격화된 양식은 없었다. 마치 영화와 같이 게임의 컷신은 하나만의 창조적인 청사진을 가지고 있지 않았다. 당신은 쉽게 상상할 수 있을 것이다. 공포영화는 코메디 영화와 다른 감정을 움직이는 장치를 가지고 있다. 하지만 아마 두 가지 다 매우 효과적인 장치일 것이다.

우리가 알아낸 것은 기어즈 오브 워, 피어, 콜오브듀티3와 같은 게임들은 특별한 테마를 가진 간정적 장치들을 통해 플레이어를 끊임없이 몰입시킨다는 것이다.

 

>>피어 : 예제 플레이어 컷신이 진행되는 동안의 아드레랄린양의 변화

X축은 시간 Y축은 아드레랄린양의 변화량

컷신이 출력되는 초반에는 아드레랄린 분비량이 떨어졌다가 계속되면서 올라가고 컷신이 끝날 때 쯤에서 다시 떨어지는 것을 알 수 있다.

 

예를 들어 피어의 경우 어두운 테마와 날카로운 음악은 지속적으로 높은 몰입도를 유지시켜 준다. 초반부 컷신의  경우 게임에서의 전투중에 분비되는 아드레랄린의 양보다도 많은 양의 아드레랄린이 분비되었다. 대화, 음악, 피로 가득찬 화면 연출과 같은 독창적인 요소들은 전체 시간의 73%동안 강한 두려움의 반응을 이끌어 내었다. 우리가 컷신의 정보를 기록한 다른 장르의 게임들에 비해 월등하게 높은 수치였다.

콜오브듀티3 : 반응의 총합

튜토리얼과 첫번째 레벨을 플레이하는 동안의 몰입도

X축은 시간, Y축은 각종 생리 지수를 이용한 몰입도

튜토리얼에서 몰입도가 떨어지는 것을 알 수 있다.

밑의 설명을 보면 스테이지가 끝나고 보상의 컷신에서 수치가 높아진다고 한다.

 

콜오브듀티3는 비록 효과적인 하나의 방법이 있음에도 다른 방법을 사용하였다. 그것은 공포가 아닌 보상에서 비롯된 몰입도가 높은 컷신이었다. 그리고 그것은 긍정적인 감정의 백터로 측정되었다. 자신이 임무를 완수한 것에 대한 NPC의 칭찬이 포함되어 있는 콜오브듀티3의 각 스테이지 마지막에 나오는 컷신들은 80%의 플레이어 들에게 보상에 대한 매우 강한 긍정적인 반응이 있었다. 이러한 방법은 게임 플레이의 성취감을 강렬하게 불려 일으키는 간단하고도 효과적인 방법이다.

 

기어즈오브워에서 우리는 놀라운 결과를 얻어내었다. 기어즈 오브 워의 10개의 가장 큰 이벤트들이 플레이어의 몰입도가 가장 높아지는 순간으로 측정되었기 때문이었다. 렉쳐들과의 싸움이나 전설적인 전투에서 이런 결과가 얻어지는 것이 놀라운 일은 아니었지만 우리는 Lieutenant Kim이라는 동료 캐릭터가 기습을 받아 적군들에게 매우 폭력적인 방법으로 살해되는 컷신 동영상에서 이런 결과가 나올 것이라고는 기대하지 않았다.

 

80%의 게이머 모두는 몰입도가 가장 높아지는 리액션을 보여주는 10번의 순간이 게임을 할 때 나타났다. 체인 톱을 통한 피의 향연이 펼쳐질때, 큰 전투가 벌어질때에 국한된 것이 아니었다.  기어즈 오브 워의 플레이어들은 액션, 배틀 시퀀스, 그리고 그들의 동료들과 대화를 할 때 지속적으로 높은 레벨의 몰입도를 보여주었다.

 

2. 전투와 통합된 튜토리얼

 

게임은 (혹은 콘트롤러는) 점 점 복잡해지고 있다. 그에 따라 게임 플레이 매카닉을 가르치는 개발자들에게 일반적으로 점점 큰 도전이 되고 있다.

우리의 연구는 18살에서 34살까지의 남자 게임 플레이어들의 경우 무엇을 해야 하는가에 대한 설명을 받아드리지 직접 해보며 효과적으로 배운다는 것을 입증했다.

 

우리는 몰입감있는 튜토리얼의 중요성을 강조하는 두가지 사이드 이팩트를 보았다. 첫번째, 대부분의 경우 어떻게 게임을 해야하는지 잘 모르는 플레이어들은 지속적으로 게임을 플레이 하는 내내 낮은 몰입감을 기록하였다. 그들은 게임 플레이에 몰입하기 위해 노력해야만 했다. 심지어 튜토리얼이 끝나고 스테이지가 끝나도 마찬가지였다.

 

두번째 길고 지루한 튜토리얼은 플레이어가 자신이 이 게임에 몰입할 수 있음을 자각하는 중요한 순간인 첫번째 몰입 순간을 지연시킨다. 우리가 테스트한 어떤 게임들은 20분동안 단지 게임을 즐겁게 하고 싶을 뿐인 플레이어들을 강하게 몰입시킬 수 있는 이벤트가 등장하지 않는다.

 

개발자들이 생각해볼 만한 것은 게임 제작 사이클이 끝나기 전까지 튜토리얼을 제작하지 않는 것이다. 튜토리얼은 게임에 진정으로 몰입할 수 있는 첫번째 순간이 될 수 있다. (그리고 앞으로, 미래 세대의 하드웨어에서는 더더욱 그럴 것이다.)

 

이 테스트에 샘플이 될 수 있는 새로운 게임 플레이를 추가한 두 개의 게임은 기어즈오브워와 고스트리콘어드벤스워파이터2였다. 기어즈오브워는 커버 메카닉을 추가하였고 고스트 리콘의 경우 분대원을 볼 수 있는 헤드업 디스플레이, 분대 기반의 전투, 연막탄, 조종사가 없는 공중 유닛 그리고 그외에도 많은 것들을 가지고 있었다.

 

이 게임들은 단순한 전략으로 유저들을 몰입시킨다. 플레이어는 액션 속에 던져지며 공격당한다. 그리고 기대한 대로 배워 나간다. 이 게임들은 플레이어에게 더미박스 타겟에 수류탄을 던지게 함으로써 수류탄을 던지는 방법을 가르치지 않는다. 그들은 실제 줄거리상의 중요한 적들을 상대 하면서 플레이어에게 교육을 시킨다.

 

기어즈 오브 워는 게임 플레이 매카닉을 전투가 없는 곳에서 강제로 배우게 하는 것 뿐만 아니라 튜토리얼을 스킵하고 전장에 던져지는 것을 선택할 수 있는 옵션을 제공하였다. 우리의 연구에 참여한 40%의 사람들이 튜토리얼을 스킵하였다. 하지만 그들이 스킵을 하였든 하지 않았든 간에 그들은 게임 플레이에 강하고 빠르게 몰입하였다. 사실 첫번째 레벨에서의 몰입감의 평균값은 이후의 게임들에 비해 비교할 수 없을 만큼 높았다.

 

고스트리콘어드벤스워파이터2의 첫번째 스테이지는 사실 튜토리얼이다. 좋지 않은 환경을 가진 시뮬레이션이었지만 실제의 일반적인 전투 상황과 크게 구분할 수 없었다. 감정이 고조되고 아드레랄린이 최고조로 올라가는 순간은 두꺼운 장갑의 정부 수송기를 날려버리기 위해 연만탄과 폭발물에 익숙해지는 때 나타났다.

 

사실 조용한 교육의 순간과 새로운 전략으로 강한 적을 상대하는 강렬함이 교대되는 것은 큰 감정의 롤러코스터를 만들어 낸다. 우리가 연구한 8개의 타이틀에서 가장 몰입감이 높아지는 첫번째, 혹은 두번째 이벤트로 기록되었다.

 

3. 다시 업시키기 위한 의도적인 긴장감의 떨어뜨림

 

롤러코스터와의 공통점은 플레이어의 몰입감과 생리적인 반응을 설명하는데 가장 적합한 것들 중 하나다. 재미라는 것은 마치 롤러코스터에 탄것 처럼 올라갔다 내려갔다 해야한다. 같은 높이에서 계속 유지되는 재미는 롤러코스터가 아닌 모노레일을 탄 것 같은 재미를 줄 것이다. 물론 비디오 게임에서의 감성적인 드라마를 만들기 위해서도 마찬가지다.

 

재미있는 것이 좋다고 느끼는 것은 매우 직관적이지만 우리의 연구에서는 가장 긴장감있는 순간은 조용한 순간의 결과로 자주 나타났다. 내려가는 타임, 몰입도가 낮아지는 순간이 항상 나쁜 것 만은 아니다. 주기적인 그러나 명확하게 플레이어를 진정시켜주는 액선은 더 긴장감 넘치는 액션 시퀀스를 만들어주며 마지막 전투의 시네마틱에 대한 더 강한 반응을 이끌어 낸다. 하지만 강조하고 싶은 것은 안심을 시켜주는 시간이 너무 길어지고 플레이어가 한가해지면 사람들은 모노레일에서 내리고 싶어할 것이라는 것이다.

 

개발자들이 이 두가지 요소를 이해하기 위한 가장 중요한 것은 큰 긴장감을 자기고 있는 이벤트와 안심을 시켜주는 이벤트는 반드시 함께 나타나야 한다는 것이다. 하나는 다른 하나가 없다면 기능하지 않는다.

 

강한 긴장감이 있는 순간의 예는 지구의 운명을 건 전설적인 전투 (콜오브듀티3, 레지스탕스, 기어즈오브워), 강한 적 보스(고스트 리콘, 기어즈오브워) 그리고 날아다니는 벌 같은 작은 것들과의 전투이다. (하프라이트2, 레지스탕스, 그리고 기어즈오브워)

 

기어즈 오브 워의 반응 그래프, X축은 시간, Y축은 반응량, 조용한 순간이 긴장감있는 순간을 이끈다.

 

폭풍전의 고요를 만드는 것은 더욱 교묘하다. 우리는 몇 가지 전략들을 확인하였다. 기어즈 오브 워에서는 컴퓨터의 라디오 메시지에 귀를 기울이고 걸어다니는 중에 계속 긴장감을 유지하게 만들어 준다. 그 순간이야 말로 에메션스홀에서 로커스트들이 출현하기 직전이기 때문이다.

 

하프라이프2는 다른 방법을 이용하였다. 전투 사이에 감정적인 단절을 가져오는 퍼즐을 제공하는 것이었다. 보통 이러한 퍼즐은 아드레랄린의 생성을 일으키지 않는다고 기댜된다. 그러나 그것들은 숨어 있는 몰입감을 끌어내며 보다 확실하게 긍정적인 감정을 이끌어낸다. 몰입감은 다른 것들과 벤치마크 했을 때 17% 증가하였으며 퍼즐을 완료한 후에 긍정적인 감정들은 보통의 경우보다 20%나 증가하였다. 이것은 하프라이프가 아드레랄린 전투와 퍼즐의 보상을 각각의 앞뒤에 끼어 넣어 마치 롤러 코스터 처럼 만들었음을 보여준다.

 

4. 근접전, 근접전, 근접전

 

근접전은 몰입감을 증대, 아드레랄린을 생성, 보상의 감정등 슈팅 게임을 재미있게 만드는 모든 감정들을 불려일으키는 믿을만한 방법이다. 근접전이 장르적으로 새로운 것은 없다. 하지만 매우 빠르게 발전하는 영역인 차세대 게임에서는 예외적으로 빠른 페이스의 근접전투를 자주 일어나게 하는 경향이 강하다.

 

올해의 게임을 수상한 3개의 게임 (기어즈오브워, 헤일로2, 하프라이프2)이 모두 근접전을 강요하거나 격려하는 매우 훌륭한 근접 무기를 가지고 있으며 해당 무기의 사용을 장려하는 디자인이 되어 있다는 사실을 폭넓게 연구한 우리에게 이러한 경향은 전혀 놀라운 일이 아니다.

 

잘 만든 FPS 타이틀들은 높은 위험을 감수한 유저에게 감정적 보상을 해주는 것과 몰입감의 레벨과 보상의 느낌을 드라마틱하게 증가시켜주는 아드레랄린이 폭발하는 시나리오를 통해 근접전을 격려한다.

 

예를 들어 헤일로2와 기어즈오브워의 경우 플레이어는 에너지 소드나 전기톱을 이용한 인스턴트 킬을 사용했을 경우 매우 큰 만족감을 느낀다. 헤일로2의 에너지 소드킬은 같은 장르의 다른 게임과 비교하여 긍정적인 감정을 30%가량 증가시켰다.

 

코어 게임 플레이 요소 퍼포먼스에 따른 생리적 반응의 변화량

X축 왼쪽부터 탈것을 조종할 때, 스나이핑, 총을 쏠 때, 실드가 떨어졌을 때, 수류탄킬, 근접전, 에너지 소드

다른 플레이를 할때보다 얼마나 좋은 반응을 이끌어 내는가?

 

또한 기어즈오브워의 플레이어들은 그들이 전기톱으로 상대를 무참히 배었을 때 출력되는 피의 분수를 보며 높은 감정적인 만족감을 얻었다. 물론 우리는 하프라이프2의 초반 전투에서 사용할 수 있는 무기가 장도리 뿐이었다는 것을 잊어서는 안된다.

 

>기어즈오브워의 예 근접전을 하는 동안의 몰입감과 긍정적인 감정의 변화

보라색이 몰입감, 초록색이 긍정적 감정

근접전을 끝낸 순간에 가장 높다.

 

다른 게임들은 근접전을 격려하지 않는다. 그들은 강요한다. 고스트 리콘에서 우리는 이미 플레이어가 어떻게 중장갑의 탈것들을 파괴하는 방법을 배우는지에 대해서 언급했다. 그것은 장갑차에 붙여서 폭탄을 설치하는 것 뿐이다. 콜오브듀티3에서 플레이어는 독일군들과 가까이 붙어서 싸울 수 밖에 없는 전장에 던져지는 미니게임이 존재한다. 두 가지 이벤트 모두 높은 몰입감이 측정되었다. 하지만 이런 이벤트 들은 게임을 하는 동안 1~2번 정도 밖에 등장하지 않는다. 많은 수의 명랑한 순간들이 게임 스스로를 두드려지게 만드는 것과는 다르다.

 

근접 무기 자체가 근접 전투를 격려하는 것은 아니다. 기어즈 오브 워의 전투를 들어보라. 수많은 총알 소음에 둘려쌓여있는 상황에서도 플레이어는 그들의 AI 팀 메이트가 적군의 옆구리를 공격하기 위해 당신에게 소리치는 말들을 또렷하게 들을 수 있다. 그들이 잊은 말이 있다면 좁은 총싸움지역이나 에메션스 홀이 급격하게 적군의 옆구리를 공격할 수 있는 근접전투로 전환될 수 있다는 사실 정도이다. 이러한 에피소드가 진행되는 동안 우리는 지속적으로 몰입감과 긴장감이 증대된다는 사실을 측정할 수 있었다.

 

재미있는 차세대의 게임을 만들려는 개발자들이 명심해야 할 것은 플레이어들을 근접전에 던져버리는 것 보다 더욱 게임을 독특하게 만들어주는 것은 없다는 것이다.

 

5. 작은 것이 큰 차이를 만들어 낸다.

 

멀티플레이 게임의 재미가 증명된 게임은 지속적으로 몰입시키는 핵심 게임 플레이 요소가 빠른 페이스로 등장한다. 근접 무기, 탈것들, 그리고 수류탄과 같은 이러한 요소들은 쉽게 싱글 플레이의 경험을 멀티 플레이의 것으로 전환시킨다.

 

우리의 게임플레이 이벤트에 따른 심리적 변화가 얼마나 자주 일어나는 가를 측정한 측정 결과에 따르면 기어즈 오브워 (평균에 비해 51% 높음)와 헤일로2(35%높음)이 가장 측정값이 높은 두 개의 게임으로 나타났다.

 

우리의 시스템은 헤일로2에서 플레이어의 실드가 다운 되었을때와 같은 핵심 이벤트들이 일어났을 때의 시간을 기록하고 그것을 자동으로 심리적 데이터와 비교해준다. 많은 게임들이 언제나 플레이어를 몰입시키는 걸출한 요소들이 있다. 그러나 헤일로2와 기어즈오브워의 경우 모든 작은 요소들이 잘 구성되어 있다. 헤일로2에서 실드 다운 이 되었을 때 18%정도 몰입도가 높아졌고, 수류탄을 쓸 때 21%의 몰입도 증가를 보여주었다. 이러한 작은 요소들은 몰입도를 높이는 가장 좋은 방법이다. 왜냐하면 그런 것들은 플레이를 하는 동안 자주 나오기 때문이다.

 

이러한 결과는 본질적인 게임플레이 경험은 몰입감을 높이기 위한 큰 스크립트 이벤트에 의존하지 않는는다는 사실을 보여준다. 대신에 거기에는 크고 포괄적인 자잘한 이득들이 있다. 이러한 모든 몰입 시스템은 쉽고 직관적으로 멀티 플레이 게임으로 이전되며 기어즈 오브 워와 헤일로2의 경우 플레이어들에게 재미를 주기 위해서 단지 그들을 데스매치의 전장에서 집어놓고 그들이 죽어가는 모습을 바라보기만 하면 되었다.

 

What Went Wrong

 

1. 엔터테인 목적이 아닌 정보를 전달하기 위한 컷신

 

컷신은 시네마틱 경험을 반들어 낼 수 있는 큰 기회을 제공한다. 콜오브듀티3, 피어, 기어즈오브워와 같은 게임들은 플레이어의 감성을 자극하기 위한 조율을 성공적으로 하였다.

 

그러나 우리가 연구한 다른 타이틀들은 컷신이 나오는 동안 집중력을 유지하는 것이 다른 게임 요소들에 비해 어려웠다. 유저들은 컷신을 원한다고 일반적으로 컷신은 전투와 같은 다른 인터렉티브한 게임 플레이에 비해 몰입도가 떨어진다. 일반적으로 컷신은 두개 레벨 사이의 피상적인 다리를 제공할 뿐이다.


잘 만들지 못한 컷신은 다른 패턴을 보여준다. 대부분은 높은 수준의 정보를 보여주기 위해 말하는 사람의 머리와 나레이션을 너무 많이 보여준다. 브리핑을 하는 듯한 컷신은 이러한 카테고리로 실패하게 된다. 예를 들어 고스트리콘어드벤스워파이터2에서 컷신이 출력되는 동안 플레이어에게는 일관성없는 생리반응이 측정되었다. 이러한 스크립트된 브리핑은 지속적으로 플레이어를 몰입시키지 못한다. 플레이어는 브리핑에서 주어지는 정보에 대해서 크게 중요하게 생각하지 않고 명확한 것은 이러한 컷신은 플레이어의 집중력을 떨어뜨린다.

 

레지스탕스에서 컷신이 출력되는 동안 플레이어의 몰입도는 명확하게 57%정도 떨어진다. 이 컷신에는 키메라의 공격과 헤일의 여행을 지나치게 자세하게 설명하고 있으며 이러한 긴 컷신이 출력되는 동안 플레이어의 감정은 게임에서 멀어진다. 반대로 생각해보면 다이나믹한 액션장면과 캐릭터간의 대화가 플레이어의 감동하게 하고 몰입시키는 강한 능력을 설명해준다는 것을 알 수 있다.

 

아무리 높은 퍼모먼스의 게임이라도 컷신 때문에 유저의 감정이 이탈되는 것에 고통을 받는다. 헤일로2의 컷신이 출력되는 동안의 유저의 몰입감 저하는 핵심 게임 플레이를 하는 동안의 극단적인 몰임감과 비교해서 64%나 떨어진다. 헤일로2와 같은 이러한 연구 결과는 전투의 즐거움이 어떤 컷신이나 스토리 라인보다 더 재미있다는 것을 보여준다. 이것은 제작 노력을 배분하는 방법을 아는것과 모든 프로덕션 스케쥴을 본질적으로 타이트한 타임 프레임을 주어주는 것이 게임 디자인 그 자체 만큼이나 중요하다는 것을 우리에게 알려준다. 

 

절적한 컷신의 사용이 우리의 집중력을 높여준다는 것은 장르를 불문하고 확실하다. 특히 차세대의, AAA타이틀의 경우는 큰 시네마틱 경험을 전달하기를 기대받는다. 당연히 이러한 현상은 컷신의 역할에 대한 의문을 불려일으킨다. : 정보를 전달하기 위한 것이냐? 즐거움을 위한 것이냐?

 

미리 말하자면 기어즈오브워는 올바른 선택을 한것으로 보인다. 이 게임의 컷신은 액션으로 가득차 있고 광범위한 모든 정보들은 전투와 전투 사이의 게임 플레이가 진정되는 국면 사이에 라디오나 대화의 형식으로 전달한다. 우리의 데이터에 따르면 즐거움을 위한 컷진이 플레이어의 몰입도와 재미의 크기에 관계되어 있다.

 

2. 신병 훈련소와 트레이닝 영역

 

우리는 영화와 텔레비전 쇼와 비디오 게임에서 고전적인 신병 훈련소에 대해서 보아왔다. 기간병들에게 압박받는 신병들은 강도 높은 훈련에 따라 강해지며 싸울 준비가 된다.

 

여기에는 오직 한 가지 문제가 있다. 총을 쏘는 것과 수류탄을 던지는 것과 손으로 싸우는 것을 더미타겟과 싸우면서 배우는 것에 사람들이 전혀 몰입하지 않는다는 것이다. 풀레이어의 첫인상이 만들어지는 첫번째 중요한 순간에서 튜토리얼이 액션, 스토리라인과 멀리 떨어져 있다는 것은 플레이어를 감정적으로 멀어지게 만든다.

 

콜오브듀티3보다 이런 순간이 많이 나타나는 게임은 없다. 트레이닝 에리어에서 플레이어는 실패에 대한 위험이나 패널티 없이 어떻게 싸워야 하는지 배우게 된다. 물론 게임 플레이 초반의 7분동안 감정적 몰입도는 떨어진다. 7분이란느 긴 시간동안 플레이어는 몰입하지도 않았고 즐겁지도 않았다. 오직 플레이어가 전장에 떨어졌을 때만 몰입도가 다시 올라가기 시작했다.

 

1년에 가까이 비디오 게임을 분석하고 테스트하는 동안 우리는 게임 디자인의 절대적인 룰을 많이 찾아내지는 못하였다. 그러나 튜토리얼에 대한 것은 명확하다. 보상과 실패가 없는 튜토리얼을 만들지 않은 게임은 그렇지 않은 게임 만큼 몰입도를 떨어뜨리지 않았다는 것이다.

 

3. 깨져버린 롤러코스터

  

플레이어가 긴장감을 조절하게 할 수 있는 많은 방법이 있음에도  끊임없이 매우 높은 수준의 긴장감의 경험을 유지하도록 시도된 게임들은 결국 낮은 긴장감, 낮은 시네마틱 그리고 낮은 줄거리 전달력을 가지게 된다.

 

이러한 문제는 두가지 방법을 사용했을 때 발생한다. 첫번째 긴장감이 발생하는 이벤트들을 다양하게 만들지 않은 게임은 극단적으로 플레이어를 잃기 시작한다. 다시한번 우리는 생리적인 신호들을 측정하였다. 측정결과에 따르면 이벤트들을 다양하게 하지 않은 게임들은 반응값이 점 점 줄어드는 것을 확인할 수 있었다. 헤일로2는 빠른 페이스의 액션을 가속시키지만 싱글 플레이의 경험에 생긴 사이드 이펙트는 긴장감이 줄어든다는 것이었다. 헤일로2의 첫 레벨에서 플레이어는 오직 많지 않은 종류의 적들의 섞여 나오는 것만을 보게 되고 그러한 결과 긴장감은 다른 게임에 비해 40%가 떨어졌다.

 

두번째 긴장감있는 총싸움으로 레벨을 시작한 게임은 플레이어의 집중력을 사로잡는다. 하지만 그런 집중력은 뒤이어 나오는 이벤트에서 사라져 버린다. 다른 게임과 비교했을 때 남은 레벨에 대한 플레이어의 집중력은 이러한 환경에서 명확하게 낮아졌다. 이것은 집중력의 감소로 이어진다.

 

예를 들어 콜오브듀티3의 두번째 레벨은 굉장히 높은 긴장감의 전투로 시작한다. 그러나 남은 레벨을 플레이하는 동안의 플레이의의 집중력은 지속적으로 감소하였다. 이것은 슈팅게임을 개발하는 모든 개발자들이 원하는 영화 같은 결말이 아니다.

 

4. 반복과 뻔한 결말

 

우리는 또한 참신함과 알려지지 않은 것, 유사한 것이 플레이어를 몰입시키는데 얼마나 중요한지에 대해 발견하였다. 기어즈오브워의 시더라는 캐릭터는 이러한 현상을 증명하는 좋은 예이다. 90분의 게임 플레이를 하는 동안 플레이어는 3번 시더와 마주치게 된다. 그들은 헤머오브던으로만 죽일 수 있으며 그들을 죽이는 것이 라디오 커뮤니케이션을 복구하는 중요한 방법이다.

 

시더를 만날을 때의 몰입도의 증가 그래프

첫번째 만났을 때 가장 높고

두번째가 가낭 낮다.

 

독특한 패턴을 가진 시더 캐릭터와 처음 만나는 장면은 게이머를 강하게 몰입시킨다. 그러나 두번째와 세번째 시더와 만달을 때는 사람들은 첫 번째 만났을 때 만큼 몰입하지 않았다. 어떤 모션, 센스 데이터는 플레이어가 두번째 세번째 시터를 만났을 때는 오직 모션을 통해서서만 움직이다는 사실을 설명해주었다.

 

예외는 존재하는가? 심지어 같은 게임에서도 그러하다. 기어즈오브워에서 로커스트의 벌과 같은 적들을 데리고 빠르게 기어다니며 레쳐의 경우 그들이 등장하는 파트에서 언제나 플레이어를 몰입시간다. 왜냐하면 플레이어는 살아남기 위한 유일한 수단인 드로이카 머신건을 위해 괴롭힘을 당했기 때문이다.

 

이러한 결과를 통해 알 수 있는 중요한 사실은 반복이 아니다. 이것은 알려지지 않은 결과이다. 한명의 플레이어는 시더를 만나면 해머 오브 던을 들어야 한다는 사실을 알고 있다. 이것은 상당히 빠른 시간에 명확하게 알 수 있는 것이다. 그러나 각각의 래처의 웨이브는 반복되는 이벤트라고 해도 플레이어는 어떻게 싸워야 그들과 싸울 수 있는지에 대한 어떠한 아이디어도 가지고 있지 않다.

 

5. 특수 무기를 통한 게임 플레이 이노베이션

 

연구결과는 특수무기는 큰 성과를 가지고 오기도 하지만 잘 못 만들었을 경우 큰 실패를 가지고 올 수도 있다는 것을 보여주었다.

 

먼저, 특수 무기의 정의에 대해서 알아보자. 특수무기란 피스톨이나 머신건과 같은 일반적인 무기에 비해 유니크하고 파워풀하게 이용하는 무기를 말한다. 이것들은 하이 파워의 스나이퍼 라이플, 머신건 터렛, 전투 로봇, 탱크와 같은 탈 것들을 포함한다.

 

이러한 독특한 게임플레이를 유발하는 무기들을 소개하는 것은 디벨로퍼와 마켓터에서 발전(그리고 위기)의 기회를 증가시킨다.

 

무엇이 매력적이고 그렇지 못한 것을 구분하는가? – 그리고 이것이 왜 양날의 검인가  - 하는 것은 그 무기들이 가진 파워의 결과이다. 플레이어들이 보호되고 아무런 위험을 느끼지 못하는 상황은 낮은 몰입감을 이끌었다. 하지만 플레이어가 지속적으로 공격당하고 보호받지 못하고 같은 힘을 가진 적군이 있을 때 특수무기의 몰입도 향상 효과는 놀라웠다. 몰입도는 차트레벨을 벗어날 만큼 최고가 되었다.

 

우리는 두가지 큰 힘을 가진 무기를 조사하였다. 스나이퍼 라이블과 머신건 터렛이었다. 두가지 무기다 대부분의 슈팅 게임에서 등장하는 요소들이었다. 머신건 터렛은 평균적으로 우리가 데이터 베이스를 소유한 다른 요소들에 비해 대단히 높은 몰입도를 가져왔다.

 

 

그러나 우리의 테스트 그룹에 속해있는 어떤 게임은 지속적으로 몰입도를 유지하는 것에 실패하였고 몰입도를 높일 큰 기회를 잃어버렸다. 예를 들어 레지스탕스에서 머신건 터렛을 쓸 때의 몰입도는 헤일로2에 비해 19%낮았다. 그것은 재미있는 것과 다른 것이었고, 솔직하게 실망스러운 것이었다.

 

이러한 실패는 어떻게 플레이어를 보호했는가에 기반한다. 레지스탕스에서 처음 90분 동안 머신건 터렛을 사용하게 되는 곳은 거대한 탱크안이다. 헤일로2에서는 플레이어들이 작고 보호받을 수 없는, 가까이에 적이 있어 자신이 죽을 수 있다는 것이 확실한 장소에서 터렛을 사용하는 그들은 죽지 않기위해 터렛을 오랫동안 사용하게 된다.

 

몰입도가 높은 스나이핑과 그렇지 않은 스나이핑의 차이는 자신이 총을 쏘기 위한 공격자세의 차이에서 기인한다. 헤일로2와 베틀필드 2142 그리고 고스트 리콘은 특별히 스나이핑에 의해 각각 연구에서 얻은 평균에 비해 12%, 18% 16%의 몰입도 향상 효과를 가졌다. 그 결과를 유추해보니 레벨 디자인을 통해서 스나이핑을 하는 유저를 계속 해서 앞으로 전진 시켰고 그들을 자주 위험한 길로 밀어 넣었다.  

 

콜오브듀티3는 그렇지 않다. 게임은 플레이어에게 그들 스스로를 베틀 필드로부터 멀리 떨어져 그들이 공격받지 않는 상태에서 스나이핑 할 수 있는 기회를 제공하였다. 그 결과는 스나이핑을 할때의 몰입도의 저하 뿐만 아니라 플레이어들이 적과 충분히 떨어져 있다고 생각하는 포지션에서의 몰입도의 저하까지도 불려 일으켰다.

 

이러한 패턴은 탈 것을 사용할때도 똑같이 일어난다. 베틀필드2141에서 배틀워커는 일반적으로 다른 베틀 워크인 동일한 파워를 가진 적들을 만나기 전까지 전혀 몰입도를 향상 시키지 못했다. 플레이어가 베틀워커에 타고 있는 대부분의 시간을 몰입도를 향상시키지 못했다. 비슷한 예로 레지스탕스에서 탱크를 몰고 있는 순간에 몰입감이 떨어지는 것이 있다. 레지스탕스에서 대적할 만한 공격이 없는 탱크 배틀은 재미있지도 않았고 아드레랄닌이 생성되지도 않았다.

 

재미있는 것은 게임을 재미있게 하는 이렇게 게임을 재미있게 해주는 공격들이 적들의 형태로 나타나지 않는다는 것이다. 헤일로2의 워스로그는 지속적인 몰입도와 아드레랄린을 다른 탈 것 들과 비교하였을 때 17%정도 더 불려일으킨다. 워스로그가 세밀한 조작이 불가능하다는 사실이 이러한 차이를 불려 일으키는 이유이다. 물론 조작에 페널티를 주지 않더라도 매우 빠른 속도의 드라이빙, 높은 점프와 같은 일반적으로 무모하게 보이는 행동들은 플레이어의 몰입감을 증대 시킨다. 이런 상황을 종합해 볼 때 플레이어는 (그리고 탈 것들의 속력은) 공격과 도전 그리고 그런 것들이 어울어진 독특한 게임 플레이에 의해 가속된다.

 

몰입감을 증대시킬 열쇠

 

우리의 고객들 (그리고 우리의 패밀리 식구들)은 그것이 비디오 게임이든, 광고이든, 영화이든 수용자가 거부할 수 없는 강한 몰입감있는 미디어를 만들 수 있는 하나의 방법이 있는지에 대해서 언제나 우리에게 물어본다.

 

하지만 여기에는 몰입감을 높이고 성공적인 게임플레이를 만드는 한정된 유행만이 있을 뿐이다. 최근에 성공한 게임들은 모두 이것보다 더 높은 수준의 성과를 이루어 내었고 독특한 매력적인 경험을 선사하는 창조력을 가지고 있다. 우리는 수류탄을 던지는 것과 같은 사소한 것들이 서사적인 대사와 플롯 이벤트들 보다 더 중요하다는 사실을 깨달았을 때 크게 놀랐다.

 

사소한 것들은 좀더 즐거운 경험을 선사하며, 높은 평점과 판매량을 좌우한다. 간단하게 말해 더 재미있다는 것이다. 우리가 연구한 바에 의하면 우리가 연구한 게임들에 공통적으로 적용할 수 있는 확실한 몇가지 재미의 법칙들이 있다.  어떤 것들은 장르를 불문하고 게임전체에 적용할 수도 있는 것들이다. 그럼에도 불구하고 더 재미있는 것은  미래의 타이틀들이 이러한 법칙을 어떻게 깨버리는가를 지켜보는 것이다. 게이머들은 게임이 주는 경험에 더욱 더 많은 기대를 할 것이고, 현명하게 법칙을 깨면서 리스크를 감수하는 것이 수많은 게임들 사이에서 우뚝 서는 유일한 길이 될 것이다.

 

수집한 생체 데이터

연구된 게임

  • Battlefield 2142 배틀필드 2142
  • Call of Duty 3 콜오브듀티3
  • F.E.A.R. 피어
  • Gears of War 기어즈오브워
  • Ghost Recon AW 2 고스트리콘 어드벤스 워파이터 2
  • Resistance: Fall of Man 레지스탕스 : 인류의 몰락
  • Halo 2 헤일로2
  • Half-Life 2 하프라이프2

측정된 플레이어의 반응들

  • Brainwaves (through dry EEG sensors) 뇌파 (건조한 EEG의 센서를 통해서)
  • Heart Activity 심장박동
  • Breathing 호흡
  • Blinking 눈깜빡임
  • Temperature 체온
  • Motion 움직임

분석한 요인들

  • Engagement 몰입도
  • Emotion 감정
  • Adrenaline 아드레랄린
  • Cognition 인지, 지각

방법론

 

엠센스는 미디어에 대한 유저의 반응을 측정하기 위한 생체 센서가 달려있는 헤드셋을 통해 새로운 세대를 만들어 내었다. 그 헤드셋은 게임을 하는 동안의 뇌파, 심장박동, 호습, 눈깜박임, 체온, 모션, 그리고 다른 신체적 신호들을 측정한다.

 

우리가 소유한 이러한 측정 알고리즘은 십년에 걸친 연구 결과와 몰입도, 감정, 아드레랄린, 그리고 인지 연구를 위한 적절한 개발 모델을 만들기 위한 엠센스에서 시행된 수천번의 실험을 통해 사실로 입증되었다. 각각의 것들은 게임 경험에 있어 각각 다른 중요성을 가지고 있다.

 

엠센스는 또한 뚜렷한 목적을 지니면서도 완전히 다른 정보가 차단된 상태에서 정보를 수집하고 분석하는 방법을 만들어 내었다. “이벤트태그플레이어의 죽음과 같은 이벤트가 언제 어디서 일어났는지에 대해서 확실히 알아낼 수 있다. 이것은 신체 데이터와 관련되어 있으며 그것들을 수집하고 다른 타이틀과 벤치 마킹을 한다. 이러한 결과는 무엇이 플레이어의 몰입과 관계가 있고 무엇이 그렇지 않은지에 대한 자세한 관점을 제공하는 목적을 지닌다.

 

 

반응형
,
Posted by ozlael

지난 번 글에서 이어지는 글입니다.

이전 글 : PC에서 3D 입체 영상 게임 개발하기 #2


들어가며

그동안은 재미 없는 내용 읽어주시느라 수고 많으셨습니다. 이번 시간부터는 재미 없는 이야기 말고 본격적으로 PC 게임에 입체 영상을 적용 할 수 있는 방법을 알아보기로 하겠습니다. 아니 어쩌면 이번 시간부터가 더 재미없고 지루해질 수도 있겠네요. 하지만 별로 어려운 내용은 없으니 그냥 편안히 읽어주시면 감사하겠습니다.


미들웨어

그럼 과연 PC에서 입체 영상을 적용하려면 어떻게 해야할까요? 디스플레이 장치도 애너글리프, 셔텨그래스, 편광안경 등 많은 종류에 따라 직접 구현을 해줘야할까요? 셔터그래스 방식이면 좌안 우안 영상을 각각 직접 따로 만들어서 프레임에 맞게 번갈아가며 직접 출력해줘야할까요? 편광안경 방식이면 해상도에 맞춰서 도트를 좌안 우안 번갈아가며 직접 찍어줘야할까요? 애너글리프(적청안경) 방식이면 다행히 하드웨어를 타지 않아서 직접 만들어 출력 해 줄 수도 있습니다. 옛날에는 애너글리프를 직접 구현해서 발매된 게임들도 존재하구요.

이미지 출처 : wikipedia

하지만 서울-대전을 2시간이면 주파하고 그 안에서 스마트폰으로 RPG를 즐기는 현대에서도 저렇게 직접 노가다를 해 줘야 할까요? 당연히 아니지요. 그냥 우리는 그동안 개발하던대로 그냥 개발하면 되고 입체 영상 미들웨어의 지원을 받으면 됩니다. 미들웨어의 요구에 맞게 아주 약간(혹은 매우 많이;;) 신경써주기만 하면 자동으로 입체 영상이 탄생하게 되지요.

현재 PC용 입체 영상 미들웨어는 주로 nVIDIA의 3D VISION, iZ3D, Tridef의 DDD 이 세 가지가 쓰이고 있습니다. 다른 것도 더 있는 것 같이도 하고 잘은 모르겠지만 암튼 이 세 가지만 알고 계시면 될 것 같습니다. nVIDIA 3D VISION은 nVIDIA에서 만들었으므로 nVIDIA 그래픽 카드에서만 돌아가고, Windows VISTA 이상에서 작동합니다. 그와 달리 iZ3D와 DDD는 nVIDIA 뿐 아니라 ATi와 intel 모두 지원하며 Windows XP 이상에서 작동합니다. 그래서 ATi에서는 nVIDIA에 대항하기 위해 iZ3D와 DDD와 제휴를 맺기도 하지요. 그래서, Geforce 유저들은 3D VISION을 주로 이용하고, Radeon 혹은 GMA 유저들은 iZ3D 혹은 DDD를 주로 이용합니다. 이는 즉 모든 H/W를 지원하기 위해서는 이 세 미들웨어를 모두 신경써줘야 한다는 뜻이 되겠지요.

이 미들웨어들은 게임 뿐 아니라 영화 사진 등 다양한 입체 영상 컨텐츠를 지원하는데요,  사용자가 이 미들웨어 드라이버를 활성화 하고 컨텐츠를 실행 시키면 사용자가 가지고 있는 출력 장치에 맞게 출력이 되지요. 원래 입체영상을 보기위해서는 편광이나 셔터글래스 등 3D 지원 모니터와 특수 안경이 필요하지요. 하지만 이 미들웨어들은 특수 장비가 필요 없는 적청영상도 제공을 합니다.(한번 설치하셔서 확인해보세요. 참고 링크 : http://ozlael.egloos.com/3570101) 사용자의 출력 장치가 편광(주로 LG 제품) 방식이든 셔터글래스(주로 삼성 제품) 방식이든 컨텐츠 제작자는 신경 쓸 필요가 없는 것이지요. 

유저가 입체 영상 미들웨어의 드라이버를 활성화 하고 게임을 실행하면 대부분의 게임은 자동으로 입체 영상으로 변환됩니다. 개발자가 따로 신경을 쓰지 않아도 기본적으로는 작동하도록 미들웨어가 만들어진 것이지요. 그럼 어떤 규칙에 의해서 입체 영상이 알아서 만들어 지는 것일까요? 이 규칙만 잘 따르면 큰 문제 없이 입체 영상을 지원 할 수 있겠지요?


드로우 콜과 랜더 타겟

우선 세 미들웨어 모두 기본적인 원리는 같습니다. 하나의 드로우콜(Draw call)을 미들웨어가 중간에서 좌안용 우안용 두개의 드로우콜로 나눠서 그리는 것이지요. 이를 스테레오화(stereolize) 된다고 표현합니다. 그래서 대부분의 게임들은 큰 문제 없이 그려질 수 있는 것이지요.

드로우콜은 최종적으로는 랜더타겟(Render target)에 그리게 되지요. 바꿔 말하자면 드로우콜이 좌우 두 개가 만들어지는 것 처럼 랜더 타겟도 두 개가 만들어 지게 되는 것입니다. 드로우 콜과 마찬가지로 하나의 랜더 타겟 생성 명령이 날려지면 미들웨어는 중간에서 좌안용 우안용 두 개의 랜더 타겟을 생성합니다. 후에 드로우 콜이 날려졌을때 미들웨어는 그리는 대상이 좌우 두개가 만들어진 랜더 타겟이면 드로우 콜 역시 두 개로 나누고, 그렇지 않으면 하나의 드로우 콜만 날리게  됩니다.

네, "좌우 두개가 만들어진 랜더 타겟이면" 드로우 콜이 나눈다고 하였습니다. 그 말인 즉슨 무조건 랜더 타겟이 두개가 되는 것이 아니라는 말입니다. 두 개로 나누어 지지 않은 랜더 타겟에 그리면 입체로 만들어지는 것이 아니라는 뜻이지요. 그렇다면 랜더타겟이 두 개로 나누어 지는 조건은 무엇일까요? 이는 미들웨어마다 조금씩 차이점이 있습니다.

nVIDIA 3D VISION은 크기가 백버퍼 이상이고 비율이 비(非)정사각형인 랜더타겟을 생성 시 두 개로 만들어집니다. 일반적으로 대부분 백버퍼는 4:3 혹은 wide로 만들기 때문에 정사각형이 아닌 조건을 충족하고, 백버퍼 이상이라는 조건 때문에 MSAA시에도 정상적으로 입체영상이 만들어 지는 것입니다. 이 조건 덕에 일반적인 셰도우맵(shadow map) 방식의 그림자도 이상 없이 작동하는 조건이 충족이 됩니다. 셰도우맵은 광원에서 바라보는 시야의 모습이기때문에 스테레오가 아닌 모노가 되어야 합니다. 즉, 좌우 갈라져야 하는 케메라 시야에서의 모습과는 달리 하나만 존재하는 태양 광원의 시야이기 때문에 좌우 갈라지면 안되는 버퍼인것이지요. 보통 셰도우맵 버퍼는 정사각형으로 만들고 사이즈는 256이나 512등 백버퍼보다 작은 사이즈로 만들기 때문에 좌우 갈라지지 않고 하나의 버퍼로만 존재하게 되는 것입니다.

이미지 출처 : nVIDIA

TriDef DDD는 크기에 대한 제약 조건은 없지만 정사각형이 아닌 랜더타겟만 좌우 분리가 되기때문에 위와 같이 셰도우맵에 대한 정상적인 대응이 가능합니다. 하지만 iZ3D는 이러한 조건은 존재하지 않고 랜더타겟은 무조건 좌우 두개로 만들어냅니다. 모노 랜더타겟을 원한다면 오로지 API를 통해서만이 가능합니다.


.마치며

개발자가 딱히 신경쓰지 않아도 되는 알흠다운 상황에 대해 알아봤습니다. 다음 시간부터는 조금씩 신경 써 줘야 하는 사항에 대해 다루기 시작하겠습니다. 이제 조금씩 귀챦아질 수 있으므로 다음 시간까지 안녕히계세요 ㅋ 


 

반응형
,
Posted by 알 수 없는 사용자

이전 글 이후에 진도는 나가야 겠는데 프로토콜이 생각처럼 잘 안만들어져서 계속 이 핑계 저 핑계 대며 미뤄왔던 죠쉬 입니다. 이대로 놀게영 필자에서 짤리는가 하고 슬퍼하던 와중에 OAuth라는 괜춘한 놈을 발견 했습니다. 사실, 내가 왜 이런 참한 규수를 그동안 모르고 있었는지 부끄러울 정도로 깔쌈한 인증 프로토콜을 가지고 있네요. 이 OAuth의 인증 절차에 대해 이야기 하면서 숨겨져있는 방어책에 대해 이야기 해 보도록 하겠습니다.


0. 참고사항

OAuth Specification: http://oauth.net/core/1.0/


1. OAuth 사전지식

사용되는 용어

프로바이더(Service Provider): OAuth를 제공하는 웹 어플리케이션, i.e. Twitter, Facebook, Daum

사용자(User): 서비스 제공자의 웹 사이트에 계정을 갖고있는 사용자.

컨슈머(Consumer): OAuth를 이용해 서비스 제공자의 인증절차를 사용하고자 하는 웹 사이트나 어플리케이션

보호된 자원(Protected Resources): 서비스 제공자가 관리하는 데이터로, 컨슈머는 인증을 받아야 액세스 할 수 있는 데이터

컨슈머 키(Consumer Key): 컨슈머가 서비스 제공자에게 스스로를 식별하기 위해 사용되는 값

컨슈머 비밀정보(Consumer Secret): 컨슈머가 컨슈머 키에 대한 소유권을 확인하기 위해 사용되는 정보, 암호화 키 정도로 생각하면 된다.

리퀘스트 토큰(Request Token): 컨슈머가 사용자에게서 권한을 얻고 액세스 토큰을 확보하기 위해 사용되는 값

액세스 토큰(Access Token): 컨슈머가 특정 사용자와 연관되어 있는 보호된 자원에 액세스 하기 위해 필요한 값

토큰 비밀정보(Token Secret): 컨슈머가 주어진 토큰의 소유권을 확인하기 위해 사용되는 값

OAuth 프로토콜의 매개변수(OAuth Protocol Parameters): oauth_ 로 시작되고, http/https 프로토콜을 통해 전달되는 매개변수들


2. OAuth Authentication Flow Diagram



3. OAuth에서 사용되는 방어기법들

위의 표 에서는 뭔가 주저리 주저리 길게 설명을 해 놓았는데, OAuth가 사용하는 절차가 꽤 길어 보인다. 그러나 여기에서 설명하려고 하는 것은 'Request Token'을 얻어내는 절차 뿐이다. 먼저, 컨슈머가 서버에게 리퀘스트 토큰을 얻기 위해 전송하는 매개값 들을 살펴 보도록 하자. 컨슈머가 보내는 정보중에 oauth_consumer_key, oauth_signature, oauth_timestame 그리고 oauth_nonce 이 넷이 사용자의 정보를 보호하고, 사용자가 원치 않는 일이 벌어지지 않도록 막기 위해 사용되는 정보들이다.


가장먼저, oauth_consumer_key는 컨슈머와 프로바이더 간에 공유하는 비밀키 이다. 이 키는 재주껏 잘 보호 해야 한다. 이 키가 노출되면 그걸로 끝이다. 아무리 강력한 암호화 기법이 있어도 이 키를 공격자에게 빼앗긴다면 그냥 게임 오버다... 는 훼이크 이고, 프로바이더 입장에서는 상대가 미리 자신과 약속한 상대가 맞다는 것을 확인하고, 그 상대의 정보를 찾기 위한 용도로 사용된다.


이게 어디서 훼이크질이야!


실제로 인증하기 위해 사용되는 비밀키는 oauth_consumer_secret 이고, 이 키야 말로 공격자에게 노출되면 게임오버이다. 그러므로, 혹시나 클라이언트에 이 키를 심으려고 생각한다면 잘 생각해서 재주껏 숨겨야 한다. 만일 가능하다면 어차피 웹에 한 번 노출 되어야 하니 웹서버를 하나 두고 OAuth 프로세스는 웹서버에서 하고, 그 결과만 클라로 옮겨오는 방법을 쓰는 것도 나쁘지 않다.


oauth_signature공격자가 요청 내용의 일부를 변형해서 보내는 것을 막기 위해 사용된다. 이전에도 한번 언급을 했지만 HASH 함수들은 입력 데이터의 한 비트가 바뀌면 결과 값이 완전히 변경되는 데다가, 특정 결과 값을 얻어낼 수 있는 데이터를 찾아내는 것도 아주 어렵다. 그렇기 때문에 전송하는 데이터를 전부 다 해시 함수의 입력으로 넘겨주게 되면 공격자는 그 내용을 알더라도 조작이 불가능 하다. 조작을 할 수 있는 경우는 서명할 때 사용되는 oauth_consumer_secret을 알아내는 방법 뿐이다.


서명은 다음과 같은 방법으로 만든다. 아래 식에 사용된 버티컬 바는 비트 연산이 아니라 문자열의 합체!(Concatenation)이다.


string = 

oauth_callback | oauth_consumer_key | oauth_nonce | oauth_signature_method | oauth_timestamp | oauth_version

key = 

oauth_consumer_secret | oauth_token_secret 

          일 때

 

oauth_signature = 

HASH(string, key)

          이다

 


그냥 한 마디로 설명 하자면, OAuth 가 필요로 하는 데이터들을 끌어 모아 시크릿 키로 해시값을 계산해 낸다[각주:1]. 그러므로, 공격자가 내용을 고쳐서 공격하려고 한다면, oauth_consumer_secret을 알아야 하며, 일단 인증된 다음에는 oauth_token_secret 까지 알아야 전달되는 내용을 수정할 수 가 있다. 물론, 수정할 수 없다는 말은 그 내용을 볼 수 없다는 말과는 완전히 다른 말이다. 위의 플로우 다이어그램에서 보듯이 전달되는 내용들을 보는 데에는 아무런 제한이 없다.


다음 설명을 하기 전에 다음 그림을 잠시 보자. 다음 그림은 흔히 시행되는 Replay Attack[각주:2] 되시겠다. 공격자 맬러리는 Alice의 아이디와 패스워드도, 서명을 만들기 위한 시크릿 값도 알아낼 필요 없다. 그냥 앨리스가 밥에게 보내는 메시지를 캡쳐 해두었다가 필요할 때 재 전송 하는 것으로 앨리스 인 척 할 수 있게 된다.


인터넷의 흔한 리플레이 어택


oauth_timestampoauth_nonce는 바로 이 Replay Attack을 방어하기 위한 용도로 추가된 내용이다. oauth_timestamp는 컨슈머가 프로바이더에게 보내는 정보를 리플레이 공격하지 못하도록 하는 용도로 사용된다. 프로바이더는 컨슈머가 보낸 요청에 포함된 oauth_timestamp를 보고 요청이 제한된 시간 내에 전송되었는지 여부를 확인함으로서 재전송 공격여부를 판별한다. 예를 들자면, 프로바이더는 컨슈머가 보내준 시간을 보고 요청이 1초 이내에 도착했는지 확인을 해서 1초가 넘었다면 일단 재전송 공격이 시도된 것으로 본다는 것이다[각주:3].


타임 스탬프를 이용한 리플레이 어택의 방어



얻다대고 혀짧은 소리야!


그러나 여기에도 문제가 하나 있다. 위의 예 에서와 같이 1초를 그 한계시간으로 전했다면, 공격자가 인증 패킷을 가로채서 1초 내에 재 전송을 한다면 공격에 성공할 가능성이 아예 없는 것은 아니다.


타임 스탬프를 이용한 방어의 회피법, 그냥 조낸 빨리 보내면 된다.


그러한 공격을 막기 위해 사용되는 값이 oauth_nonce이다. nonce[각주:4]는 원타임 패스워드로 이해하는 경우도 있는, '한 번만 사용되는 값'을 의미한다. 프로바이더는 마지막으로 사용된 oauth_nonce를 저장해두고, 컨슈머가 제한 시간 내에 보내온 요청값이 마지막으로 사용되었던 nonce 값과 동일한지를 확인하여 동일한 값이라면 재전송 공격을 한 것으로 간주한다. 이렇게 함으로서 공격자가 패킷을 받자마자 재 전송 함으로서 제한 시간 내에 공격 패킷을 보내는 경우에 공격이 성공되는 것을 막는다.


타임 스탬프와 Nonce를 이용한 리플레이 어택의 방어


nonce를 사용하는 경우에, 공격자가 컨슈머가 보낸 패킷을 가로채는 방법을 이용해 공격에 성공하려면, 공격자의 패킷이 컨슈머가 보낸 패킷보다 먼저 프로바이더에게 공격자의 패킷을 보내야만 한다. 조건을 극도로 제한하면 이 방법으로 공격에 성공할 수 도 있겠지만, 일반적인 상황에서는 쉽지 않을 것 이다.


위의 절차를 거쳐 '안전하게' '실제 권한을 요청할 자격이 있는 컨슈머 임을 확인한' 다음에 사용자는 서비스 프로바이더 - 즉, 페이스 북 이나 트위터 같은 서비스 제공자의 사이트에 가서 필요한 경우 로그인을 한 후에, 컨슈머에게 권한을 부여할지 여부를 결정할 수 있게 된다. 사용자는 자기가 의도하지 않은 방향으로 자신의 정보가 제공 되거나 영역이 침범되지 않을 것을 확신 할 수 있게 된다.


마지막으로, 프로토콜을 공격하는 방법중에 가장 잘 알려진 두 가지 방법은 위에서 구구절절히 설명한 Replay Attack과 Man In The Middle Attack이 있다. 위에서 설명 했듯이 OAuth는 Replay 공격에 대한 대책이 잘 마련 되어있다. 사실 Replay Attack은 쓰기 쉬운 공격 법 이기 때문에 로그인 아이디와 패스워드를 날릴때 단순히 암호화 했다고 해서 안심하지 말고, 습관적으로 time stamp와 nonce를 추가해 주면 어이없이 보안이 뚫리는 상황이 만들어지지는 않을 것이다.


또한, 인증서를 사용해서 SSL을 통해 데이터를 전송한다 해도 비공인 인증서라면 MITM(Man In the Middle) Attack으로 뚫릴 수 있다. 그러나, SSL을 통해 전달되는 데이터를 한 번 더 살짝 위에서 설명한 OAuth의 테크닉으로 싸서 보내면 좀 더 안전해 질 수 있다. 정확히는 SSL의 MITM 공격이 성공 하더라도 공격자는 할 수 있는 일이 없게 된다. 왜? OAuth 자체가 MITM에도 안전하기 때문이다. OAuth는 미리 공유한 oauth_consumer_secret을 이용하기 때문에 설령 공격자가 전달되는 내용을 볼 수 있다 하더라도 서명에 포함된 정보의 수정이 불가능 하기 때문이다. 즉, 궂이 SSL을 사용하지 않더라도, OAuth의 방법을 사용한다면 공격자는 미리 서버와 클라이언트 간에 공유된 비밀 정보를 알아내지 않는 한 전달되는 정보를 수정할 수 없으므로 MITM에 강해진다. 그러니 SSL로 보내는 데이터를 OAuth에서 사용한 방법으로 살짝 싸주면 공격 당해도 안심! 인거다. 이경우, 패스워드를 숨겨서 전달하고 싶다면 다음과 같이 해주면 깔끔하고 안전하게 전달(?)[각주:5]할 수 있다.


string = 

userid | nonce | timestamp

key = 

secret | userpassword

          일 때

 

signature = 

HASH(string, key)

          이다.


 

더 이상 심플 할 수 없을 만큼 심플하다. 그냥 키의 제일 마지막에 사용자의 패스워드를 덧붙여서 키로 사용하면 된다. 서버 쪽에서 계산해낸 signature와 클라이언트에서 보낸 signature가 다르다면 패스워드가 틀린 것 이다. 뭐, 시크릿을 공유하는 것 조차 싫다면, 그냥 사용자의 패스워드를 키로 사용해주면 된다. string에 nonce와 timestamp가 들어가므로 설령 같은 id와 password가 사용된다 해도, 공격자가 훔쳐보는 내용은 매번 다른 데이터가 암호화 되어 전달 되는 것 처럼 보일 것이다.


4. 결언


설령 OAuth 자체를 사용할 일이 없다 하더라도 OAuth에서 사용한 프로토콜은 게임에서 사용되는 데이터를 주고 받을 때 그 정보를 숨겨야 하는 상황에서, 혹은 전달되는 데이터를 임의로 수정하는 일이 없어야 하는 상황에서 아주 유용하게 사용할 수 있다. time stamp, nonce 그리고 HASH를 이용한 signature의 사용법을 익히는 것 만으로도 꽤 안전한 통신을 즐길 수 있으리라 믿는다. OAuth는 수 많은 전문가들이 오랜시간 고민해서 만든 프로토콜 스펙이니 만큼, 이걸 뜯어 보는 것 만으로도 충분히 안전한 통신 프로토콜을 만드는데 필요한 지식들을 얻을 수 있으리라 본다.


추가적으로, OAuth 자체를 칭찬한다면, OAuth는 인증(Authentication)과 권한부여(Authorization)를 분리해 준다는 것 이다. 인증 - 즉 로그인은 무조건 프로바이더 페이지를 통해야만 하도록 함으로서 사용자의 비밀 정보가 빠져나갈 가능성 자체를 차단해 주었다. 그리고 권한부여 라는 절차를 거쳐서 서드파티가 제공하는 기능들을 편안하게 이용할 수 있도록 하였다.


사실, OAuth 자체는 웹 환경에 최적화 되어있는 프로토콜 이기에 앱에 도입 하기엔 불편함이 많은 것은 사실이다. 위에서 말한 장점인 '반드시 프로바이더 페이지를 통해서 로그인'하는 기능을 앱에서 사용하려면 실제 사용할 앱 외에 브라우저를 실행시키고, 브라우저에서 제공하는 정보를 다시 앱에 입력해야 하는 절차를 거쳐야만 한다. 당연히 사용하려는 프로그램 외의 다른 프로그램을 실행시켜야 한다는 것은 부담이 될 수 도 있고, 불편한 것은 사실이다. 그러나, 비록 조금 불편 하다 할 지라도 고객은 새로운 사이트에 별도의 회원가입을 하지 않아도 된다는 잇점에 대해선 만족할 것이며, 기존에 회원 가입했던 트위터나 페이스북을 통해 인증을 받을 뿐 아니라, 그런 서비스를 함께 쓸 수 있다는 것에 대해서도 만족할 것이다.


OAuth의 메인 목적은 인증이 아니라 권한부여 쪽이다. 그러므로 서비스 프로바이더의 인증 기능을 이용하기 위해 OAuth를 이용하는 것은 그다지 좋은 생각은 아니다. 만약 인증을 받는 쪽에 대하여 고민을 하고 있다면 OAuth가 아니라 Open ID에 관심을 가져보길 권한다.


*     *     *


OAuth 덕분에 이 미천한 필자의 놀게영 체제 기간이 늘었습니다. 우화화화홧! 다음 번 부터는 보안 쪽 말고 완전 초보자를 위한 초보자의 게임 제작 삽질기 라도 올려야 겠습니다. 그러다가 OAuth 같이 섹쉬한 보안 프로토콜을 발견하면 소개해 드리는 쪽으로 가닥을 잡기로 했습니다. 이상, 놀게영에서 천년만년 필자질을 하려고 음모를 꾸미고 있는 죠쉬 였습니다.


  1. OAuth를 실제로 사용하고자 하는 사람들이 주의할 점이 있다면, 여러번 반복하게 되는데, 해시 함수는 한 비트만 달라져도 결과가 완전히 달라지므로, 해시 연산을 하기 위한 데이터의 순서가 아주 중요하다. [본문으로]
  2. Replay Attack ; 이전에 정당한 사용자가 보낸 메시지를 캡쳐하여 저장해 두었다가 단순 재전송 함으로서 공격하는 방법 ; 아이디와 패스워드가 암호화 되어 전송되는 경우, 공격자는 정당한 사용자가 입력한 아이디와 패스워드를 알아내기 위해서는 암호를 깨야 한다. 그러나, 아이디와 패스워드가 항상 같은 방법으로 암호화 된다면, 공격자는 궂이 암호를 깰 필요없이 암호화된 아이디와 패스워드를 그냥 재전송 해주는 것으로 공격에 성공할 수 있다. [본문으로]
  3. 물론, 실제로 1초라는 것은 아닙니다. 그 시간은 서비스 프로바이더가 임의로 결정하게 됩니다. [본문으로]
  4. nonce는 원래 그 자체로도 replay attack을 막는 용도로 사용이 됩니다. 어떤 데이터를 서버로 암호화 해서 보낼 때 서버에서 nonce를 받아 그 값을 암호화 하는 데이터에 포함시켜 보내줌으로서 replay attack을 막습니다. 물론 서버는 클라이언트가 nonce를 요청할 때마다 다른 값을 리턴해 주어야만 replay attack을 막을 수 가 있겠지요 [본문으로]
  5. 실제로 패스워드 자체가 보내지는 것은 아니니 패스워드를 전달 한다고 말 할 수는 없다. 단지 패스워드를 검증하기 위한 정보가 전달될 뿐이다. [본문으로]
반응형
,
Posted by 알 수 없는 사용자

안녕하세요?

몇차례나 펑크를 내고 있는 비인기 포스트 == 네트워크 게임 튜터리얼의 백수 히키코모리 변태, 요망한 김레아입니다.

적고 있던 "네트워크 게임 튜터리얼 6 - 유저풀"편이 아직 완성이 덜되었기 때문에 부득이하게 번외편이 나갑니다.

 

원래 게임데브포에버용 글이 아니었기 때문에 평소에 달리 존댓말 대신 반말이며 읽는 재미도 떨어질 것입니다만,

요즘 아는 분들 사이에 뜨고 있는 WebSocket, node.js, Socket.IO에 대한 C/C++ 프로토콜 분석기입니다.

 

이게 무엇인지 이해 가지 않고 게임이랑 무슨 상관있는지 멍~하실 분들이 많으실텐데요,

분명 상관있고 조만간 판도를 뒤짚을 기술입니다.

웹프로그래머분들의 시선이 아닌 Native 개발자의 시선이므로 도움이 되실꺼라 믿으며,

다음 본강을 기대해주시길 바랍니다.

 

 

반도의 돌직구녀. 이런게 바로 제대로

반도의 돌직구녀. 이런게 바로 제대로 "배운 녀자"지.


돌직구녀에게 감동을 받아 돌직구 포스트 한번 적어본다.
제목처럼 C/C++로 Socket.IO에게 돌직구 던지는 법이다. Socket.IO가 뭔지, 게임이랑 무슨 상관인지 어쩌구 저쩌구하는 머 그런 대딩같은 질문들은 일체 사절하도록 한다. 나중에 유료 세미나에서 돈내고 듣길 바란다.
돌직구는 언제나처럼 Socket으로 던진며, 당연히 BSD든 Winsock이건 똑같다.
아, Socket.IO 버전은 v.9.

1. 일단 주워보자.
있는 것을 다시 만들 필요없다, Socket.IO 홈페이지(http://socket.io/)와 github(https://github.com/)를 뒤졌다.
우선 홈페이지에는 얼랭, 안드레기, 자바, 루아, 오브젝레기-C, 펄, 고, 피똥, 루비, 플레기, 다 있는데......C++만 없었다. -_-
github와 구글느님께 도움을 요청했다.

아크데몬이 지저분한 소스에 기분이 상해버렸다.

아크데몬이 지저분한 소스에 기분이 상해버렸다.


딱 하나 나왔다.
요즘은 오픈소스도 참 잘 만들고 정리가 잘 되어 있는데 이건 마치 90년대 슬랙웨어를 보는 듯한
푸세식 화장실에서 건져올린 느낌의 C++ 프로젝트가 하나 나왔다.
물론 빌드도 제대로 안되고 에러처리로 제대로 안되어 있어 도저히 사용할 수 없었다.
이런거나 만들라고 공개된 Boost.Asio가 아닐텐데... .
간만에 코딩을 해야할 운명에 처했다.

2. RFC 6455
그래서 다른 언어로 된 Socket.IO 클라이언트를 읽고 C/C++로 포팅할려고 했다.
대부분 이미 구현된 WebSocket 클래스 위에 Socket.IO용 JSON 프로토콜을 올린 식이었다.
하지만 문제는 WebSocket이 이미 Fix된 프로토콜이 아니란 점이다.
소스들이 제각각 달랐다. 이래저래 별 도움이 안됐다. 역시 이 넘들에게 기대한 내가 바보였어.

할수 없이 RFC 6455(http://tools.ietf.org/html/rfc6455) 문서와 Socket.IO 문서(https://github.com/learnboost/socket.io-spec)를 읽었다.
오오미, 신기술답게 "ws://"도 등장한다.
하지만 우리들은 http든 ws든 그게 그거라는 것을 잘 알고 있다. GET이나 POST냐 PUT이냐 그런게 문제지.

이보다 더 자세한 설명이 있었는데 찾기 못하겠다.

이보다 더 자세한 설명이 있었는데 찾질 못하겠다.


하지만 단순히 WebSocket을 구현하는 것만으로는 안된다.
Socket.IO에게 WebSocket으로 접속하는 것 이전에 Socket.IO의 프로토콜의 알아야 하기 때문이다.

3. 뜯기

결국 직접 구현하기로 맘을 먹었다.
나에게 도움을 주실 분은 Fiddler2(http://www.fiddler2.com/fiddler2/)와 TCPView.
Fiddler2는 웹개발자를 위해 탄생한 툴이나 웹개발자보단 내 경험상, 항상 C/C++ 클라이언트 개발자들이 써왔다.

하악하악 섹시한 바이올린으로 갈것 같다.

하악하악 섹시한 바이올린으로 갈것 같다.


서버 소스는 구글에서 가장 먼저 검색된 http://psitsmike.com/2011/09/node-js-and-socket-io-chat-tutorial/ 를 쓰기로 했다.
블로그가 분홍색으로 알록달록하지만 분명 블로그 주인은 넷카마남자일꺼다.
......트위터 털어보니(사실은 링크) 남자분 맞으시네, 포스트 다 적고 인사하고 팔롱해드려야지.
아뭏든 우리의 피들러2느님께서 딱 잡아주신다.


암튼 뒤에 체크한 두개가 소켓으로 구현해야하는 부분이다.
마지막 접속 부분이 중요한데 만약 WebSocket을 지원하지 못하는 브라우저라면,
"/socket.io/1/xhr-polling/15479987321848421359?t=1339783678755" 식으로 XMLHTTPRequest로 접속할 것이다.
이는 실제 소켓 연결이 아니라 계속 요청을 보내 데이터를 가져온다는 뜻이다.
스마트 디바이스에 이런 연결을 하면 이통사에서 존나 싫어할 것 같다.ㅋㅋㅋㅋ

결국 웹브라우저가 아닌 소켓의 입장에서는

1) 접속
2) 클라이언트에서 만든 Timestamp용 랜덤키값 전송
3) Session ID와 사용가능한 Transport ID 받음
4) websocket 혹은 XMLHTTPRequest 방식으로 가져올 것인지 선택
5) XMLHTTPRequst 라면 계속 접속을 하여 데이터 획득
6) WebSocket이라면 실제 전송을 위해 새 Transport 연결 획득
7) 지정된 시간만큼 핸드쉐이킹
8) Socket.IO에서 지정된 JSON 프로토콜대로 데이터 주고받기

이다. 랜덤키를 클라이언트에서 만드는게 독특하다. 그리고 랜덤키가 없어도 세션ID는 돌아온다.
세션 ID는 Socket.IO 모듈의 manager.js의 691 라인의 이 부분이라 추측된다.
그냥 현재 시각을 이용한 랜덤이다.

/**
* Generates a session id.
*
* @api private
*/

Manager.prototype.generateId = function () {
return Math.abs(Math.random() * Math.random() * Date.now() | 0).toString()
+ Math.abs(Math.random() * Math.random() * Date.now() | 0).toString();
};

문제는 헤더에 실수가 있을 경우 에러값도 전혀 없이 접속을 종료한다. 즉 접속하고 아무 데이터나 보내면 그냥 close시켜버린다.
처음 이것 때문에 고생 좀 했다.

4. 구현
4.1 접속 및 세션 ID얻기
웹브라우저가 아닌 Winsock으로 하니 피들러2가 보여준 HTTP 요청들이 대거 축소되었다.
몇번이나 예제로 나간 MFCClient.sln을 고쳐 HTTP 요청을 보내도록 하였다.
주소 이후 URL은 "socket.io/1/?t=타임스탬프(랜덤)13자리&jsonp=0" 이다.

CString strHead = "GET " + strFileURL + " HTTP/1.1\n\n";
m_pClientSocket->Send(strHead, strHead.GetLength(), 0);

참고로 1.1로 요청하면 HTTP 연결형으로 접속이 된다.
1.0으로 요청하면 응답 후 소켓이 끊어지는 것을 눈으로 확인할 수 있다(직접 확인해보길 바란다.)
대부분이 잘못 알고 있는 것과 달리 현재 HTTP는 매회 요청시 Connection 요청을 하지 않는다.
따라서 WebSocket, 아니 서버에서 클라이언트로 메시지를 뿌리는 것도 가능한 것이다.
사실 WebSocket 자체는 결코 신기한 기술이 아니다.
HTTP 1.1부터는 1.0과 달리 연결이 항상 맺어져있다고 생각하면 무엇이든 이해가 될 것이다. 끊어지면 다시 연결하면 되는거고.

Connection: Keep-Alive에 주목! 그리고 세션 ID를 얻어왔다.

Connection: Keep-Alive에 주목! 그리고 세션 ID를 얻어왔다.


세션 ID(149821928277990092)를 얻어왔다.

세션 ID와 함께 날라오는 것은 Transport ID로 websocket, htmlfile, xhr-polling, jsonp-polling 이란 메시지이다.
이것은 세션 ID만큼 중요한데 이 클라이언트가 구현할수 있고, 서버가 응답가능한 통신 프로토콜들 리스트다.
즉, 이 포스트의 핵심인 websocket도 쓸수 있고, 계속 HTTP 요청으로 무식하게 htmlfile을 요청할수도 있고,
XMLHTTPRequest나 JSON Padding으로 구현할수도 있다는 이야기다.
물론 이것은 Socket.IO에서 설정한 대로 나오게 된다.

var serverSocket = socketio.listen(server);
serverSocket.set('transports', ['websocket', 'flashsocket', 'xhr-polling']);

이런 식으로 말이다.
이게 바로 Socket.IO의 역활이다. 어떤 웹브라우저라도 연결된 것처럼 써먹을 수 있게 해주겠다는 것이다.

물론 우리는 다른 것 다 필요없다, 웹브라우저가 아니니까 오직 WebSocket만 쓰면 된다.
위에도 적었지만 어떤 이유로 폴링 방식을 쓰겠다면 서버에도 xhr-polling 을 선언해주고 클라이언트는 "/socket.io/1/xhr-polling/세션ID?t=아까 정한 랜덤키"로 요청을 계속하면 된다.

4.2 Transport connection
드디어 HTTP가 아닌 "ws://" 프로토콜을 구현할 시간이다.
앞서 말한 것처럼 그래봤자 GET으로 요청하는 것에 불과하다.
위키피디아(http://en.wikipedia.org/wiki/WebSocket)에서 가져온 헤더들을 적자면,
요청시

GET /mychat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

로 보내면 서버는

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

라고 보내준다고 한다.
핸드쉐이킹을 위해 클라이언트에서 랜덤하게 생성한 Sec-WebSocket-Key가 어떤 알고리즘으로 Sec-WebSocket-Accept로 바뀌는지는 역시 RFC 6455 에 친절히 설명되어 있다. WebSocket을 위한 GUID인 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"붙여 SHA-1과 Base64로 지지고 볶는데 서버를 만들 것이 아니라면 큰 관심을 가질 필요는 없을 것 같다.
다만 클라이언트에서 정하는 Sec-WebSocket-Key는 16자리 랜덤키를 Base64로 뽑아낸 것임은 기억할 필요가 있다.

테스트 삼아 대충 아래와 같이 헤더를 만들어 보냈다.
소켓은 더 만들 필요없고 첫 HTTP 접속에 사용한 소켓을 그대로 사용하면 된다.

CString strSessionID;
GetDlgItem(IDC_ADDRESS2)->GetWindowText(strSessionID);

CString strHead2;
strHead2 = "Upgrade: websocket\n"
"Connection: Upgrade\n"
"Host: localhost:8080\n"
"Origin: http://127.0.0.1:8080\n"
"Sec-WebSocket-Key: MTIzNDU2Nzg5MDEyMzQ1Ng==\n"
"Sec-WebSocket-Version: 13\n\n"
"Sec-WebSocket-Extensions: x-webkit-deflate-frame\n";

CString strHead = "GET /socket.io/1/websocket/" + strSessionID + " HTTP/1.1\n" + strHead2;
TRACE ("%s\n", strHead);

m_pClientSocket->Send(strHead, strHead.GetLength(), 0);

거지같은 소스지만 연결은 훌륭하게 잘된다.
문자열 파싱 좀 붙여 주소랑 포트, 그리고 랜덤하게 Sec-WebSocket-Key만 정해주면 훌륭해질 것이다.

WebSocket 연결 성공

WebSocket 연결 성공


4.3 Socket.IO Data Frame(혹은 Framing)
정말로 채팅이 될까? 기존 웹채팅이랑 통신해보자.

서버와 접속이 된 상태이니 당연히 메시지를 받는다.

폴링따윈 껒!!

폴링따윈 껒!!


이제 데이터를 보내보자, 진정한 돌직구다.
결론적으로 Socket.IO에서 설명하고 있는 JSON 형식을 그대로 보내서는 안된다. 또 연결이 끊길 것이다.
그러나 WebSocket이 연결된 이후 데이터 전송에 대해서는 Fidder2로도 잡을수 없다.
왜냐면 WebSocket으로 Switching이 된 이후부터는 HTTP 가 아니라 일반 소켓 접속이기 때문이다.
크롬 + 외부 서버 + WireShark를 돌려봤지만 이렇다 할 답은 찾지 못했다. 크롬이 일반 binary로 통신하기에 데이터 모습도 모른체 binary를 뜯기는 너무나 힘이 든다.

Switching Protocol을 받은 이후(WebSocket으로 구현된 후), 패킷 데이터 구조체는 역시 RFC 6455 문서에 적혀있다.

WebSocket Data Framing

WebSocket Data Framing


 

아... 솔까 이런 그림만 보고 코딩하라면 나도 당황스럽다...

아... 솔까 이런 그림만 보고 코딩하라면 나도 당황스럽다...


이것을 C/C++로 옮겨보면,

string payload = "Socket.IO에 정의된 JSON 문자열";
payload = AnsiToUTF8(payload); // UTF-8로 보낸다.

char frame[131];

frame[0] = '\x81';
frame[1] = 128 + payload.length();
frame[2] = '\x00';
frame[3] = '\x00';
frame[4] = '\x00';
frame[5] = '\x00';

_snprintf(frame+6, 125, "%s", payload.c_str());


int iRet = m_pClientSocket->Send(&frame, payload.length() + 6, 0);

이런 형태가 된다.
아래 짤이 구현된 모습이다. C/C++소켓에서 보낸 "Hi, Hi"란 메시지가 웹브라우저에게 나타나고 있다.

돌직구 완성.

돌직구 완성.


아쉽게도 WebSocket은 한번에 최대 125byte밖에 보내지 못한다.
가장 앞의 "0x81"은 이 패킷이 단일 패킷(single-frame)이라고 상대에게 알려주는 것이다.
따라서 125 이상되는 내용을 보내고자 한다면 Socket.IO에게 보낼 JSON 데이터(상기 소스에서 string payload)를 길이에 맞게 나눠 가공하는 작업이 필요하며, 첫 패킷의 앞부분은 "0x01", 두번째 패킷부터는 "0x80"로 보내야 한다.
binary 데이터를 보낼려면 "0x82"를 붙여야 하지만 node.js의 속력을 감안하면 binary는 IIS같은 웹서버를 이용하는게 좋을 것 같다.

close()쪽은 특별히 신경쓸게 없는 것 같다. 그냥 close() 호출해줘도 node.js나 Socket.IO에서 에러는 나지 않았다.

5. 결론
이 포스팅을 하는 현재, 그 어느 소스도 맘에 들게 정상적으로 작동하는 것을 보지 못했다.
오픈 소스 대부분이 외국 학생들의 숙제였던 경우가 많고 WebSocket 프로토콜과 Data-Framing 규약이 그간 엄청나게 빠른 속도로 바뀌었었기 때문이다.

지난 일주일...

지난 일주일...


나 역시도 인터넷 검색하며 오래전 규약의 문서(현재 Socket.IO v9이 사용하는 WebSocket에 맞지 않는)들을 보며 수많은 함정에 빠졌었다.
마지막엔 WebSocket이 아닌 Socket.IO의 변태같은 JSON 프로토콜에 이틀밤을 낭비했다.
조금더 정리해서 나두 github같은데 올려볼까 한다.

전부 완성하고 보면 언제나 그렇듯 별 게 없다.
WebSocket 프로토콜과 Socket.IO도 또 언제 바뀔진 모른다.
그러나 힘들게 한번 구현하고 나니 앞으로 바뀔 모습도 예상되고 빨리 적용할 것 같다.
가장 중요한 것은 웹브라우저로 서비스할 것이 아니니 버전을 Fix 시켜놓고 그것만으로 운영해도 무리는 없을 것 같다.
이 엉망인 문서도 혹시 WebSocket을 쓰고자하는 진취적인 개발자들에게 작은 도움이 되길 바란다.
아무것도 아니지만, 나름 일주일 고생했다. 레알.

분석 마쳤으니 나는 다시 잉여질이나 해야지~

분석 마쳤으니 나는 다시 잉여질이나 해야지~

 

 

 

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


저는 백수라서 잘 모르지만, 어떤 곳에서 이런 재미있는 연구들을 바탕으로 빅재미 넘치는 게임을 만들꺼라고 하오니,

관심있으신 분은 트위터 @RheaStrke_DEV 로 연락바랍니다. 제가 주선해드림.



 

반응형
,
Posted by ozlael

지난 번 글에서 이어지는 글입니다.

이전 글 : PC에서 3D 입체 영상 게임 개발하기 #2



들어가며

그동안은 재미 ㅇ벗는 내용 읽어주시느라 수고 많으셨습니다. 이번 시간부터는 재미 없는 이야기 말고 본격적으로 PC 게임에 입체 영상을 적용 할 수 있는 방법을 알아보기로 하겠습니다. 아니 어쩌면 이번 시간부터가 더 재미없고 지루해질 수도 있겠네요. 하지만 별로 어려운 내용은 없으니 그냥 편안히 읽어주시면 감사하겠습니다.



미들웨어

그럼 과연 PC에서 입체 영상을 적용하려면 어떻게 해야할까요? 디스플레이 장치도 애너글리프, 셔텨그래스, 편광안경 등 많은 종류에 따라 직접 구현을 해줘야할까요? 셔터그래스 방식이면 좌안 우안 영상을 각각 직접 따로 만들어서 프레임에 맞게 번갈아가며 직접 출력해줘야할까요? 편광안경 방식이면 해상도에 맞춰서 도트를 좌안 우안 번갈아가며 직접 찍어줘야할까요? 애너글리프(적청안경) 방식이면 다행히 하드웨어를 타지 않아서 직접 만들어 출력 해 줄 수도 있습니다. 옛날에는 애너글리프를 직접 구현해서 발매된 게임들도 존재하구요.

이미지 출처 : wikipedia

하지만 서울-대전을 2시간이면 주파하고 그 안에서 스마트폰으로 RPG를 즐기는 현대에서도 저렇게 직접 노가다를 해 줘야 할까요? 당연히 아니지요. 그냥 우리는 그동안 개발하던대로 그냥 개발하면 되고 미들웨어의 지원을 받으면 됩니다. 미들웨어의 요구에 맞게 아주 약간(혹은 매우 많이;;) 신경써주기만 하면 자동으로 입체 영상이 탄생하게 되지요.

 

반응형
,