언리얼 엔진을 활용한 멀티 플레이를 구현하기 위해 학습 하던 중, 리슨서버 및 데디케이티드 서버에 대해 학습하였습니다.

해당 과정에서 언리얼 엔진에서 제공하는 리슨서버 및 데디케이티드 서버의 특징, 차이점들을 작성하며

그 외 P2P 서버 및 클라우드 서버 등에서도 간략하게 알아보겠습니다.

 

 

멀티플레이 (MultiPlay)

  • 여러 플레이어가 네트워크를 통해 같은 게임 월드에서 상호작용 할 수 있도록 구현하는 시스템
  • 서버 - 클라이언트 구조로 이루어져있다.
  • 언리얼 엔진 내 리플리케이션, 세션을 활용하여 동작한다.
    • 서버 (Server) : 게임 상태 관리
      • 여러 클라이언트와 상호작용
      • 클라이언트에서 해킹당하면 안되는 데이터에 대한 처리
      • 플레이어의 상태 관리
    • 클라이언트 (Client) : 서버에서 관리하는 데이터를 가져와 게임을 플레이하는 방식
    • 리플리케이션(Replication) : 서버의 정보를 클라이언트에 동기화하는 기능
    • 세션 (Session) : 멀티플레이 게임에서 클라이언트들이 연결되는 로비 개념

 

리슨서버 (Listen Server)

  • 한 플레이어가 직접 서버 역할을 하며 동시에 클라이언트를 수행하는 방식
    • Player1 = Server + Client
    • Player2,3,4... = Client
  • 멀티플레이 관련 설정이 다른 서버 연결방식보다 쉽다.
  • 별도의 서버 운영이 필요 없으며, 서버 운영 비용이 발생하지 않는다.
  • 서버 호스트가 게임을 종료하면, 모든 플레이어가 해당 세션에서 종료된다.
  • 서버 호스트 PC성능에 비례하여 네트워크 성능이 저하 될 수 있다.
  • 보안에 취약하다.
    • 리슨서버는 게임 데이터를 노출시키는 형식. 데이터를 쉽게 조작 할 수 있다.
    • 클라이언트가 서버를 운영하는 방식이기 때문에 데이터를 조작하더라도 감지가 어렵다.
    • UFUNCTION(WithValidation)을 사용한 보안 강화 가능.
    • 클라우드 서버 환경에서는 토큰과 같은 보안방식을 사용하여 보안을 강화시킬 수 있다.

데디케이티드서버 (Dedicated Server)

  • 게임을 플레이하지 않는 독립적인 서버 존재, 클라이언트가 해당 서버에 접속하는 방식
  • 서버는 게임 상태 및 데이터를 관리, 클라이언트는 서버의 데이터를 받아온다.
  • 고정된 네트워크 환경에서 실행되므로 안정성이 뛰어나다.
  • 리슨서버와 다르게 호스트가 종료를 해도 게임이 중단되지 않는다.
  • 독립적인 서버를 통한 게임 데이터를 캡슐화 할 수 있다.
  • 별도 서버 운영 비용이 발생하며, 서버 유지 보수가 필요하다.
  • 고정된 서버 개수로 인해 접속자가 급등하거나 급락할 경우 서버 운영에 문제가 발생한다.

클라우드 서버 (Cloud Server)

AWS GameLift - https://aws.amazon.com/ko/blogs/korea/introducing-amazon-gamelift-anywhere-run-your-game-servers-on-your-own-infrastructure/

  • 네트워크를 통해 접근할 수 있는 가상 서버
  • 현재 게임 회사들이 가장 많이 사용하는 형태
  • 필요할 때만 서버를 생성하는 OnDemand Server 방식을 통해 서버 운영 비용을 절감할 수 있다.
  • AWS, SnowFlake, Azure 등의 클라우드 서비스를 통해 운영
  • 클라이언트 접속자가 급등하더라도 Auto Scaling기능을 통한 안전한 서버 운영 가능
  • 지역별 서버를 배포하므로 글로벌 서버의 경우에도 용이하다.
  • 클라우드 서비스 내 보안 시스템을 사용한 보안 기능을 강화시킬 수 있다.
    • AWS 모니터링, AWS AccessKey 등
  • 서버에 문제가 발생시 별도의 독립된 서버를 통해 모니터링, 프로파일링을 통해 빠른 복구가 가능하다.

 

게임 서버 품질을 보장하는 4가지

1. 안정성 (Stability)

  • 게임 서버가 얼마나 다운되지 않는가. (인듀어 테스트를 통한 검증)
  • 게임 서버가 얼마나 오작동을 하지 않는가.

