데이터베이스가 고장 나면 게임이 어떻게 동작해야 하나요?

생각보다 드물지 않게 게임의 일부에 장애가 발생하면 나머지 부분이 어떻게 동작해야 할 지에 대한 게임디자인 관점의 대책을 제시할 것을 요구받습니다. 이 요구는 올바르지 않다고 생각합니다.

데이터베이스가 고장 나면 게임이 어떻게 동작해야 하나요?

게임디자이너는 종종 협업 부서로부터 나온 모든 질문에 제대로 대답해야만 한다는 압박에 시달릴 때가 있습니다. 특히 시스템디자이너는 우리들이 작성한 기획서에 따라 개발하던 엔지니어가 하는 모든 질문에 올바르게 대답하거나 그들이 질문하기 전에 질문을 예상해 기획서에 그런 내용을 포함해야 한다는 말을 들을 때가 많습니다. 이런 접근은 어느 정도 기획서를 잘 작성하게 만들어 주기도 하지만 때때로 게임디자이너의 업무 범위 바깥의 고민을 하게 만들어 지식이 부족한 상태로 이상한 대답을 하거나 이상한 요구사항을 문서에 작성하게 될 수 있습니다. 게임디자이너는 근본적으로 고객에게 의미 있는 경험을 주고 또 우리들 스스로의 급여를 책임지는 소프트웨어 서비스를 개발해 내는 역할을 합니다. 이 때 어느 정도 의사소통을 위해 직군 바깥의 지식을 가지고 여러 질문에 대답할 수 있으면 도움이 되지만 그런 소양이 필수는 아닙니다. 이전에 경험한 사례들을 살펴보며 이야기해보겠습니다.

어느 프로젝트에 참여해 이전에 만들어진 기획서와 데이터들을 살펴보다가 이해가 안 되는 부분을 발견합니다. 플레이어는 게임을 진행함에 따라 여러 가지 경로로 장비와 장신구를 획득한 다음 이들을 장착해 강해지고 장비와 장신구 각각은 성장 재료를 통해 더 강해지는 구조를 의도하고 설계되었을 것이 분명한 데이터 정의가 기획서에 언급되어 있었습니다. 장신구 하나는 성장 재료를 투입할 때마다 단방향으로 성장하고 고객은 이 장신구가 최대 어느 정도 수준까지 성장할지 미리 최대 수치를 확인할 수 있습니다. 이 때 장신구는 그 등급에 따라 더 긴 구간에 걸쳐 성장하기도 하고 더 짧은 구간에 걸쳐 성장하기도 하기 때문에 장신구를 획득한 다음 장신구의 등급과 최대 성장 가능성을 살펴보고 이 장신구를 현재 장착하고 있는 장신구 대신 장착할지, 그리고 이 장신구가 본격적인 성능을 발휘하기 위해서는 얼마나 더 플레이 해야 할 지, 그리고 앞으로 더 나은 장신구를 파밍할 때까지 얼마나 더 플레이 해야 할 지, 그 동안 새 장신구를 어디까지 성장 시킬 수 있을지 등을 판단해 장신구 교체 장착 여부를 판단하도록 합니다. 장신구 각각은 이를 장착함에 따라 몇 가지 스테이터스를 추가 획득할 수 있는데 이들을 나열한 엑셀 파일은 대략 장신구 하나가 여러 레벨을 가지고 있고 각 레벨마다 오르거나 내리는 스테이터스를 나열하는 모양으로 만들어져 장신구 하나가 성장 가능한 레벨 수 만큼의 행을 차지하고 있고 각 행마다 성장하는데 필요한 성장 재료와 종류와 수량, 그리고 이 행에 해당하는 레벨에 도달할 때 받는 스테이터스 증감이 나열되어 있었습니다. 이는 여느 비슷한 게임에서 흔히 사용하는 모양으로 딱히 생소할 것은 없었습니다.

