로그인

회원가입 | ID/PW 찾기

NDC

[NDC22] 넥슨 '프로젝트 매그넘' 어떻게 개발되고 있나요?

SPICA를 사용한 서버 부하 줄이기

에 유통된 기사입니다.
김승주(4랑해요) 2022-06-09 17:00:48
넥슨의 루트 슈터 게임 <프로젝트 매그넘>은 어떤 개발 과정을 거치고 있을까?

<프로젝트 매그넘>은 언리얼 엔진으로 개발되고 있다. 언리얼 엔진의 데디케이티드 서버를 사용할 때, PvE 게임에서는 유저수 대비 몬스터수가 많게 되면 서버 연산량이 높아 서버가 받을 수 있는 유저의 수가 적어져 실 서비스가 불가능해지는 문제가 있다.

이 문제를 해결하고자 개발진은 서버의 연산을 클라이언트가 위임하는 SPICA를 개발해 NDC21에서 소개한 바 있다. 그리고 NDC21에서는 <프로젝트 매그넘>에 SPICA를 적용하는 과정과, 당시 생겼던 이슈의 해결책을 공유하고 결과를 보여주는 자리를 마련했다.

장주한 개발자는 해당 강연을 통해 "데디케이티드 서버 최적화의 새로운 해결책을 보여주며, 최적화 및 대규모 처리를 해야 하는 비슷한 문제에 직면한 분들에게 유용한 정보가 되었으면 한다."라고 전했다.

 


강연자 : 장주한

 

소속 : 넥슨게임즈

 

발표자 소개

현재 넥슨게임즈에서 루트 슈터 장르인 매그넘 프로젝트의 서버를 담당하고 있으며, 주로 서버 아키텍쳐 개발 및 언리얼 엔진 최적화 관련 업무를 수행하고 있습니다. 이전에는 엔씨소프트의 리니지2의 서버 개발, 넥슨게임즈의 V4 서버 개발을 담당한 바 있습니다.

 

 

# <프로젝트 매그넘>은 어떤 게임?

 

강연 내용으로 들어가기 전에 <프로젝트 매그넘>이 어떤 게임인지부터 알아보도록 하자.


<프로젝트 매그넘>은 2021년 8월 진행된 ''NEXON New Projects : 미디어 쇼케이스’에서 공개된 게임이다. <히트>, <V4> 등으로 알려진 넷게임즈(현 넥슨게임즈)가 개발을 맡았으며, 슈팅에 RPG 요소를 결합한 '루트 슈터' 장르를 표방했다. 대표적인 루트 슈터 장르 게임으로는 <데스티니> 시리즈가 있다.

 


 

<프로젝트 매그넘>은 SF 스타일 판타지 세계관을 배경으로 하며, 정체를 알 수 없는 기계 거미나 대형 거대 로봇이 등장해 플레이어를 위협한다. 트레일러에서는 와이어를 통한 액션이 공개되었으며, 향후에도 다양한 스킬과 액션, 총기가 등장할 수 있음이 예고됐다.

또한, 루트 슈터는 대규모의 적과 맞서는 액션과 아이템 파밍 요소가 중요하기에 유저 클라이언트와 서버 간의 최적화가 중요하게 여겨진다. 과도한 연산으로 서버 최적화에 문제가 생기면 '렉'이 걸리거나, 복잡한 스킬의 대미지 공식이 제대로 처리되지 않아 처리 지연이 발생할 가능성이 있다.

해당 강연은 SPICA 프로그램을 통해 이러한 난관을 해결하기 위해 어떤 시도가 있었는지 설명했다. 아래부터는 강연 내용을 요약한 것이다.

 

<프로젝트 매그넘>

 

 

# SPICA를 만들었던 이유

 

참고자료 : SPICA UE4에서 대규모 몬스터가 나오는 PvE 게임을 위한 하이브리드 데디케이티드 서버

 

먼저, SPICA가 만들어진 상황의 이해를 돕기 위해 지난 NDC21에서의 강연이 짧게 요약됐다.

<프로젝트 매그넘>은 FPS와 RPG가 혼합된 루트 슈터 장르 게임이다. 많은 몬스터가 등장하기에 빠른 반응성과 정교한 액션, 많은 물량을 보이기 위해 서버에서 연산을 많이 해야 했다. 많은 유저를 한 서버에 받아야 하기에 연산은 더욱 필요했고, 계산 결과 데디케이트 프레임이 1fps도 나오지 않는 상황이었다.