2. 확장성 (Scalability)

  • 서버를 얼마나 많이 설치할 수 있는지
  • 사용자 수가 늘어나더라도 서비스 품질이 떨어지지 않고 유지되는지
    • 수직적 확장 방법 (Scale Up) : CPU,RAM 같은 서버 머신 부품 업그레이드
    • 수평적 확장 방법 (Scale Out) : 서버 머신의 개수 증설
    • 해당 방법은 데디케이티드 서버일 경우에 대한 방법. 클라우드 서비스에서는 Auto Scaling을 통한 자동 증설기능

3. 성능 (Performance)

  • 얼마나 빠르게 처리되는지
  • 게임 장르에 따른레이턴시(Latency) 고려
  • 코드 및 알고리즘 최적화
  • 서버 과부화 영역 분산
    • Code Profiling을 통한 함수처리 시간 확인, 개선
  • 네트워크 프로토콜 최적화
    • 메시지 양 줄이기 (ZLib, 양자화 등)

4. 관리 편의성

  • 백그라운드 프로세스에서도 프로그램이 실행되는지
    • 윈도우 : 서비스 / 리눅스 : 데몬

 

안정성을 고려한 서버 개발 방법

  • 치밀한 개발 및 단위테스트
    • 모든 함수 호출의 반환값을 반드시 체크하는 루틴
    • 자동화가 구현되어있는 자가 검증 (단위테스트, Unit Test)
  • 80 : 20법칙 유지
    • 성능의 80%는 20%의 소스 코드에서 나타난다는 파레토 법칙
    • 구조가 복잡해지더라도 성능 최적화 및 유지보수하기 쉬운 단순한 구조 방식 개발
  • 1인 이상의 코드리뷰
    • 코드리뷰를 통한 지식 공유, 버그 발견
  • 가정하지 말고 검증하기
    • 봇 테스트, 더미 클라이언트 테스트, 스트레스 테스트를 통한 검증
      • 입력 처리, 렌더링 과정이 생략된 프로그래밍된 행동을 반복하는 더미를 서버에 접속
      • 서버 성능 프로파일링을 통해 지표 확인
  • 불안정시 극복 과정
    • 서버가 다운되더라도 최대한 빠르게 복구
      • 서버 프로세스 중단시, 자동으로 복구되는 프로그램 설계
      • AWS 내 모니터링 시스템을 통한 자동 복구 프로그램 설계 가능
    • 서버가 다운되더라도 최대한 적은 서비스만 다운되게 설계
      • 서버 프로세스 분리를 통한 서버 장애 발생시에도 일부 서비스는 작동할 수 있는 설계
    • 서버 오작동에 대한 로깅하기

출처 및 참고내역

 

게임 서버 프로그래밍 교과서

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/networking-and-multiplayer-in-unreal-engine

https://unrealcommunity.wiki/linux-quickstart-faqs-8f7980

https://aws.amazon.com/ko/blogs/korea/introducing-amazon-gamelift-anywhere-run-your-game-servers-on-your-own-infrastructure/

'Unreal Engine > 네트워크' 카테고리의 다른 글

[UE5] - 리플리케이션 (Replication)  (0) 2025.02.04

토이프로젝트를 준비하며 프로젝트 설계시 고려해야하는 부분이 여러가지 있었습니다.

객체 관리, 게임모드, UI 등등 다양한 부분에서 설계를 해야했지만, 게임 장르 및 플레이 타입에 대해 가장 먼저 고민하게 되었습니다.

그 중 멀티플레이를 목적으로한 프로젝트 개발을 결정하게 되었으며, 멀티플레이 환경에서 서버-클라이언트간 어떻게

데이터를 처리하는지에 대해 알아보며 언리얼의 RPC, 리플리케이션, POD 등 다양한 용어들을 학습하게 되었습니다.

그 중 가장 멀티플레이 환경에서 데이터를 동기화하는 방법인 리플리케이션에 대해 알아보도록 하겠습니다.

 