그런데 또 다른 데이터에는 먼저 살펴본 장신구 데이터에 언급된 각 장신구의 구분자마다 성장하지 않는 것처럼 보이는 한 줄로 된 단일 레벨에 아까와는 다른 스테이터스 증감이 표시되어 있었는데 앞서 장신구 데이터가 성장하고 성장에 따라 여러 스테이터스 증감이 일어나는 데이터는 굳이 기획서를 살펴보지 않아도 바로 이해할 수 있었지만 그와 똑같은 이름의 장신구에 이번에는 성장 관련 데이터가 빠져 있고 한 줄로 되어 있으며 그 한 줄에 아까와는 상당히 다른 꽤 큰 폭의 스테이터스 증감이 표시되어 있는 데이터는 이 데이터가 어떻게 사용되는지 바로 이해할 수가 없었습니다. 게임에 따라 최대 레벨에 도달한 장신구가 이전과 비교해 한 번에 훨씬 더 큰 폭으로 성장하기도 하는데 어쩌면 이 데이터는 그런 의도일 가능성이 있습니다. 하지만 그렇다 하더라도 굳이 원래 장신구의 성장에 따른 능력치 증감을 기입한 데이터와 완전히 별도 데이터를 사용해 이를 언급할 필요는 별로 없어 보입니다. 그냥 장신구 레벨마다 한 줄 씩 늘려 가다가 맨 마지막 줄의 최대 레벨에는 이전보다 훨씬 큰 폭의 스테이터스 증감을 입력하면 그만이었습니다. 혹은 데이터구조와 화면 구성을 서로 구분해서 생각하지 못하고 화면에 따라 데이터를 설계한 흔적일 가능성도 없지 않습니다. 가령 같은 장신구의 성장 과정에 사용하는 데이터와 최고 레벨 데이터를 분리해 놓을 만한 원인 중 하나는 성장 과정에 사용하는 화면에 보여줄 데이터와 이 장신구가 최대 레벨까지 성장해 각 장신구의 최대 레벨만 보여주는 화면이 서로 다를 수 있고 이 때 서로 다른 화면에 표시할 값을 서로 화면에 따라 분리된 데이터로 만들 가능성도 없지는 않습니다. 이상하지만 종종 이런 일이 일어나기도 합니다.

숫자를 바꿔 게임을 실행해 보고 게임 안에서 방금 새로 입력한 숫자의 시인성을 좋게 만든 장신구를 테스트 명령어를 사용해 불러온 다음 엑셀 데이터시트에 입력한 값들이 잘 적용되는지 살펴봅니다. 숫자의 시인성을 좋게 만드는 것은 각 레벨마다 제개 새로 입력한 데이터에 의한 숫자들임을 확실히 알 수 있도록 눈에 잘 띄는 아무 숫자를 입력한 것입니다. 가령 각 레벨마다 서로 다른 성장 재료 수량을 요구한다면 게임 상에서 이 장신구를 불러와 살펴봐도 이 데이터가 제가 새로 입력한 데이터가 올바르게 적용되어 표시되는 것인지 확신하기 어려울 수 있습니다. 특히 밸런스 디자이너에 의해 이 모든 숫자들이 장신구를 장착할 전용 클래스와 장신구 각각의 등급에 따라 조정되고 나면 게임 상에서 장신구 숫자만 보고 이 데이터가 정상적인지 밸런스 디자이너가 아닌 사람이 판단하기는 쉽지 않습니다. 이럴 때 테스트 데이터를 입력하기 위해 엑셀 파일을 열고 바로 직전에 있는 장신구 데이터를 그대로 복사해 새 데이터를 만들면 게임 상에서 새로 입력한 장신구를 구분하기 어려워 테스트를 편하게 진행하기 어려워집니다. 그래서 아이템 아이콘에 에셋이 허용하는 한 가장 이상한 아이콘을 넣어 테스트 아이템임을 확실히 구분할 수 있게 만들고 또 숫자들을 정확히 구분할 수 있도록 입력하곤 합니다. 가령 새 장신구의 각 레벨 별 성장재료 요구량은 1레벨부터 각각 1, 2, 3, 4, 5 … 와 같이 입력하고 각 레벨 별 스테이터스 증감치는 +1, -1, +2, -2, +3, -3 … 과 같이 어떻게 해도 누군가 이렇게 입력하거나 밸런스 디자인에 의해 이런 숫자가 나올 가능성이 없는 숫자를 입력합니다.