가장 큰 문제가 무엇인지 파악한 결과 대규모 몬스터가 원인이었다. 문제를 해결하고자 서버의 일을 클라이언트에 나눠 처리하는 시스템을 고안하였고, 서버가 클라이언트와 하나인 것처럼 동작하는 SPICA를 만들어 NDC21에서 소개했다.

 


 

 

# 그 후에 무슨 일이?

 

당초 <프로젝트 매그넘>에 일부 적용될 예정이었던 SPICA는 전체 몬스터에 적용되기로 변경됐다.

SPICA는 2019년 개발됐다. 2020년 초에는 <프로젝트 매그넘>에 적용이 가능한지 테스트가 진행됐고, 이후 게임 엔진이나 스케쥴러 같은 시스템을 확장하는 데 집중했다. SPICA를 <프로젝트 매그넘>에 적용하기보단 대규모 몬스터가 등장하는 콘텐츠 추가 후 적용될 예정이었다.

그러나 2021년 큰 변화가 생겼다. FGT(포커스 그룹 테스트) 준비를 위해 서버 머신 스펙을 정해야 했다. 4명의 유저로 데디케이트 서버 프로파일링을 진행한 결과 월드 지연 시간이 약 20~48ms 정도가 나왔다. 이전에 공개했던 <프로젝트 매그넘>의 월드틱 목표는 2.66ms였다. 약 17배 이상의 최적화가 필요한 상황.


그렇기에 두 가지의 최적화 방식을 적용하기로 결정했다. 첫 번째는 프로파일 결과를 분석해 불필요한 부분이나 다른 방식으로 바꿀 수 있는 부분을 하나 하나씩 줄이는 데디케이트 서버 최적화 방식이었고, 두 번째는 SPICA를 기본으로 사용하는 방식이었다. 이 결정으로 인해 SPICA는 대규모 몬스터를 위한 시스템에서 모든 몬스터에 적용되는 시스템이 되었다.

SPICA를 사용함으로써 서버에서 사라지게 할 수 있는 연산은 몬스터의 틱 처리 부분, 몬스터의 길 찾기에 사용하는 EQS, 몬스터 상태 동기화를 위한 리플리케이션 등이 있다. 서버 부담을 크게 덜 수 있다.

 

 

 

# SPICA 실제 적용기

 

다음은 <프로젝트 매그넘>에서 SPICA가 동작하는 과정과, 적용 과정에서 발생한 일이다.

먼저 새로운 클라이언트가 서버에 접속하면, 접속한 클라이언트의 SPICA 네트워크를 요청한다. 요청에 따라 SPICA 네트워크가 준비되고, 서버에서 접속을 시도한 후 성공하면 다른 클라이언트도 접속을 시도하게 된다. 

모든 클라이언트가 접속을 성공하면 해당 클라이언트는 호스트 클라이언트가 되는데, 개발망에서 테스트할 당시에는 문제가 없었으나 애저에 서버를 올린 후부터는 SPICA 네트워크를 구축할 수 없는 문제가 생겼다. 가정용 공유기 문제로 포트가 열리지 않는 일이 발생했기 때문이다.

이를 해결하고자 '홀펀칭'(STUN)을 구현했다. 홀펀칭은 포트가 열려 있지 않은 상황에서 클라이언트가 연결을 시도할 때 내부에서 먼저 클라이언트로 패킷을 보내 공유기의 문을 일시적으로 열어, 외부에서 해당되는 문을 통해 접속할 수 있는 방벙을 말한다. 서로 간의 정보가 필요하기에 데디케이트 서버가 STUN 서버가 되어 정보를 공유한다. 


환경에 따라 안 되는 경우가 있기도 하기에 백업 플랜으로 릴레이 서버를 구축하는 것이 일반적이다. 다만, 릴레이 서버는 서버의 부담을 가중시키기에 <프로젝트 매그넘>에는 고려되지 않았다.