리플리케이션 (Replication)

  • 멀티플레이어 환경을 구축할 때 서버와 클라이언트 간의 데이터를 동기화 하는 기능
  • 서버가 권한(Server Authority)을 가지며, 이를 기반으로 리플리케이션 시스템 사용
    • 게임 서버가 진짜 상태를 결정하고, 이를 클라이언트에 전송하는 방식
    • Ex) Player1 이동 -> 서버 : 이동에 대한 결과 -> Player 2,3,4... 에게 반영 (동기화)
    • 객체의 속성, 위치, 애니메이션 등 필요한 정보를 클라이언트에 전송
    • 클라이언트는 서버의 정보를 기반으로 화면을 업데이트 한다.
    • 해당 과정을 통해 중요한 게임 로직은 서버에서 실행되며, 클라이언트들은 서버에서 데이터를 받아 로컬에서 표시하는 역할을 한다.
  • 리플리케이션은 액터(Actor)를 기준으로  실행된다. 
  • 리플리케이션 대상은 Object, Component, Property, Function이 될 수 있다.
    • Object : 캐릭터, 아이템, 차량 등
    • Component : Mesh, Audio, Collision 등
    • Property : 객체의 위치, 속도, 체력, 점수 등
    • Function(RPC) : 문열기, 공격 이벤트, 총 발사
  • RPC : 데이터 통신
  • Replicated, Replicated Notify : 데이터 복제

 

리플리케이션 설정 방법 ,종류

 

1. 변수 리플리케이션 (Property Replication)

  • UPROPERTY(Replicated) 설정
  • GetLifetimeReplicateProps 함수 내 리플리케이션 변수 등록
  • Replicated Notify 설정

 

// UPROPERTY Replicated

UPROPERTY(Replicated)
int32 PlayerHealth;

// GetLifetimeReplicatedProps

void AMyCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    DOREPLIFETIME(AMyCharacter, PlayerHealth);
}

// Rep Notify
UPROPERTY(ReplicatedUsing = OnRep_PlayerHealth)
int32 PlayerHealth;

UFUNCTION()
void OnRep_PlayerHealth()
{
    // 체력 값이 변경될 때 실행할 로직
}

 

 

2. 함수 리플리케이션 (Func Replication) / RPC(Remote Procedure Call)

  • UFUNCTION(Server/Client/Multicast, Reliable)
    • Server : 서버에서만 실행. (Client -> Server)
      • 공격 요청, 스킬 사용 등의 로직
    • Client : 클라이언트에서만 실행. (Server -> Target Client)
      • HUD 업데이트
    • MultiCast : 서버에서 호출, 모든 클라이언트에 실행 (Server -> All Client)
      • 폭발 이벡트, 애니메이션 재생, 게임 결과 등의 로직
// Server RPC
UFUNCTION(Server, Reliable, WithValidation)
void ServerFire();

// Client RPC
UFUNCTION(NetMulticast, Reliable)
void MulticastExplosion();

// Multicast RPC
UFUNCTION(Client, Reliable)
void ClientShowHUD();

 

 

 

3. 액터 리플리케이션

  • 생성자 { bReplicates = true; , SetReplicateMovement(true);}
    • bReplicates = false시 모든 플레이어가 권한(Authority)를 가지게 되며, 플레이어 1이 이동시 다른 플레이어들도 이동한다.
    • 해당 액터의 Movement를 Replicated하게 해준다.

액터 스폰시 SetReplicates(true);

 

// Constructor Replicated Settings
AMyActor::AMyActor()
{
    bReplicates = true; // 서버가 Authority를 가지게 한다. 서버에 정보를 알리고 모든 Client에 전파할 수 있다.
    SetReplicateMovement(true)  // 해당 액터의 Movement를 Replicated한다.
}

// 액터 스폰시 Replicated
AYourActor::Func()
{
    AMyActor* SpawnedActor = GetWorld()->SpawnActor<AMyActor>(MyActorClass, SpawnLocation, SpawnRotation);
    SpawnedActor->SetReplicates(true);
}

 

 

 

Replicated VS Replicated Notify VS RPC

기능 Replicated Replicated Notify (RepNotify) RPC (Remote Procedure Call)
설명 동기화를 통한 데이터 복제 복제 후 특정 시점에 지정한 함수 호출 즉시 함수 호출, 통신 방식
데이터
변경 방식
서버에서 변경하면 클라이언트가 자동으로 반영 서버에서 변경하면 클라이언트가 반영 + 추가 함수 실행 클라이언트 또는 서버에서 직접 함수 실행
변경 감지 기능   복제된 시점에서OnRep_Func() 호출  
동기화
시점
서버에서 변경되면 다음 네트워크 업데이트 시 자동 동기화 서버에서 변경되면 다음 네트워크 업데이트 시 자동 동기화 후 함수 실행 함수가 호출되는 즉시
사용 예시 플레이어 체력, 점수, 탄약 개수 등 체력 변경 시 UI 업데이트, 특수 효과 실행 공격 실행, 문 열기,
이펙트 재생

 

+ Recent posts