장신구 성장 데이터에 입력한 새 테스트용 장신구는 인게임에서 쉽게 발견했고 또 입력한 대로 나타났으며 예상한 동작을 확인했지만 나중에 발견한 같은 장신구 이름에 성장 데이터 없이 이전과는 상당히 다른 스테이터스 증감이 입력된 데이터에 기반한 장신구 아이템은 어디 나타나는지 찾을 수가 없었습니다. 기획서를 한참 찾아보고 또 여러 회의록을 살펴보며 따라가다가 도저히 이 숫자들의 동작을 확인할 수가 없어 옆 자리 아저씨에게 물어봤는데 아저씨로부터 돌아온 답변은 꽤 충격적이었습니다. 게임 서비스가 정상 동작할 경우 제가 처음 살펴본 각 레벨 별 성장 재료 요구량과 그 레벨에 도달할 때 적용될 스테이터스 증감을 포함한 제가 처음 본 데이터에 의해 동작합니다. 이 때 제가 나중에 본 같은 장신구 이름이지만 성장 데이터가 없고 스테이터스 증감 폭이 훨씬 큰 데이터는 사용되지 않습니다. 그런데 만약 게임 서비스가 오동작 할 때, 특히 어떤 이유로 플레이어의 성장 데이터와 인벤토리 데이터 따위를 불러올 수 없는 데이터베이스 이상 상황에는 플레이어가 장착한 장신구의 현재 레벨을 확인할 수 없기 때문에 각 레벨에 따른 스테이터스 증감 데이터를 이미 가지고 있다 하더라도 이를 장신구 레벨에 근거해 적용할 수 없기 때문에 이런 장애 상황에만 사용할 성장하지 않고 대략 전체 성장의 중간 정도 되는 스테이터스 증감을 적용할 데이터를 따로 들고 있다가 사용한다는 것입니다. 그러니까 서비스가 정상 동작할 때는 쉽게 동작을 파악할 수 있었던 바로 그 데이터를 사용하지만 장애 상황에서는 아무리 테스트를 해도 적용되는 사례를 찾을 수 없었던 바로 그 데이터를 사용한다는 말입니다. 제가 데이터가 사용되는 시나리오를 도저히 발견할 수 없었던 상황이 그 때에 가서야 이해 됩니다. 테스트 환경에서 데이터베이스는 절대 죽지 않아 항상 정상 동작하고 있었기 때문입니다.

이 설명을 듣고 마음속으로는 상당히 충격 받았지만 짐짓 아무렇지도 않은 표정을 유지하는데 상당한 에너지를 소모하는 상태에서 왜 그렇게 동작하는지 이어서 질문했고 이전에 일어났던 일에 대해 들을 수 있었습니다. 현재 빌드를 개발했던 엔지니어들은 어떤 이유로 지금은 퇴사한 상태인데 그들이 초점을 맞춘 부분 중 하나는 어떤 이유로 게임 서비스 전체 중 일부가 오동작 하는 상황에서 게임의 나머지 부분이 큰 영향을 받지 않고 동작하거나 완전한 정상 동작을 하지 않더라도 일종의 대체 모드로라도 동작해 이전과는 약간 다를 수 있지만 어쨌든 게임을 계속할 수 있는 제 이의 상태를 제공하는 것입니다. 가령 스포츠 PvP 모드가 있을 때 여기 참여하는 플레이어들의 매치메이킹을 담당하는 서버가 동작하지 않게 되더라도 PvP 자체를 중단하는 대신 그 전까지는 이를 전담하던 서버에 의해 이루어지던 매치메이킹 대신 매치메이킹 서버가 응답하지 않을 때는 그냥 플레이어들이 매치를 신청한 순서에 따라 그냥 입장 시켜 매치메이킹이 정상 동작하지 않는 상황에도 겉으로는 이를 잘 느낄 수 없도록 만들었습니다. 이와 비슷한 맥락으로 새로운 월드에 진입할 때 어떤 이유에 의해 데이터베이스로부터 현재 고객의 성장 상태, 장착한 각 장비의 성장 상태를 가져오는데 실패하더라도 게임 서비스 전체를 멈추는 대신 데이터베이스로부터 레벨을 가져오지 못할 경우에 대비해 각 장비와 장신구가 가질 일종의 표준 성장 수준에 따른 스테이터스를 미리 정의해 놓고 데이터베이스로부터 가져온 실제 레벨에 근거한 숫자 대신 표준 숫자를 사용하는 것입니다. 그럼 적어도 ‘게임 서버와 접속이 끊어졌습니다’ 메시지를 보여주고 서비스를 중단하는 대신 뭔가 이전과는 약간 다른 숫자를 보여주기 시작하겠지만 일단 게임이 돌아가고 있는 상태를 유지할 수는 있다는 것입니다. 그러니까 제가 도무지 이 숫자들이 사용되는 상황을 찾을 수 없는 숫자들은 바로 데이터베이스로부터 장신구 레벨을 가져올 수 없을 때 대신 사용될 숫자였습니다.