포트 개방이나 홀펀칭을 사용해 서버와 모든 클라이언트의 연결에 성공하면 해당 클라이언트는 호스트 클라이언트가 된다. 모든 클라이언트가 성공한다면 전부 호스트가 될 수 있다.

이제 접속을 하고 이동하다 보면 몬스터를 마주치게 된다. 서버에서 연산 중인 몬스터를 호스트에게 넘기는 행위를 '위임'이라 하고, 이를 반환하면 '반환'이다. <프로젝트 매그넘>은 필드에서 여러 미션을 각각 진행하기 때문에 호스트가 아무 몬스터를 위임하면 안 된다. 따라서 호스트의 시야 범위 안에 몬스터가 들어올 때 위임해 주기로 했다. 이를 위해 시그니피컨스 매니저 기법이 사용됐다.



위임은 세 단계로 진행된다. 서버에서 위임이 요청을 보내며 데이터를 생성하고 연산을 정지한다. 오너쉽까지 제거한 후 생성된 데이터를 호스트에게 전달하며, 호스트는 해당된 데이터로 정보를 업데이트하고 오너쉽을 획득한 후에 연산을 시작하고 완료를 통보한다. 서버가 위임 완료 처리를 하면 위임이 완료된다. 반환도 비슷한 과정으로 전개된다. 만약 연결이 끊기면 주기적으로 서버로 전달된 백업 데이터를 토대로 처리를 진행한다.

네트워크로 전달하는 두 가지가 있는데, 위임/반환을 할 때 전달하는 데이터와 주기적으로 전달하는 위임 액터의 백업 데이터다. 이 데이터로 인해 네트워크 부하가 생길 수 있어 데이터 최적화를 진행했다. 최적화는 NetCache와 Block Update 구현을 통해 이루어졌다. 이렇게 최소 50%에서 99.7%까지의 데이터 최적화가 이루어졌다.


다음은 발사체 생성이다. 총을 들고 있는 몬스터가 공격을 하는 경우에는 이펙트만 표시하면 돼 큰 문제가 없었다. 그러나 몬스터가 런처류를 발사하면 발사체가 생성되고 이동하는 과정이 필요한데, 위임된 몬스터가 런쳐를 발사하면 SPICA에서 클라이언트 생성을 막아 미사일이 생성되지 못했다. 클라이언트 생성이 막혀 있던 이유는 SPICA를 최초 개발할 때 보안 이슈를 막기 위해 그렇게 설계됐기 때문이다.

문제를 해결하고자 처음에는 서버 생성을 요청하는 방식으로 만들었다. 그러나 서버에 요청을 보내는 시간만큼의 딜레이가 생기고, 서버에 직접 생성해야 되기 때문에 연산 비용이 증가하는 문제가 있었다. 대신, 클라이언트에서 이를 생성하고 서버에서 검증하는 식으로 구성됐다. 허용되지 않는 클라이언트 생성일 경우에는 서버에서 해당 클라이언트의 연결을 끊도록 해 보안 문제도 신경 썼다.


다음은 몬스터를 처치하는 과정이다. SPICA를 사용하지 않은 상태에서의 전투를 설명하면 서버에서 피격을 판정한다. 이렇게 맞게 되면 시전자의 스텟을 통해 대미지를 계산하며, 피격자는 자신의 스텟을 통해 다시 대미지를 계산한다. 이후에 상태를 업데이트한다.

SPICA를 사용해 해당 과정을 진행할 경우에는 앞선 문제처럼 맞아도 대미지가 발생하지 않는다. 위임된 몬스터의 오너십이 서버에 없기 때문에 피격자 처리가 진행되지 않기 때문이다. 해당 문제는 서버 RPC를 미리 활용해 해결할 준비를 해 놓았다.

서버 RPC는 액터의 오너십을 가진 곳에서 실행되게 하는 것으로, 서버 오너십이면 서버에서 실행되고 호스트 오너십이면 호스트 오너십에서 실행된다. 그렇기에 시전자와 피격자 사이를 서버 RPC로 변경하면 피격자가 서버 오너십이면 서버에서 처리되고, 호스트 오너십이면 호스트에서 처리가 가능해진다.

