▲ 넥슨코리아 정성훈 서버유닛 리더

  • 주제: 실시간 MMORPG의 플레이 감각을 날카롭게 벼려보자! - 예측과 보정을 통한 자연스러운 동기화
  • 강연자 : 정성훈 - 넥슨 코리아 / NEXON KOREA
  • 발표분야 : 프로그래밍 / 게임기획
  • 권장 대상 : 프로그래머, 시스템 디자이너
  • 난이도 : 기본적인 사전지식 필요


  • [강연 주제] 지연 시간이 존재하는 온라인 멀티플레이 게임에서 정보 동기화의 정합성 확보 및 자연스러운 연출을 해내기 위해 어떤 것들에 집중하면 좋을 지에 대한 이야기입니다. 생각해 본 해당 문제에 대한 몇 가지 대응 방향성을 제시하고, 프라시아 전기 개발을 진행하면서 실제 마주했던 문제들과 그 원인 파악 과정 및 어떤 식으로 대응 및 결정을 하고 해결했었는지, 예제를 기반으로 종합적인 선택지에 대해 공유해보려 합니다.

    최근에는 드물긴 하지만, 초고속 인터넷이 전국적으로 깔리기 전에는 컴퓨터 사양과 관련 없이 멀티플레이 게임을 하다보면 종종 핑이 튀면서 캐릭터가 멋대로 가있는 일이 잦았다. 온라인 게임은 클라이언트를 거쳐 서버에서 처리하게 되는데, 정보가 전달되는 과정에서 지연이 발생해 명령이 순차적으로 처리되지 않거나 이미 클라이언트에서 처리된 상황에서 서버가 정보를 뒤늦게 받고는 그 전달받은 위치로 캐릭터를 다시 보내곤 했기 때문이다.

    PC, 콘솔 등 안정적인 네트워크 환경에서 플레이하게 되는 게임에서는 이런 문제들이 많이 개선됐지만, 이동통신망을 사용하게 되는 모바일 게임에서는 다시금 이 문제가 개발자들에게 최우선 해결 과제 중 하나로 자리잡았다. 와이파이를 안정적으로 사용하는 환경 외에도 LTE, 5G, 그리고 한 자리에 서있지 않고 빠르게 이동하는 등 네트워크 상황이 이전보다 더 복잡해졌기 때문이다.

    넥슨이 준비하고 있는 모바일-PC 크로스플랫폼 MMORPG '프라시아 전기'에서는 이러한 문제에 대해 어떻게 대응하고 있을까? 넥슨코리아의 정성훈 프라시아 전기 개발팀 서버유닛 리더는 프라시아 전기 개발 초창기부터 히스토리를 훑어가면서 문제 발생 후 어떻게 개선해나갔나 설명해나갔다.




    ■ 멀티플레이 게임에서 피해갈 수 없는, '지연 시간' 문제

    ▲ 아 내가 먼저 보냈는데 왜 늦게 전송되냐고....이런 일이 만일 게임에서 발생한다면?

    정성훈 서버유닛 리더는 온라인 게임에서의 플레이를 메신저에 비유했다. 메시지를 작성해서 보내면 서버를 거쳐 상대방에게 전송이 되는 방식은 비슷하기 때문이다. 메신저에서도 네트워크 이상 등으로 종종 전송이 지연되서 다른 사람보다 먼저 보냈는데도 나중에 떠버려서 이미 단톡방에서 결정이 다 나버렸다던가 하는 일이 있다. 이러한 현상이 게임에서도 일어날 수 있고, 그 순간 쾌적한 게임플레이를 망치고 유저의 기분을 상하게 만들게 된다.

    현재 정성훈 리더가 속한 팀이 개발 중인 신작 '프라시아 전기'는 MMORPG에, 실시간 PVP가 핵심이 되는 게임이다. 그런 만큼 수많은 사람들이 접속해있는 상황에서 어떻게 지연시간을 줄여야 할지가 관건이었다. 이론상 유선 네트워크는 보통 10ms, 많으면 20~30ms의 지연시간이 발생한다. 와이파이로 가면 짧게는 100ms, 이동통신으로 넘어가면 200~300ms까지 올라갈 수도 있다.

    ▲ 프라시아 전기는 실시간 MMORPG인 만큼

    ▲ 지연 시간 문제를 필히 고려할 수밖에 없었다

    통상 유저들이 말하는 30프레임, 60프레임 단위로 환산하면 어떨까. 60프레임 기준으로는 한 프레임당 16ms 이상으로 지연시간이 발생하면 다수의 유저들이 인지하게 된다. 30프레임 단위에서는 33ms 이상의 지연시간이 발생하면 유저들이 부자연스럽다고 여긴다. 흔히 말하는 핑이 나쁘다, 핑이 튄다고 말하는 상황이 되는 것이다. 심한 경우에는 벽쪽으로 걸어가는 줄 알았더니 순간이동을 해버렸다거나 하는 등등, 옛날 네트워크 상태가 안 좋았던 초창기 온라인 게임 시절에 많이 겪었을 현상이 발생한다. 이와 관련해서 대처를 아예 안 하게 되면, 누구도 관심을 갖지 않게 된다.

    그렇다면 지연현상에 대처하려면 어떻게 해야 할까? 정성훈 리더는 예측과 보정이라는 개념을 언급했다. 가지고 있는 정보로 미리 예측하고, 정확한 정보가 원격으로 왔을 때 예측한 것과 다르다면 그에 맞춰 보정하는 것이 갑작스런 네트워크 지연에도 유닛이 갑자기 순간이동해버리거나 하는 현상을 방지할 수 있다는 것이다.





    ■ 타격이 되기 전에 피격 효과부터 나온다? 예측으로 조율하기

    ▲ 타격 판정이 뜨기 전에 피격 판정이 떠서 손맛이 없었다는 제보에 개발팀이 원인 분석에 나섰다

    팀에서 이런 개념에 대해 관심을 갖기 시작한 것은, 테스트를 담당하던 팀원이 퇴근길에 게임의 손맛이 떨어진다는 평을 하면서부터였다. 원인을 파악해본 결과 이동통신망, LTE 환경에서 버스에 타거나 한 자리에 가만히 있지 않게 되면 타격 판정이 지연된다거나 하는 문제가 발생했다는 사실이 밝혀졌다.

    때로는 피격 판정 효과가 먼저 발생한 뒤 타격음이 나중에 들리는 등, 플레이하면서 어색하게 느껴질 부분들이 종종 발생하는 것을 확인한 개발팀은 해결 방안을 모색하기 시작했다. PC 환경에서는 안정적으로 출력됐지만, '프라시아 전기'는 모바일-PC 크로스플랫폼을 내세운 만큼 모바일 환경에서도 쾌적한 플레이를 제공해야만 했기 때문이다.

    우선 개발팀은 타격과 연관된 스킬 시스템을 다시 훑어보고, 그 개발 이력을 더듬어나갔다. 최초의 프라시아 전기는 타겟팅 스킬만 개발됐으나, 논타겟 스킬이 필요하다는 요청이 오면서 시전 시점과 스킬 피격 대상 선정 시점을 분리했다. 그렇게 해야 스킬 시전시 영역 안에 있는 개체들이 시전 완료되기 전에 영역 밖으로 도망가는 식으로 회피할 수 있었기 때문이다.

    ▲ 처음엔 타겟팅 스킬만 있어 단순했지만, 논타겟 스킬을 추가하게 되고

    ▲ 더 다양한 조건이 붙으면서 시점 구분이 복잡해졌다

    그러나 점차 다양한 종류의 스킬이 추가되면서 요구사항이 복잡해졌다, 예를 들어 넉백이 되는 스킬은 스킬에 맞은 대상이 넉백되고, 대미지는 그렇게 넉백되는 중간에 입게 된다고 하면 스킬이 시전되는 시점, 넉백되는 시점, 그리고 대미지를 입는 시점이 각각 따로 존재하게 된다. 여기에 쿨다운 시점을 어떻게 적용하느냐, 시전 중 캔슬 개념을 도입하느냐 등등이 더해지면 몇 개의 고정된 구간으로 나눌 수 있는 수준을 벗어나버린다.

    이러한 문제를 해결하기 위해 '스킬 스테이지'라는 개념을 도입했다. 한 스킬에 여러 스테이지로 구간을 나눠서 구성, 복잡한 요구사항을 정리한 것이다. 이렇게 정리하면서 다양한 스킬을 하나의 시스템으로 만들어낼 수 있도록 개발을 진행했다. 그 결과 플레이어 스킬과 보스 스킬은 하나의 시스템으로 구성하면서도, 복잡다단한 스킬들을 구현해낼 수 있었다.


    이 단계에서 LTE 환경에서 지연이 발생하는 문제가 캐치되자, 다시 한 번 문제점을 검토하기 시작했다. 초창기에는 타격 연출 후에 0.5초 후 피격 이런 식으로 단순하게 구성하면 됐으나, 스테이지 기반으로 변경하고 난 이후에는 매번 스테이지마다 결정 시점이 다가오는 방식이었다. 결정하는 시기가 많아지다보니 그 전달하는 과정도 많아졌고, 그때마다 다른 지연 시간으로 전달이 되니 개발자가 의도한 시간대에 전달이 안 되는 일도 많았다. 특히 네트워크가 불안정한 상황이면 이런 일이 필히 닥쳤다.

    원인을 파악한 개발팀은 연출을 보여줄 때 클라이언트 내에 정보가 부족한 상황이었다고 판단, 이를 채우는 방안으로 접근했다. 아직 시작되지 않은 스킬 스테이지도 미리 계산해서 그 예측값을 공유한 상황에서 실제 스테이지 진행은 서버나 클라이언트 다 각각 진행하는 식으로 구축한 것이었다.

    ▲ 네트워크 지연으로 예상과는 다르게 흘러가버리는 문제가 발생했다

    미리 전체를 계산해버리면 안될까 하는 생각도 있겠지만, 그는 그 모든 상황을 다 한꺼번에 계산할 수 없었기 때문에 구간을 다르게 스테이지로 묶는 방식을 취했었다는 점을 언급했다. 그래서 스킬 스테이지 플로우라는 개념을 또 도입했다. 시점이 나뉘어야 되는 주요 부분만 플로우를 나누는 기준으로 적용하고, 나머지 스테이지는 묶어서 미리 계산하게끔 한 것이다.

    그렇게 해서 밀려나있던 타격 스테이지를 묶음으로서 원래 4번 전송되던 스테이지를 2번만 전송하게 하고, 그 안에 연출이 어색하지 않게 진행되게 하면서 타격이 되기 전에 피격 판정과 피격음이 먼저 나오는 문제를 처리할 수 있었다.


    ▲ 예측 가능하게 만들기 위해 스킬 스테이지 플로우를 도입

    ▲ 지연이 발생해도 연출이 어색하지 않게끔 했다


    물론 이런 조치만으로 모든 문제가 해결되는 것은 아니었다. 플로우가 길다보니, 미리 스킬 정보를 알려준 상황에서 도중에 취소했을 때 때 처리가 늦어지면 스킬은 끊겼는데 피격 판정이나 모션이 나오는 문제가 발생할 수 있기 때문이다. 이 부분은 스킬 연출과 별개로 대미지 플로터를 실제로 완료되면 빨갛게 확정 메시지를 띄우고, 취소가 되면 문구를 모래처럼 흩날리거나 하는 등 연출을 더하는 등 추가 조치로 해결해나갈 예정이다.



    ■ 갑자기 멈춘 상대한테 공격이 안 맞는다면? 보정해서 위치를 조정하기

    ▲ 이번에는 멈춰있는 상대한테 스킬이 안 맞는다는 제보를 듣고 점검에 나섰다

    앞서 취한 조치가 예측을 전제로 했다면, 그 예측과 실제가 달라졌을 때 정확하게 보정하는 시스템도 필요하다. 개발팀이 이런 문제점을 파악한 것 역시도 테스터의 제보 덕분이었다. 가만히 서있던 대상에게 스킬이 맞지 않는다는 제보에 개발팀은 테스터를 불러서 상황을 재현하고, 원인을 분석하기 시작했다.

    개발팀은 분석 결과 타격자가 보는 시점과 피격자의 시점이 살짝 달랐다는 것을 확인할 수 있었다. 예시로 든 상황에서 타격자가 볼 때 적 캐릭터의 위치는 좀 더 왼쪽에 있었는데, 정작 그 상대는 타격자가 본 것보다 더 오른쪽에 있었다. 즉 스킬을 엉뚱한 곳에 시전해버린 셈이었다. 이를 서버에 디버거를 적용해서 파악한 결과 서버가 생각하는 위치와 피격자의 실제 위치가 또 달랐다는 것을 알아냈다.

    ▲ 분석 결과 각 클라이언트, 그리고 서버가 생각하는 캐릭터 위치가 제각각 달랐었다고

    그렇다면 왜 위치가 제각각 달라졌을까? 이를 파악하려면 프라시아 전기의 이동 시스템을 어떤 식으로 구축해나갔나 역추적해볼 필요가 있었다. 프라시아 전기의 초기 이동 시스템은 바닥에 폴리, 타일을 깔아두고 그 위를 자유롭게 이동하는 시스템으로 구축되어있다. 여기에 셀도 없고 방향도 특정되지 않아 자유롭게 돌아다닐 수 있도록 짜여져있다. 여기에 대규모 전투를 상정한 만큼, 그때 대량의 통신량이 들어올 것을 대비해 위치를 짧은 시간에 지속적으로 동기화하는 모델 대신 적당한 길이의 이동 구간을 만들어 동기화하는 방식을 채택했다.

    맨 처음에는 스킬처럼 서버의 허가 하에 이동을 진행, 지연 시간에 따라 오차가 있었으나 대체로 잘 맞아떨어지긴 했다. 그러나 조작감과 반응성이 낮다는 단점이 있었다. 그래서 클라이언트에서 먼저 이동한 뒤, 이를 서버에 알리는 식으로 변경했다. 그렇게 하니 조작감과 반응성은 좋아졌지만 각 클라이언트 피어들 간 위치 정보의 오차가 커지는 문제가 있었다. 특히 이동하다가 멈출 때 그 오차가 상당히 컸다.

    ▲ 타일 기반에, 대규모 전투를 상정해 적당한 길이의 이동 구간을 만들어 동기화하도록 하고

    ▲ 클라이언트에서 먼저 이동을 처리한 뒤 알리도록 했는데, 그러다보니 피어 간 위치 정보 오차가 커졌다

    그렇다면 왜 멈출 때 오차가 더 크게 발생한 이유는 무엇이었을까. 정성훈 리더는 예정된 이동을 다 하고 난 뒤에 멈추면 이런 현상은 발생하지 않았는데, 갑자기 멈췄을 때 발생했다고 힌트를 제시했다. 즉 보정이 진행된 상황에서는 각각 다른 위치 정보로 인한 오차가 조정되지만, 갑자기 멈추고 다음 이동이 제시되지 않으면 위치 정보 보정이 발생하지 않아 지연으로 인해 각각 다르게 위치가 적용된 상태 그대로였던 것이다.

    이를 해결하기 위해 캐릭터가 멈추게 되면 그 위치를 바로 동기화하는 식으로 짰는데, 그러니 캐릭터들의 움직임이 갑자기 뒤로 당겨지면서 툭툭 끊기는 현상들이 발생했다. 보정 구간 없이 자연스럽게 동기화할 구간을 찾아내는 것도 어렵다고 판단됐다. 그래서 갑자기 멈추라고 할 때도 보정할 수 있는 구간을 새로 만들기로 결정했다.

    ▲ 갑자기 멈추게 되면 보정이 안 된 상황이기 때문에 제각각 다르게 위치를 파악하게 되고

    ▲ 멈추는 즉시 동기화하자니 지연에 따라 진도가 다르니, 그걸 맞추다보면 튀는 현상이 발생한다

    이 문제는 핑과도 연결이 되어있기도 했다. 핑이 안정적일 때는 보정할 내용은 없지만, 핑이 갑자기 좋아지거나 나빠졌을 때는 보정이 필요했다. 핑이 좋아지면 멈추라는 명령이 빨리 전달되어 멈춰야 되는 시점보다 더 빨리 멈추게 되고, 반대로 핑이 나쁘면 멈춰야될 위치에서 좀 더 간 다음에 그 명령이 전달되어 캐릭터가 정지하기 때문이었다.

    핑이 좋은 상태에서는 추가로 멈춰야 할 위치까지 이동하는 식으로 보정하는 건 큰 문제가 없지만, 문제는 캐릭터가 멈춰야 할 위치보다 더 갔을 때였다. 앞에 가있던 캐릭터를 강제로 당겨오는 식이 되는데, 그렇게 하면 게임플레이에서 어색함을 느낄 수밖에 없었다. 그렇다고 해서 그대로 멈추게 하자니, 보정이 될 수도 있고 안 될 수 있는 상황이었다.

    이 문제를 해결하기 위해서 개발팀은 핑이 나쁜 상황을 기준으로 보정하게끔 기준을 다시 잡았다. 예를 들어 다른 개체의 이동 요청을 120ms에서 받았다면, 마치 이를 200ms에 받은 것처럼 처리하는 식이었다. 이렇게 하면 보정은 과해지긴 하지만, 보정이 안 된 케이스는 거의 없어져서 일관성이 확보되는 셈이다.

    ▲ 갑작스런 정지 상황에 맞춰 보정할 수 있게끔 구간을 만들고, 핑이 나쁜 상황을 기준으로 보정하게끔 했다

    그러나 이렇게 하면 이동 중 오차가 더 커지는 문제가 있었다. 사람의 인지 범위 안에서 그 오차를 받아들일 수 있을 정도 수준에 멈췄을 때 안 맞는 상황을 피하기 위한 조치이긴 했지만, 이를 어떻게 더 정교하게 오차를 줄여나갈 수 있을지는 개발팀에서 지속적으로 연구 중에 있다.

    이러한 문제는 프라시아 전기뿐만 아니라, 네트워크를 활용하는 실시간 멀티플레이 게임에서는 필연적으로 발생하는 문제들이다. 이를 해결하기 위해 온라인 게임 개발자들은 다들 정도는 다르지만 '예측'을 활용하고 있다. 모든 정보를 알리는 방식으로 동기화하면 과다하게 트래픽이 올라가거나, 그래서 반응성이 늦어지는 등 오류들이 발생하기 때문이다. 그래서 시간의 흐름에 따른 상태를 계산해낼 수 있는 일부 상태만 알림을 통해 동기화하고 나머지는 정해진 규칙에 따라 현재의 상태를 도출하는 방식으로 진행된다.

    그러나 네트워크를 통하다 보면 예측 못한 외부 요인으로 주요 상태가 변경됐을 때 어느 한쪽에서 늦게 알게 되는 일이 있다. 이를 보정을 거쳐 맞춰주는 작업이 필요하다. 그 예측이 얼마나 정확하고 안정적이고, 보정이 자연스럽게 되느냐가 온라인 게임에서 자연스러운 플레이의 완성도를 좌우하는 중요한 포인트 중 하나인 셈이다.