이미 이전부터 게임 서비스를 유지하기 위해 서로 다른 여러 서버 애플리케이션이 정상 동작하지 않는 상황에 대응하는 여러 가지 전략을 본 적이 있습니다. 가령 게임 서버, 매치메이킹 서버, 파티 서버, 월드 서버는 각기 다른 역할을 하는 애플리케이션으로 이들은 서비스 도중 각자가 요구하는 하드웨어 및 네트워크 자원에 따라 같은 기계에서 동작하기도 하고 서로 다른 기계에서 동작하기도 합니다. 가령 몬스터를 공격할 때마다 대미지를 판정하고 서로에게 대미지를 준 결과를 반영하고 각자의 피격 여부를 판정하는 게임 서버는 많은 연산과 잦은 네트워크 통신을 필요로 했기 때문에 대체로 독립된 기계에서 게임 서버 애플리케이션만 돌리곤 했습니다. 이와 달리 파티 서버, 매치메이킹 서버, 길드 서버 같은 것들은 필요할 때만 동작했고 또 사용량을 어느 정도 쉽게 예측할 수 있어 굳이 각각을 서로 독립된 기계에서 동작하도록 하는 대신 같은 기계에 각각의 서버 애플리케이션을 한 번에 구동해 전체 하드웨어 비용을 낮추고 또 게임 서비스를 새로운 데이터센터에 전개할 때 복잡도를 감소 시킵니다. 그런데 이들은 근본적으로 윈도우 서버에서 동작하는 윈도우용 응용프로그램이었고 각자가 서로 다른 기계에서 돌아갔지만 필요하다면 그냥 원래 다른 기계에서 돌아가야 하는 응용프로그램을 서로 같은 기계에서 실행하더라도 마치 아무 일도 없었던 것처럼 서비스가 운용되었는데 이는 하드웨어나 네트워크 장애가 일어나 특정 하드웨어에 접근할 수 없을 때 그 하드웨어에서 돌던 응용프로그램을 현재 사용량이 낮은 다른 하드웨어에서 실행해 일부 하드웨어 장애 상황에서도 완전히 똑같이 서비스를 구동할 수 있게 해 주었습니다.

가령 로그인 서버 애플리케이션을 구동하는 하드웨어나 네트워크에 장애가 일어나 로그인이 지연되는 상황에 각 서버 하드웨어에 흩어져 있던 감시 프로그램이 로그인 서버가 응답하지 않는다는 사실을 감지하면 다른 하드웨어에 로그인 서버 애플리케이션을 실행하면 기존 로그인 서버를 구동하던 하드웨어가 여전히 장애 상황이더라도 로그인이 조금 느려지겠지만 바로 문제가 해결되는 식이었습니다. 비슷한 관점에서 파티를 담당하는 서버 애플리케이션이 중단되면 일시적으로 모두의 파티 정보가 사라지고 파티에 의존해 동작하던 규칙이 오동작하거나 파티가 해체되었을 때의 시나리오에 따라 게임이 동작할 수 있었지만 조금 기다리면 다시 파티를 만들 수 있었는데 겉보기에는 그냥 파티가 깨지고 이를 다시 만드는 것으로 느껴지겠지만 내부에서는 이전 파티 서버가 응답하는 대신 다른 하드웨어에서 새로 실행된 파티 애플리케이션이 새 파티 생성을 담당하고 있게 됩니다. 한번은 빌드를 만들어 연휴 기간에 걸쳐 제한된 고객들에게 서비스를 열어 베타 테스트를 수행해야 하는 상황이 되었는데 회사는 우리들에게 모든 서비스를 커버할 만큼 충분한 하드웨어를 지급하지 않은 상태였고 우리들이 개발한 게임 서비스를 구성하는 여러 서버 애플리케이션들 역시 크래시 되지 않고 온전하 동작할 수 있을지 여부가 확실하지 않았습니다.