하지만, 스킬에서 문제가 발생했다. 가령 '견인 수류탄'은 주변의 몬스터를 일정 시간 동안 폭발 위치로 당겨 오는 무기다. 그렇기에 구조가 복잡해 RPC로 변경해야 할 부분이 많았고, 일정 시간 동안 몬스터를 당겨야 하기에 몬스터의 수 x RPC의 수만큼 주기적으로 호출돼 서버 부하를 증가시킬 가능성이 높았다. 게다가 <프로젝트 매그넘>에는 더욱 다양하고 복잡한 스킬이 존재하고, 이에 대한 모든 RPC 전환은 무리라고 판단하게 됐다.


이를 해결하기 위해 위임 없이 서버에서 처리하자는 생각과, SPICA의 호스트 클라이언트의 연결이 끊어지면 서버에서 이를 감지해 위임된 몬스터를 반환하여 처리하는 기능을 응용하자는 생각을 하게 됐다. 그 결과 서버에서 즉시 반환해서 처리하는 'Fast Return'을 구현하게 됐다.

'Fast Return'은 RPC로 전환하기 어려운 스킬을 서버로 즉시 반환하여 처리하는 기능이다. 서버의 부하는 증가하겠지만, 전체를 보면 소수이고 전투 중인 몬스터는 몇 초 안에 사망하기에 크게 문제가 없으리라 판단했다.

하지만, 문제는 또다시 발생했다. 이를 이해하기 위해서는 패스트 리턴과 반환의 차이를 알아야 한다. 반환은 서버에서 반환 요청을 보내면 호스트에서 자신이 처리하고 있는 오너쉽을 제거한다. 그렇기에 서버와 호스트 둘 다 오너쉽이 없는 상황이 잠시 발생한다. 반면 Fast Return은 발생 시점으로 서버가 즉시 오너십을 가져감으로써 서버와 호스트 둘 다 오너쉽을 가진 상태가 존재하게 된다.


이 구간에서는 서버와 호스트가 각각 연산을 하기 때문에 연산이 동일할 수 없어 불일치가 발생한다. 이러한 불일치는 '다이버전스'라 하며 두 가지 상황으로 나뉜다. 첫 경우는 서버에서 호스트로 패킷을 보낼 때 서버에서 Fast Return이 일어나면, 전달된 패킷을 처리하는 과정에서 둘의 데이터가 달라져 발생한다. 두 번째는 호스트에 연산된 결과를 서버가 반영하려 할 때 서버가 이미 오너십을 가지고 있어 반영이 되지 못하고 데이터가 달라져 발생한다.

다이버전스는 두 가지 네트워크 라인이 있어 발생하는 문제기에, 네트워크 라인을 하나로 만들고 강제로 패킷의 오더를 맞추는 등 여러 작업을 진행해 해결했다. 즉시 반환 시점의 서버 액터를 기준으로 처리하고, 서버에서 보냈지만 처리되지 못한 패킷은 서버에서 처리하고, 이후의 호스트 데이터를 무시하고 서버가 호스트로 강제로 데이터를 보내는 것이다.

Fast Return의 성능 측정 결과 부담도 8.7 마이크로세컨드 정도밖에 되지 않아 부담 없이 사용할 수 있었다. 결과적으로 RPC로의 변경과 Fast Return을 통해 SPICA의 동작이 가능해진 셈이다.


SPICA 1.0은 <프로젝트 매그넘>에 적용된다. 테스트 결과 SPICA의 사용 유무에 따라 몬스터 100마리를 소환했을 때 서버 성능이 3.9배에서 4.6배까지 향상되는 것을 확인할 수 있었다. 필드에서도 몬스터당 효율로 계산할 시 7.48배의 효율이 발생했다.

장주한 개발자는 이런 과정을 통해 기존에 없는 것이라도 포기하지 말고 시도하라는 말을 전하고 싶었다고 설명했다. SPICA를 개발할 당시에도 이러한 시스템이 가능한지 의문이 있었으나, <매그넘 프로젝트>로 적용하는 과정을 통해 충분히 가능하다고 생각하게 되었다. 

플러그인이나 프레임워크 구현 시에 실제 프로젝트에 적용해 보며 보완해 나가는 과정 또한 중요하다고 전했다. 디버깅 코드나 로그를 과하게 넣었던 것이 다이버전스를 발견할 때 유용하게 활용됐다고 언급하기도 했다.

 



 

최신목록 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10