게임 데이터 작성하기 1
보통 프로그램을 작성할 때에는 필요한 데이터를 읽고, 해석하여 동작하는 구조로 많이 작성한다. 게임 역시 마찬가지의 구조를 갖는데, 데이터의 종류가 좀 많고, 상호 연관성이 있으며, 양도 꽤 많다는 점이 특징이라 할 수 있겠다.
나는 회사에서 게임 코딩을 할 때 보통 다음의 순서로 진행했다.
- 기획서/사양서를 보고 대충 시스템을 설계한다.
- 기획자가 데이터를 입력할 수 있도록 적절히 코드와 데이터를 분리한다.
- 기획자에게 데이터 구조를 알려주고(예제 전달 등) 유지 보수를 진행한다.
기획자가 데이터의 구조를 잡아서 주는 경우도 있지만 (합의 하에) 구조를 변경하여 진행하였으므로 사실상 프로그래머 주도로 데이터가 설계된 것이다.
완벽하게 독립적인 기능을 만든다, 라는 것이 가능할지는 모르겠지만 적어도 게임 데이터가 그런 경우는 없는 것 같다. 즉 하나 이상의 다른 기능과 연관된 데이터를 작성하게 된다는 것이다. 경험상 위처럼 데이터를 작성할 경우 데이터의 구조가 금새 엉망이 되었고 흐트러지기 일쑤였다.
프로그램을 먼저 작성하고 데이터의 구조를 나중에 잡는 경우에는 프로그램에서 읽기 편한대로 데이터를 작성하게 되는 경우가 많고, 그 과정에서 데이터의 정합성이 깨진다거나 미처 고려하지 못한 많은 요소들로 인해 문제가 발생했기 때문이다. (데이터 입력이 불편함, 연관된 데이터를 찾기 어려움, Localization 작업이 어려움 등)
따라서 데이터를 먼저 설계하고 그에 맞추어 프로그램을 작성하는 것이 좋다는 이야기를 시작해보려 한다.
데이터를 설계할 때 적어도 다음의 요소에 대한 고려가 필요하다고 생각한다.
- 데이터 입력이 편리한가?
- 데이터 구조를 직관적으로 이해할 수 있고, 컨텐츠와 연결지어 생각할 수 있는가?
- 업데이트 히스토리를 기록하기 용이한 구조로 작성되었는가?
- 하나의 파일에 하나의 의미를 지니는 데이터가 들어가 있는가?
- Localization 작업이 수월한가?
- 서버, 클라이언트, 툴에서 읽기에 무리가 없고, 각자 필요한 데이터가 잘 분리되어 입력된 구조인가?
- 각 데이터의 식별자는 명확한가?
- 연관성을 데이터 수준에서 검증할 수 있는가?
- 형 검사(type validation)가 가능한 형태로 작성되었는가?
- Branch와 Merge에 견고한 구조로 작성되었는가?
더 많이 있겠지만 일단 생각나는대로 적다보니 부족한 내용이 있을텐데 글 쓰다보면 기억날 것이라 믿고 일단 넘어간다-_-
대충 묶어보면 작업 편의성, 직관성, 식별성, 정합성 정도가 될 것 같다.
직관성, 편의성
데이터의 직관성은 작업 편의성과도 연결된다.
데이터가 직관적으로 작성되어 있어 그 의도에 대해 원 시스템 설계자에게 물어보거나, 다른 문서를 찾아볼 필요가 없다면 최고이다. 게다가 직관적이면 입력하기 어렵지도 않을테니 작업하기도 쉽다. 더 나아가서 데이터를 읽는 것 만으로 시스템의 의도를 이해할 수 있고 해당 컨텐츠에 대해 이해할 수 있다면 정말 좋을 것이다. 그리고 해당 데이터의 변경 사항을 버전 관리 도구로 파악하여 이전 작업자의 의도까지 파악한다면?
꿈 같은 소리라고 생각할 수 있지만 의외로 프로그래머에게는 익숙한 내용이다. 직관적으로 작성된 코드는 그 의도에 대해 원 작업자에게 물어볼 필요도 없이 이해가 가능하고, 해당 코드를 읽는 것만으로도 컨텐츠에 대해 이해할 수 있고 유지보수 하기도 쉽다. 그리고 버전 관리 도구의 로그를 통해 변경 사항과 그 의도를 파악할 수 있다.
필요한 부분에만 주석으로 정보를 추가한다. 너무 많은 주석은 주석에 대한 유지 보수 비용이 발생하기 때문이다. 해당 코드를 설명하는 추가적인 문서를 작성했다면? 주석에 대한 유지 보수 비용보다 더 큰 비용이 발생하기 때문에 오히려 더 비효율을 야기하는 작업일 것이라 생각한다. 즉 코드를 직관적으로 잘 작성하는게 최고라고 생각한다.
코드가 되는데 데이터가 안 될리가 없다. 다만 데이터 입력은 생각보다 중요한 작업이 아니라고 생각하기 때문에 대충 돌아가는 수준으로 데이터를 입력하는 경우가 많고, 그 때문에 대충 작성한 코드처럼 난해하고 작성하기 어려운 구조의 데이터가 만들어지게 되는 것이다.
프로그래머가 깨끗한 코드를 작성하려 노력하는 것처럼 데이터 작성에 있어서도 깨끗한 데이터 작성을 위해 노력해야 한다는 것이다. 제발 key 이름을 a, b, c 이런 것 좀 쓰지 말고. 그리고 버전 관리 도구에 변경 사항에 대한 로그는 빈 칸으로 남기고 업데이트 히스토리를 따로 작성해서 남기지 말고, 제발 좀!
툴
직관적으로 작성된 데이터가 literal programming 수준으로 진화하다보면 데이터가 소설이 되는 경우가 있다. 개인적으로 그러한 경향이 옳은지는 잘 모르겠는데 이것을 작업 편의성과 묶어서 생각해보면 좋을 것 같다.
패키지 게임을 만들거나, 3달 서비스할 게임을 만들면 상관이 없겠지만 만약 그보다 더 긴 기간의 서비스를 진행하는 게임이라면 데이터 작업이 쉽도록 데이터가 설계되어야 한다. 하지만 직관성과 충돌이 발생할 경우에는 반드시 직관성을 우선해야 한다고 생각한다. (입력하기 귀찮다고 key 이름을 a, b, c로 짓지 말고 좀!)
그렇다면 어떻게 하면 직관성과 편의성을 모두 얻을 수 있을까? 그것을 위해 필요한 것이 툴과 스크립트라고 생각한다.
툴을 통한 데이터 template, scaffolding, assist 등을 지원하고 스크립트를 통해 대규모 작업을 쉽게 수행할 수 있도록 한다. 기획자들은 툴 + 스크립트
를 Excel + VBA
로 사용하는 경우가 많기 때문에 별도의 툴을 만들어준다고 해도 잘 쓰지 않는 경우가 많다. 때문에 툴 + 스크립트
를 VSTO Excel + C#
으로 해결하는 것이 현재는 가장 합리적인 해결책이라고 생각한다. 이에 대해서는 추후 다른 글에서 다루도록 하겠다.
결국 적절한 툴/스크립트가 제공되어 기획자들의 작업 효율이 향상될 수 있도록 해야 한다는 것인데 이 때 고려할 점은 다음과 같다고 생각한다.
- 최대한 단일 툴에서 모든 데이터를 다룰 수 있도록 구현
- 툴만 봐도 게임이 어떻게 흘러가는지 알 수 있도록 직관적으로 구성
- 반드시 툴을 사용하지 않아도 데이터 작업이 가능할 수 있도록 작성
- 툴로 인해 생성되는 임시/중간/결과 파일 등이 merge 가능한 형태가 되도록 구성
- 툴에서 데이터의 유효성 검사가 가능하도록 구현
- 가능하다면 인-게임 툴로 구현
- 이것 역시 VSTO Excel 이야기할 때 같이 이야기해보도록 하겠다.
데이터 정의
프로그램을 잘 작성하기 위해 먼저 큰 그림을 그린다. 데이터 역시 마찬가지로 데이터가 어떻게 작성되어야 할지 설계를 해야 한다. (보통 이런 작업을 안하고 데이터를 만들다보면 모든 자잘한 데이터가 다 담긴 창고(warehouse) 파일 같은 것이 생긴다.)
데이터를 설계할 때에는, 약간 과하게 생각해본다면 RDB처럼 설계할 수 있다. 각 데이터가 고유 식별자를 갖고(Primary-Key) 다른 데이터를 참조(Foreign-Key) 할 수 있는 것이다. 그리고 여러 제약 조건을 가질 수 있도록 만든다. 이러한 정보는 metadata에 속하니 이를 기록할 수 있는 파일을 먼저 만든다. 보통 data definition이라고 하는데 직접 언어를 만들어서 서술해도 좋고 XSD 같은 것을 사용해도 좋다고 생각한다.
위와 같은 작업을 해두면 무엇이 좋을까?
- 데이터만 보고 컨텐츠 간의 명확한 연관관계를 파악할 수 있다. (참조 그래프를 제대로 그렸다면)
- 데이터의 정합성을 쉽게 판단할 수 있다. (해당 아이템에 연결된 퀘스트가 존재하지 않습니다. 즉 퀘스트만 삭제함)
- 데이터의 형 오류를 쉽게 판단할 수 있다. (공격력에 0.5 입력해봐야 서버에서 int로 읽으면 0이다)
- 데이터의 연결성을 파악할 수 있으니 데이터 template 작성에 좋다. 즉 scaffolding이 쉽다.
- data definition 기반으로 model, parser 등의 코드를 자동 생성할 수 있다.
- 고유 식별자를 통해 데이터의 변경점을 원자적으로 분리할 수 있고 이는 데이터 merge에 큰 도움이 된다.
- 6번 항목에 대해서는 데이터 merge 글에서 다시 다루도록 하겠다.
당연한 이야기를 써놓은 것 같지만 의외로 잘 지켜지지 않는 내용들이다.
데이터를 설계를 먼저하고 데이터를 입력한다는 것은 data definition을 먼저 작성하고 실 데이터를 입력한다는 것이기 때문에 기존 데이터의 구조를 고려하여 새로운 데이터의 식별성, 연관성, 형, 제약 조건들을 먼저 입력한다는 것이다. 보다 주의깊게 데이터를 설계하게 될 것이라고 생각한다. (물론 이를 도와주는 적절한 data design가 있으면 더욱 좋을 것이다.)
반면 데이터를 먼저 입력하고 그것을 기반으로 data definition을 만들어냈을 경우 data definition이 제대로 만들어지지 않을 가능성이 높다. 좁은 시야로 자기가 원하는 데이터를 작성하기 때문인데, 실제로 회사에서 클라이언트 개발자와 서버 개발자가 작성한 같은 컨텐츠의 다른 데이터의 정합성이 전혀 맞지 않는 문제가 있었다-_-
하나의 동일한 의미를 가리키는 key가 전혀 달라서 발생한 문제인데 그 이유는 단순히 서버/클라이언트에서 각자 읽기 쉬운 구조로 데이터의 식별자를 정의하였기 때문이다. 이 데이터는 추후 data definition 정리 및 툴 작성의 가장 큰 걸림돌이 되었다.
- localization 관련 내용에 대해서는 추후 다른 글에서 다루도록 하겠다.
정리
대충 썼는데 요약하면 데이터를 입력하기에 앞서 data definition을 먼저 잘 정의하자는 것이다.