특히 모니터링 환경이 아직 갖춰지지 않아 누군가 서비스 기간 내내 모니터링 하며 하드웨어나 소프트웨어 장애가 발생할 때마다 이를 재시작 해야 하는 상황이었는데 우리들 모두는 연휴 동안 회사에서 모니터 앞에 앉아 장애 발생에 따라 서버를 시작하는 역할을 하고 싶지 않았습니다. 누군가가 아이디어를 내 각 하드웨어에서 프로세스 목록을 모니터링하다가 특정 프로세스가 크래시 되어 사라지면 재빨리 같은 프로세스를 다시 실행하는 스크립트를 만들어 무한히 수행되도록 만들어 놓은 다음 다 함께 연휴 동안 회사를 비웠는데 이 단순한 스크립트는 프로세스를 모니터링 해 서버 애플리케이션을 재시작하고 네트워크 장애가 일어나면 필요한 서버 애플리케이션을 아무 기계에나 띄워 서비스를 계속했는데 나중에 살펴보니 게임 서버가 크래시되자 로그인 서버 하드웨어에 게임 서버 애플리케이션이 떠 있기도 했습니다.

이런 동작은 기술적으로 서비스를 유지하는 접근으로 올바르고 하드웨어나 소프트웨어 장애에도 불구하고 고객들은 짧은 시간 동안 불안한 동작을 경험할 수 있겠지만 일단 장애 상황이 복구되고 나면 이전과 완전히 똑같은 경험을 계속할 수 있다는 점에서 앞서 소개한 데이터베이스로부터 값을 가져올 수 없을 때 대신 사용할 값을 미리 입력해 놓는 시나리오와는 완전히 다릅니다. 게임 서버가 크래시 되면 그 때 플레이 하던 고객들은 접속 단절을 겪겠지만 바로 게임을 재실행 하면 엉뚱하게도 로그인 하드웨어에서 다시 실행된 게임 서버에 의해 이전과 똑같은 게임 경험을 할 수 있습니다. 뭐 로그인 동작이 조금 느려질 수 있겠지만 뒤에서 무슨 일이 일어났는지 고객들은 결코 눈치 챌 수 없을 테고 일단 게임이 시작되면 이전과 똑같은 경험을 할 수 있다는 점이 가장 중요합니다. 하지만 데이터베이스에 접근할 수 없을 때를 대비한 비상 데이터는 일단 이 상황에 게임 서비스가 유지되는 것처럼 보이게 만들 수는 있지만 고객들의 경험은 이전과 완전히 달라집니다. 장신구를 더 높은 레벨까지 성장 시킨 고객들은 갑자기 전투 경험이 이전보다 어려워졌음을 느낄텐데 그렇게 느끼기만 한다면 다행이지만 죽지 않을 상황을 예상한 전투에서 갑자기 죽는 경험을 하면 크게 실망할 수 있습니다. 또 어떤 고객들은 갑자기 장신구가 이전에 비해 훨씬 강해졌다고 생각할 수도 있습니다. 이들은 무슨 일이 벌어졌는지 생각하기보다는 뭔가 이전보다 갑자기 강해진 것 같으니 재빨리 더 높은 보상을 드랍하는 필드로 달려가 이전 같으면 획득할 수 없을 보상을 획득하며 밸런스 디자이너가 예상한 성장 진행을 망가뜨릴 수 있습니다.

온라인 게임에서 우리들이 게임에 투자한 시간과 노력에 대한 기록은 게임 서버의 데이터베이스에 기록됩니다. 이 기록에 근거해 우리들의 게임 경험이 좌우되며 이 기록이야말로 고객들의 시간과 노력을 대변하는 게임 서비스 전체에서 가장 중요한 데이터라고 말할 수 있습니다. 그런데 이 데이터를 불러오지 못했다면 이는 게임 서비스를 유지하는 것이 핵심이 아니라 그 데이터를 불러올 수 없는 상황을 최대한 빨리 해결하는 것이 핵심입니다. 데이터베이스가 죽어 플레이어들의 강함 정보를 가져올 수 없다면 이런 상황에도 불구하고 게임이 동작하는 것처럼 보이게 만드는 게임디자인 상의 조치보다는 이 상황에 한정된 오동작에 의해 문제가 확대되는 상황을 피하기 위해 일단 서비스 전체를 중단하고 데이터베이스가 정상 동작하도록 조치하는 쪽이 올바릅니다. 물론 나중에서야 왜 이런 이상한 개발이 일어났는지 전해 들었는데 이전에 그 프로젝트의 엔지니어들이 경험한 회사는 게임 서비스의 중단 시간에 극도로 민감해 하고 있었고 이들은 제한된 자원 안에서 중단되지 않는 서비스를 개발하는 어려운 선택을 하는 대신 중단 상황이 회사 입장에서는 중단으로 인식되지 않도록 하는 좀 더 쉬운 결정을 내린 것 같습니다. 결국 서비스를 운영하는 동안 실제로 비상용 데이터에 의해 게임이 동작하는 모습을 실제로 본 적은 없지만 여러 가지 잘못된 의사결정이 연속으로 일어나면 이런 결과를 초래할 수 있다는 사실을 배운 계기가 됩니다.

최근에 저는 한 엔지니어로부터 그 분이 작업을 진행하다가 저에게 한 질문 덕분에 지금까지 설명한 사례를 다시 떠올리게 되었습니다. 아직 개발 중인 프로젝트는 게임의 여러 기능이 단일 서버 애플리케이션에 의해 동작하고 있습니다. 플레이어가 위치한 세계를 구분하고 또 통제하는 월드 서버, 이들 모두의 상호작용을 관장하는 게임 서버, 이들의 파티 여부를 제어하는 파티 서버 같은 서로 다른 애플리케이션에 의해 동작하도록 하던 기능들을 일단 개발 기간 동안에는 모두 단일 서버 애플리케이션에 의해 동작하도록 했는데 이는 개발 기간 동안에는 개발 과정의 불편함을 줄이고 여러 요구사항을 빠르게 적용할 수 있는 장점이 있을 뿐 아니라 테스트 환경의 하드웨어와 소프트웨어를 배포하기에도 아주 편리합니다. 하지만 모든 기능이 단일 서버 애플리케이션에 기반해 동작하다 보니 자잘한 문제가 있었는데 가령 파티 기능이 단일 서버 애플리케이션에 기반해 동작하지만 월드 서버는 우선 같은 하드웨어 상에서 여러 프로세스에 의해 동작하다 보니 월드 서버 애플리케이션에 포함된 파티 기능이 플레이어가 한 월드 서버에서 다른 월드 서버로 이동할 때 종종 문제를 일으킵니다. 만약 파티 서버가 월드 서버에 독립적으로 만들어져 있었다면 플레이어가 월드 서버를 이동한다 하더라도 파티 기능에 영향을 받지 않을 겁니다. 하지만 이들이 같은 서버 애플리케이션에서 동작하고 이 상황을 따로 처리하지 않는다면 한 레벨에서 파티를 맺었지만 다음 레벨로 이동하니 파티가 사라지는 현상을 겪게 됩니다. 파티 서버 애플리케이션을 따로 개발하지 않고 일단 서로 다른 월드 서버 애플리케이션 끼리 파티 정보를 공유하도록 임시 처리할 수 있지만 근본적으로 이런 처리는 파티 기능 개발을 전혀 진전 시키지 못합니다.

이런 상황에서 드디어 파티 서버를 별도 서버 애플리케이션으로 분리해 개발하기로 한 상황이었는데 이 때 제가 받은 질문은 플레이어가 한 월드 서버에서 다른 월드 서버로 이동할 때 파티 정보가 변경되면 이 정보를 어디까지 유지하고 또 유지하지 않아도 되는지, 파티 정보가 변경되었다는 사실을 표시하는 메시지를 어디까지 정확히 표현하고 또 표현하지 않아도 되는지, 그리고 마지막으로 파티 서버가 장애 상태일 때 파티는 어떻게 동작해야 하는지에 대한 것입니다. 사실 이 질문들을 쭉 들으며 대강 답변을 생각해 놓다가 마지막 질문인 파티 서버가 장애 상태일 때 파티가 어떻게 동작해야 하는지에 대한 질문을 듣고 방금 전까지 머릿속으로 준비한 모든 답변이 다 쓸모 없다는 사실을 인식했습니다. 게임은 여러 가지 부분으로 구성되어 있고 현대 온라인 게임에서 이런 여러 기능은 서로 구분된 서버 애플리케이션에 근거해 동작하며 이들은 필요에 따라 같은 하드웨어 상의 다른 프로세스로 실행되거나 다른 하드웨어에 기반해 실행됩니다. 그런데 이들 중 어느 한 하드웨어나 서버 애플리케이션에 장애가 생기면 장애가 생긴 부분은 오동작 하겠지만 나머지 부분은 정상 동작하도록 만들곤 합니다. 가령 상점을 담당한 서버 애플리케이션이 크래시 되었다면 상점 메뉴를 클릭하면 에러 메시지를 띄우겠지만 게임의 나머지 부분은 정상 동작할 겁니다. 이 때 중요한 점은 상점 서버 애플리케이션이 장애 상태일 때 억지로 상점이 정상 동작하는 것처럼 보이도록 하는 어떤 게임디자인 관점의 전략도 의미가 없다는 것입니다. 이 상황에서 가장 중요한 것은 상점 서버의 장애 원인을 파악하고 상점 서버를 다시 실행해 상점 서비스를 복구하는 것입니다. 상점 서버가 장애 상태일 때 대신해서 동작할 어떤 게임디자인 관점의 규칙을 준비하는 것이 아닙니다.

파티 역시 마찬가지입니다. 현대에는 파티 단위로 진입해야 하는 던전에서 중간에 파티를 탈퇴해 생기는 여러 가지 예상하지 않은 동작을 차단하기 위해 파티를 반드시 요구하는 던전에서 중간에 파티를 탈퇴하면 던전 밖으로 내보내곤 합니다. 그래서 중요한 파티 던전을 플레이 할 때 파티 서버는 굉장히 중요한 역할을 합니다. 만약 파티 서버 애플리케이션이 장애를 일으키면 파티 정보가 사라지고 던전은 규칙에 따라 더이상 파티에 속해 있지 않은 플레이어들을 던전 밖으로 내보내며 이는 완전히 정상적인 동작입니다. 물론 고객들 입장에서는 자신들이 지금까지 플레이 한 진행이 사라지는 경험을 하겠지만 파티 기능이 오동작 한 이상 이런 결과를 피할 수 없습니다. 아마도 어딘가의 어떤 프로젝트에서는 파티를 반드시 요구하는 던전을 플레이 하다가 파티 기능에 장애가 생길 경우에 대비해 원래 규칙은 파티에 속하지 않으면 더 이상의 문제를 일으키지 않기 위해 던전 밖으로 내보내는 규칙이 있지만 파티 서버가 죽은 상태에서는 제한적으로 파티에 속하지 않은 상태에서도 던전을 계속해서 플레이 하고 이에 따라 던전 끝에서 파티를 가정한 보상을 줄 때 플레이어들이 파티 상태가 아닐 경우에 대응하는 또 다른 보상 정책을 수립했던 것 같습니다. 엔지니어는 게임디자인 관점에서 이렇게 파티 기능이 동작하지 않을 경우에 던전이 다른 규칙으로 동작할 전략을 요구했던 것 같습니다. 하지만 저는 전혀 그렇게 생각하지 않습니다.

우리는 게임 소프트웨어에 의해 구동되는 서비스를 만들고 있습니다. 우리들은 절대로 실패해서는 안되는 소행성 탐사선이나 절대로 오동작 해서는 안되는 항공기, 또한 절대로 예측 가능한 동작만을 수행해야 하는 의료기기를 개발하고 있지 않습니다. 때문에 한 가지 기능이 오동작 할 때 핵심은 오동작 하는 기능을 정상화 하고 오동작에 의한 서비스 중단을 감수하는 것입니다. 기술적인 관점에서 서비스의 장애 상황에 서비스를 계속하기 위한 게임디자인 관점에서 제 이의 규칙을 만들면 현재 동작이 정상 상황에 적용되는 제 일의 규칙이 적용된 상태인지 아니면 장애 상황일 때 제 이의 규칙이 적용된 상태인지 구분하기 어려울 수 있어 게임디자인 복잡도를 급격히 올릴 뿐 아니라 근본적으로 각 시점에 어떤 규칙이 실행될지 예측할 수 없게 됩니다. 앞서 파티를 강제하는 던전 시나리오에서 파티에 의한 클리어를 가정한 보상은 파티가 깨진 상태에서 완전히 이상하게 동작할 수 있습니다. 원래 파티 하나를 대상으로 한 벌만 집행되어야 하는 보상이 파티가 깨진 상태에서는 인원 수만큼 집행될 수도 있고 이를 고려해 설정한 제 이의 보상 정책은 원래 이들이 기대한 것과 다른 보상을 수 있습니다. 이 상태는 앞서 데이터베이스에 접근할 수 없는 상태일 때 레벨 정보 없이 사용할 장신구 스테이터스처럼 동작 하는 것처럼 보이지만 실제로는 고객들이 예상한 것과 전혀 다르게 동작하며 이는 그저 서비스가 돌아가고 있을 뿐 고객들에게 일관된 경험을 주지 못하는 이상한 상태를 만들 뿐입니다.

파티 서버가 장애 상태일 때는 파티가 없어질테니 게임의 모든 부분에서 파티가 깨질 때 이루어져야 하는 표준 절차에 따른 동작이 수행되어야 하고 플레이어들이 파티를 강제하는 던전을 얼마나 많이 클리어 했든 관계 없이 원래 이들이 파티가 아니라면 바로 내보내는 규칙을 그대로 적용해 파티 서버 장애 상황일 때 던전은 중단되며 이들은 던전 입구로 돌아가고 파티는 사라진 상태이며 이 때 던전에 재진입 하려고 하면 던전에 진입할 수 없다는 메시지를 표시해야 한다고 설명했습니다. 그리고 이런 답변을 예상하지 않으셨을 것이 분명한 엔지니어님께 지금까지 설명한 게임의 일부가 오동작하는 상황에 대비한 제 이의 규칙은 게임디자인의 복잡도를 올리고 게임이 일관되지 않은 모양으로 동작해 고객들이 게임의 동작을 신뢰할 수 없게 만들며 우리들 스스로도 동작을 신뢰할 수 없게 만들어 개발하기도 어렵고 테스트하기도 어려운 상태를 만들기 때문에 요구하신 정책을 만들어 드릴 수 없다고도 설명합니다. 마지막으로 우리가 방금 나눈 대화에서 가장 중요한 것은 게임디자인 입장에서 엔지니어가 장애가 거의 일어나지 않는 파티 서버를 만들어 주실 것에 대한 신뢰에 기반해 우리가 게임디자인을 만드는 것이며 장애를 가정한 규칙을 요구하기 전에 장애가 일어나지 않는 서버 애플리케이션을 만드는 것이 더 중요하다고 말씀 드린 다음 대화를 마쳤습니다.

한편 월드 서버를 이동하는 사이에 일어난 이벤트를 설명하는 메시지는 다음 월드 서버에 도달한 다음 어떻게 처리해야 할까요. 이 질문에 대해서도 이야기했는데 이미 글이 너무 길어진 것 같으니 이 이야기는 나중에 기회가 될 때 해 보겠습니다.